<commit_before>#include "ModernGL.hpp"

#include "OpenGL.hpp"

PyObject * NewFramebuffer(PyObject * self, PyObject * args, PyObject * kwargs) {
	int width = 0;
	int height = 0;
	int colors = 1;
	bool depth = true;

	static const char * kwlist[] = {"width", "height", "colors", "depth", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiip:NewFramebuffer", (char **)kwlist, &width, &height, &colors, &depth)) {
		return 0;
	}

	if (!width && !height) {
		width = activeViewportWidth;
		height = activeViewportHeight;
	}

	CHECK_AND_REPORT_ARG_VALUE_ERROR(width < 1, "width", width);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(height < 1, "height", height);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(colors < 0 || colors > 8, "colors", colors);

	int framebuffer = 0;
	OpenGL::glGenFramebuffers(1, (OpenGL::GLuint *)&framebuffer);
	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, framebuffer);

	int depthTex = 0;
	OpenGL::glGenTextures(1, (OpenGL::GLuint *)&depthTex);
	OpenGL::glBindTexture(OpenGL::GL_TEXTURE_2D, depthTex);
	OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MIN_FILTER, OpenGL::GL_LINEAR);
	OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MAG_FILTER, OpenGL::GL_LINEAR);
	OpenGL::glTexImage2D(OpenGL::GL_TEXTURE_2D, 0, OpenGL::GL_DEPTH_COMPONENT, width, height, 0, OpenGL::GL_DEPTH_COMPONENT, OpenGL::GL_FLOAT, 0);
	OpenGL::glFramebufferTexture2D(OpenGL::GL_FRAMEBUFFER, OpenGL::GL_DEPTH_ATTACHMENT, OpenGL::GL_TEXTURE_2D, depthTex, 0);

	int colorTex[8] = {};
	OpenGL::glGenTextures(colors, (OpenGL::GLuint *)colorTex);
	for (int i = 0; i < colors; ++i) {
		OpenGL::glBindTexture(OpenGL::GL_TEXTURE_2D, colorTex);
		OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MIN_FILTER, OpenGL::GL_LINEAR);
		OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MAG_FILTER, OpenGL::GL_LINEAR);
		OpenGL::glTexImage2D(OpenGL::GL_TEXTURE_2D, 0, OpenGL::GL_RGBA, width, height, 0, OpenGL::GL_RGBA, OpenGL::GL_FLOAT, 0);
		OpenGL::glFramebufferTexture2D(OpenGL::GL_FRAMEBUFFER, OpenGL::GL_COLOR_ATTACHMENT0 + i, OpenGL::GL_TEXTURE_2D, colorTex, 0);
	}

	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, defaultFramebuffer);

	PyObject * tuple = PyTuple_New(2 + colors);
	PyTuple_SET_ITEM(tuple, 0, CreateFramebufferType(framebuffer, colorTex, depthTex));
	for (int i = 0; i < colors; ++i) {
		PyObject * colorTexture = CreateTextureType(colorTex[i], width, height, 4);
		PyTuple_SET_ITEM(tuple, i + 1, colorTexture);
	}
	PyTuple_SET_ITEM(tuple, colors + 1, CreateTextureType(depthTex, width, height, 1));

	return tuple;
}

PyObject * DeleteFramebuffer(PyObject * self, PyObject * args) {
	Framebuffer * fbo;

	if (!PyArg_ParseTuple(args, "O:DeleteFramebuffer", &fbo)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_TYPE_ERROR("fbo", fbo, FramebufferType);

	OpenGL::glDeleteFramebuffers(1, (OpenGL::GLuint *)&fbo->fbo);
	OpenGL::glDeleteTextures(1, (OpenGL::GLuint *)&fbo->color);
	OpenGL::glDeleteTextures(1, (OpenGL::GLuint *)&fbo->depth);
	Py_RETURN_NONE;
}

PyObject * UseFramebuffer(PyObject * self, PyObject * args) {
	Framebuffer * fbo;

	if (!PyArg_ParseTuple(args, "O:UseFramebuffer", &fbo)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_TYPE_ERROR("fbo", fbo, FramebufferType);

	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, fbo->fbo);
	activeProgram = fbo->fbo;
	Py_RETURN_NONE;
}

PyObject * GetDefaultFramebuffer(PyObject * self) {
	OpenGL::glGetIntegerv(OpenGL::GL_DRAW_FRAMEBUFFER_BINDING, (OpenGL::GLint *)&defaultFramebuffer);
	Py_RETURN_NONE;
}

PyObject * UseDefaultFramebuffer(PyObject * self) {
	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, defaultFramebuffer);
	Py_RETURN_NONE;
}

PyObject * ReadPixels(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;
	int width;
	int height;
	int components = 3;

	static const char * kwlist[] = {"x", "y", "width", "height", "components", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii|i:ReadPixels", (char **)kwlist, &x, &y, &width, &height, &components)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_VALUE_ERROR(width < 1, "width", width);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(height < 1, "height", height);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(components < 1 || components > 4, "components", components);

	int size = height * ((width * components + 3) & ~3);

	const int formats[] = {0, OpenGL::GL_RED, OpenGL::GL_RG, OpenGL::GL_RGB, OpenGL::GL_RGBA};
	int format = formats[components];

	PyObject * bytes = PyBytes_FromStringAndSize(0, size);
	char * data = PyBytes_AS_STRING(bytes);

	OpenGL::glReadPixels(x, y, width, height, format, OpenGL::GL_UNSIGNED_BYTE, data);
	data[size] = 0;

	return bytes;
}

PyObject * ReadDepthPixels(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;
	int width;
	int height;

	static const char * kwlist[] = {"x", "y", "width", "height", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii:ReadDepthPixels", (char **)kwlist, &x, &y, &width, &height)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_VALUE_ERROR(width < 1, "width", width);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(height < 1, "height", height);

	int size = height * height * 4;
	float * pixels = ModernGL::ReadDepthPixels(x, y, width, height);
	PyObject * data = PyBytes_FromStringAndSize((const char *)pixels, size);
	free(pixels);

	PyObject * bytes = PyBytes_FromStringAndSize(0, size);
	char * data = PyBytes_AS_STRING(bytes);
	OpenGL::glReadPixels(x, y, width, height, OpenGL::GL_DEPTH_COMPONENT, OpenGL::GL_FLOAT, data);
	data[size] = 0;

	return bytes;
}

PyObject * ReadPixel(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;

	static const char * kwlist[] = {"x", "y", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:ReadPixel", (char **)kwlist, &x, &y)) {
		return 0;
	}

	unsigned rgba = 0;
	OpenGL::glReadPixels(x, y, 1, 1, OpenGL::GL_RGBA, OpenGL::GL_UNSIGNED_BYTE, &rgba);
	return PyLong_FromUnsignedLong(rgba);
}

PyObject * ReadDepthPixel(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;

	static const char * kwlist[] = {"x", "y", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:ReadDepthPixel", (char **)kwlist, &x, &y)) {
		return 0;
	}

	float depth = 0.0;
	OpenGL::glReadPixels(x, y, 1, 1, OpenGL::GL_DEPTH_COMPONENT, OpenGL::GL_FLOAT, &depth);
	return PyFloat_FromDouble(depth);
}
<commit_msg>Revert "solved #6"<commit_after>#include "ModernGL.hpp"

#include "OpenGL.hpp"

PyObject * NewFramebuffer(PyObject * self, PyObject * args, PyObject * kwargs) {
	int width = 0;
	int height = 0;

	static const char * kwlist[] = {"width", "height", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:NewFramebuffer", (char **)kwlist, &width, &height)) {
		return 0;
	}

	int framebuffer = 0;
	int color = 0;
	int depth = 0;

	OpenGL::glGenFramebuffers(1, (OpenGL::GLuint *)&framebuffer);
	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, framebuffer);

	if (!width && !height) {
		width = activeViewportWidth;
		height = activeViewportHeight;
	}

	OpenGL::glGenTextures(1, (OpenGL::GLuint *)&color);
	OpenGL::glBindTexture(OpenGL::GL_TEXTURE_2D, color);

	OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MIN_FILTER, OpenGL::GL_LINEAR);
	OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MAG_FILTER, OpenGL::GL_LINEAR);
	OpenGL::glTexImage2D(OpenGL::GL_TEXTURE_2D, 0, OpenGL::GL_RGBA, width, height, 0, OpenGL::GL_RGBA, OpenGL::GL_FLOAT, 0);
	OpenGL::glFramebufferTexture2D(OpenGL::GL_FRAMEBUFFER, OpenGL::GL_COLOR_ATTACHMENT0, OpenGL::GL_TEXTURE_2D, color, 0);

	OpenGL::glGenTextures(1, (OpenGL::GLuint *)&depth);
	OpenGL::glBindTexture(OpenGL::GL_TEXTURE_2D, depth);
	OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MIN_FILTER, OpenGL::GL_LINEAR);
	OpenGL::glTexParameteri(OpenGL::GL_TEXTURE_2D, OpenGL::GL_TEXTURE_MAG_FILTER, OpenGL::GL_LINEAR);
	OpenGL::glTexImage2D(OpenGL::GL_TEXTURE_2D, 0, OpenGL::GL_DEPTH_COMPONENT, width, height, 0, OpenGL::GL_DEPTH_COMPONENT, OpenGL::GL_FLOAT, 0);
	OpenGL::glFramebufferTexture2D(OpenGL::GL_FRAMEBUFFER, OpenGL::GL_DEPTH_ATTACHMENT, OpenGL::GL_TEXTURE_2D, depth, 0);

	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, defaultFramebuffer);

	PyObject * fbo = CreateFramebufferType(framebuffer, color, depth);
	PyObject * colorTexture = CreateTextureType(color, width, height, 4);
	PyObject * depthTexture = CreateTextureType(depth, width, height, 1);

	return Py_BuildValue("OOO", fbo, colorTexture, depthTexture);
}

PyObject * DeleteFramebuffer(PyObject * self, PyObject * args) {
	Framebuffer * fbo;

	if (!PyArg_ParseTuple(args, "O:DeleteFramebuffer", &fbo)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_TYPE_ERROR("fbo", fbo, FramebufferType);

	OpenGL::glDeleteFramebuffers(1, (OpenGL::GLuint *)&fbo->fbo);
	OpenGL::glDeleteTextures(1, (OpenGL::GLuint *)&fbo->color);
	OpenGL::glDeleteTextures(1, (OpenGL::GLuint *)&fbo->depth);
	Py_RETURN_NONE;
}

PyObject * UseFramebuffer(PyObject * self, PyObject * args) {
	Framebuffer * fbo;

	if (!PyArg_ParseTuple(args, "O:UseFramebuffer", &fbo)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_TYPE_ERROR("fbo", fbo, FramebufferType);

	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, fbo->fbo);
	activeProgram = fbo->fbo;
	Py_RETURN_NONE;
}

PyObject * GetDefaultFramebuffer(PyObject * self) {
	OpenGL::glGetIntegerv(OpenGL::GL_DRAW_FRAMEBUFFER_BINDING, (OpenGL::GLint *)&defaultFramebuffer);
	Py_RETURN_NONE;
}

PyObject * UseDefaultFramebuffer(PyObject * self) {
	OpenGL::glBindFramebuffer(OpenGL::GL_FRAMEBUFFER, defaultFramebuffer);
	Py_RETURN_NONE;
}

PyObject * ReadPixels(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;
	int width;
	int height;
	int components = 3;

	static const char * kwlist[] = {"x", "y", "width", "height", "components", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii|i:ReadPixels", (char **)kwlist, &x, &y, &width, &height, &components)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_VALUE_ERROR(width < 1, "width", width);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(height < 1, "height", height);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(components < 1 || components > 4, "components", components);

	int size = height * ((width * components + 3) & ~3);

	const int formats[] = {0, OpenGL::GL_RED, OpenGL::GL_RG, OpenGL::GL_RGB, OpenGL::GL_RGBA};
	int format = formats[components];

	PyObject * bytes = PyBytes_FromStringAndSize(0, size);
	char * data = PyBytes_AS_STRING(bytes);

	OpenGL::glReadPixels(x, y, width, height, format, OpenGL::GL_UNSIGNED_BYTE, data);
	data[size] = 0;

	return bytes;
}

PyObject * ReadDepthPixels(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;
	int width;
	int height;

	static const char * kwlist[] = {"x", "y", "width", "height", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii:ReadDepthPixels", (char **)kwlist, &x, &y, &width, &height)) {
		return 0;
	}

	CHECK_AND_REPORT_ARG_VALUE_ERROR(width < 1, "width", width);
	CHECK_AND_REPORT_ARG_VALUE_ERROR(height < 1, "height", height);

	int size = height * height * 4;
	float * pixels = ModernGL::ReadDepthPixels(x, y, width, height);
	PyObject * data = PyBytes_FromStringAndSize((const char *)pixels, size);
	free(pixels);

	PyObject * bytes = PyBytes_FromStringAndSize(0, size);
	char * data = PyBytes_AS_STRING(bytes);
	OpenGL::glReadPixels(x, y, width, height, OpenGL::GL_DEPTH_COMPONENT, OpenGL::GL_FLOAT, data);
	data[size] = 0;

	return bytes;
}

PyObject * ReadPixel(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;

	static const char * kwlist[] = {"x", "y", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:ReadPixel", (char **)kwlist, &x, &y)) {
		return 0;
	}

	unsigned rgba = 0;
	OpenGL::glReadPixels(x, y, 1, 1, OpenGL::GL_RGBA, OpenGL::GL_UNSIGNED_BYTE, &rgba);
	return PyLong_FromUnsignedLong(rgba);
}

PyObject * ReadDepthPixel(PyObject * self, PyObject * args, PyObject * kwargs) {
	int x;
	int y;

	static const char * kwlist[] = {"x", "y", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:ReadDepthPixel", (char **)kwlist, &x, &y)) {
		return 0;
	}

	float depth = 0.0;
	OpenGL::glReadPixels(x, y, 1, 1, OpenGL::GL_DEPTH_COMPONENT, OpenGL::GL_FLOAT, &depth);
	return PyFloat_FromDouble(depth);
}
<|endoftext|>


<commit_before><commit_msg>String release first<commit_after><|endoftext|>


<commit_before>#include "databasecontroller.h"
#include "app.h"
#include <QtSql>
#include <QtConcurrent>

DatabaseController::DatabaseController(QObject *parent) :
	QObject(parent),
	multiThreaded(false),
	threadStore()
{
	QtConcurrent::run(this, &DatabaseController::initDatabase);
}

QUuid DatabaseController::createIdentity(const QUuid &deviceId)
{
	auto db = threadStore.localData().database();
	if(!db.transaction()) {
		qCritical() << "Failed to create transaction with error:"
					<< qPrintable(db.lastError().text());
		return {};
	}

	auto identity = QUuid::createUuid();

	QSqlQuery createIdentityQuery(db);
	createIdentityQuery.prepare(QStringLiteral("INSERT INTO users (identity) VALUES(?)"));
	createIdentityQuery.addBindValue(identity);
	if(!createIdentityQuery.exec()) {
		qCritical() << "Failed to add new user identity with error:"
					<< qPrintable(createIdentityQuery.lastError().text());
		db.rollback();
		return {};
	}

	QSqlQuery createDeviceQuery(db);
	createDeviceQuery.prepare(QStringLiteral("INSERT INTO devices (deviceid, userid) VALUES(?, ?)"));
	createDeviceQuery.addBindValue(deviceId);
	createDeviceQuery.addBindValue(identity);
	if(!createDeviceQuery.exec()) {
		qCritical() << "Failed to add new device with error:"
					<< qPrintable(createDeviceQuery.lastError().text());
		db.rollback();
		return {};
	}

	if(db.commit())
		return identity;
	else {
		qCritical() << "Failed to commit transaction with error:"
					<< qPrintable(db.lastError().text());
		return {};
	}
}

bool DatabaseController::identify(const QUuid &identity, const QUuid &deviceId)
{
	auto db = threadStore.localData().database();

	QSqlQuery identifyQuery(db);
	identifyQuery.prepare(QStringLiteral("SELECT EXISTS(SELECT identity FROM users WHERE identity = ?) AS exists"));
	identifyQuery.addBindValue(identity);
	if(!identifyQuery.exec() || !identifyQuery.first()) {
		qCritical() << "Failed to identify user with error:"
					<< qPrintable(identifyQuery.lastError().text());
		return false;
	}

	if(identifyQuery.value(0).toBool()) {
		QSqlQuery createDeviceQuery(db);
		createDeviceQuery.prepare(QStringLiteral("INSERT INTO devices (deviceid, userid) VALUES(?, ?) "
												 "ON CONFLICT DO NOTHING"));
		createDeviceQuery.addBindValue(deviceId);
		createDeviceQuery.addBindValue(identity);
		if(!createDeviceQuery.exec()) {
			qCritical() << "Failed to add (new) device with error:"
						<< qPrintable(createDeviceQuery.lastError().text());
			return false;
		} else
			return true;
	} else
		return false;
}

bool DatabaseController::save(const QUuid &userId, const QUuid &deviceId, const QString &type, const QString &key, const QJsonObject &object)
{
	auto db = threadStore.localData().database();
	if(!db.transaction()) {
		qCritical() << "Failed to create transaction with error:"
					<< qPrintable(db.lastError().text());
		return false;
	}

	//check if key exists
	QSqlQuery getIdQuery(db);
	getIdQuery.prepare(QStringLiteral("SELECT index FROM data WHERE userid = ? AND type = ? AND key = ?"));
	getIdQuery.addBindValue(userId);
	getIdQuery.addBindValue(type);
	getIdQuery.addBindValue(key);
	if(!getIdQuery.exec()) {
		qCritical() << "Failed to check if data exists with error:"
					<< qPrintable(getIdQuery.lastError().text());
		db.rollback();
		return false;
	}

	quint64 index = 0;
	if(getIdQuery.first()) {// if exists -> update
		index = getIdQuery.value(0).toULongLong();
		QSqlQuery updateQuery(db);
		updateQuery.prepare(QStringLiteral("UPDATE data SET data = ? WHERE index = ?"));
		updateQuery.addBindValue(jsonToString(object));
		updateQuery.addBindValue(index);
		if(!updateQuery.exec()) {
			qCritical() << "Failed to update data with error:"
						<< qPrintable(updateQuery.lastError().text());
			db.rollback();
			return false;
		}
	} else {// if not exists -> insert
		QSqlQuery insertQuery(db);
		insertQuery.prepare(QStringLiteral("INSERT INTO data (userid, type, key, data) VALUES(?, ?, ?, ?) RETURNING index"));
		insertQuery.addBindValue(userId);
		insertQuery.addBindValue(type);
		insertQuery.addBindValue(key);
		insertQuery.addBindValue(jsonToString(object));
		if(!insertQuery.exec() || !insertQuery.first()) {
			qCritical() << "Failed to insert data with error:"
						<< qPrintable(insertQuery.lastError().text());
			db.rollback();
			return false;
		}
		index = insertQuery.value(0).toULongLong();
	}

	//update the change state
	QSqlQuery updateStateQuery(db);
	updateStateQuery.prepare(QStringLiteral("INSERT INTO states (dataindex, deviceid) "
											"SELECT ?, id FROM devices "
											"WHERE userid = ? AND deviceid != ? "
											"ON CONFLICT DO NOTHING"));
	updateStateQuery.addBindValue(index);
	updateStateQuery.addBindValue(userId);
	updateStateQuery.addBindValue(deviceId);
	if(!updateStateQuery.exec()) {
		qCritical() << "Failed to update device states with error:"
					<< qPrintable(updateStateQuery.lastError().text());
		db.rollback();
		return false;
	}

	//notify all connected devices

	if(db.commit())
		return true;
	else {
		qCritical() << "Failed to commit transaction with error:"
					<< qPrintable(db.lastError().text());
		return false;
	}
}

void DatabaseController::initDatabase()
{
	auto db = threadStore.localData().database();

	if(!db.tables().contains("users")) {
		QSqlQuery createUsers(db);
		if(!createUsers.exec(QStringLiteral("CREATE TABLE users ( "
											"	identity	UUID PRIMARY KEY NOT NULL UNIQUE "
											")"))) {
			qCritical() << "Failed to create users table with error:"
						<< qPrintable(createUsers.lastError().text());
			return;
		}
	}
	if(!db.tables().contains("devices")) {
		QSqlQuery createDevices(db);
		if(!createDevices.exec(QStringLiteral("CREATE TABLE devices ( "
											  "		id			SERIAL PRIMARY KEY NOT NULL, "
											  "		deviceid	UUID NOT NULL, "
											  "		userid		UUID NOT NULL REFERENCES users(identity), "
											  "		CONSTRAINT device_id UNIQUE (deviceid, userid)"
											  ")"))) {
			qCritical() << "Failed to create devices table with error:"
						<< qPrintable(createDevices.lastError().text());
			return;
		}
	}
	if(!db.tables().contains("data")) {
		QSqlQuery createData(db);
		if(!createData.exec(QStringLiteral("CREATE TABLE data ( "
										   "	index	SERIAL PRIMARY KEY NOT NULL, "
										   "	userid	UUID NOT NULL REFERENCES users(identity), "
										   "	type	TEXT NOT NULL, "
										   "	key		TEXT NOT NULL, "
										   "	data	JSONB, "
										   "	CONSTRAINT data_id UNIQUE (userid, type, key)"
										   ")"))) {
			qCritical() << "Failed to create data table with error:"
						<< qPrintable(createData.lastError().text());
			return;
		}
	}
	if(!db.tables().contains("states")) {
		QSqlQuery createStates(db);
		if(!createStates.exec(QStringLiteral("CREATE TABLE states ( "
											 "	dataindex	INTEGER NOT NULL REFERENCES data(index), "
											 "	deviceid	INTEGER NOT NULL REFERENCES devices(id), "
											 "	PRIMARY KEY (dataindex, deviceid)"
											 ")"))) {
			qCritical() << "Failed to create states table with error:"
						<< qPrintable(createStates.lastError().text());
			return;
		}
	}
}

QString DatabaseController::jsonToString(const QJsonObject &object) const
{
	return QJsonDocument(object).toJson(QJsonDocument::Compact);
}

DatabaseController::DatabaseWrapper::DatabaseWrapper() :
	dbName(QUuid::createUuid().toString())
{
	auto config = qApp->configuration();
	auto db = QSqlDatabase::addDatabase(config->value("database/driver", "QPSQL").toString(), dbName);
	db.setDatabaseName(config->value("database/name", "QtDataSync").toString());
	db.setHostName(config->value("database/host").toString());
	db.setPort(config->value("database/port").toInt());
	db.setUserName(config->value("database/username").toString());
	db.setPassword(config->value("database/password").toString());
	db.setConnectOptions(config->value("database/options").toString());

	if(!db.open()) {
		qCritical() << "Failed to open database with error:"
					<< qPrintable(db.lastError().text());
	} else
		qInfo() << "DB connected for thread" << QThread::currentThreadId();
}

DatabaseController::DatabaseWrapper::~DatabaseWrapper()
{
	QSqlDatabase::database(dbName).close();
	QSqlDatabase::removeDatabase(dbName);
	qInfo() << "DB disconnected for thread" << QThread::currentThreadId();
}

QSqlDatabase DatabaseController::DatabaseWrapper::database() const
{
	return QSqlDatabase::database(dbName);
}
<commit_msg>simplified data update<commit_after>#include "databasecontroller.h"
#include "app.h"
#include <QtSql>
#include <QtConcurrent>

DatabaseController::DatabaseController(QObject *parent) :
	QObject(parent),
	multiThreaded(false),
	threadStore()
{
	QtConcurrent::run(this, &DatabaseController::initDatabase);
}

QUuid DatabaseController::createIdentity(const QUuid &deviceId)
{
	auto db = threadStore.localData().database();
	if(!db.transaction()) {
		qCritical() << "Failed to create transaction with error:"
					<< qPrintable(db.lastError().text());
		return {};
	}

	auto identity = QUuid::createUuid();

	QSqlQuery createIdentityQuery(db);
	createIdentityQuery.prepare(QStringLiteral("INSERT INTO users (identity) VALUES(?)"));
	createIdentityQuery.addBindValue(identity);
	if(!createIdentityQuery.exec()) {
		qCritical() << "Failed to add new user identity with error:"
					<< qPrintable(createIdentityQuery.lastError().text());
		db.rollback();
		return {};
	}

	QSqlQuery createDeviceQuery(db);
	createDeviceQuery.prepare(QStringLiteral("INSERT INTO devices (deviceid, userid) VALUES(?, ?)"));
	createDeviceQuery.addBindValue(deviceId);
	createDeviceQuery.addBindValue(identity);
	if(!createDeviceQuery.exec()) {
		qCritical() << "Failed to add new device with error:"
					<< qPrintable(createDeviceQuery.lastError().text());
		db.rollback();
		return {};
	}

	if(db.commit())
		return identity;
	else {
		qCritical() << "Failed to commit transaction with error:"
					<< qPrintable(db.lastError().text());
		return {};
	}
}

bool DatabaseController::identify(const QUuid &identity, const QUuid &deviceId)
{
	auto db = threadStore.localData().database();

	QSqlQuery identifyQuery(db);
	identifyQuery.prepare(QStringLiteral("SELECT EXISTS(SELECT identity FROM users WHERE identity = ?) AS exists"));
	identifyQuery.addBindValue(identity);
	if(!identifyQuery.exec() || !identifyQuery.first()) {
		qCritical() << "Failed to identify user with error:"
					<< qPrintable(identifyQuery.lastError().text());
		return false;
	}

	if(identifyQuery.value(0).toBool()) {
		QSqlQuery createDeviceQuery(db);
		createDeviceQuery.prepare(QStringLiteral("INSERT INTO devices (deviceid, userid) VALUES(?, ?) "
												 "ON CONFLICT DO NOTHING"));
		createDeviceQuery.addBindValue(deviceId);
		createDeviceQuery.addBindValue(identity);
		if(!createDeviceQuery.exec()) {
			qCritical() << "Failed to add (new) device with error:"
						<< qPrintable(createDeviceQuery.lastError().text());
			return false;
		} else
			return true;
	} else
		return false;
}

bool DatabaseController::save(const QUuid &userId, const QUuid &deviceId, const QString &type, const QString &key, const QJsonObject &object)
{
	auto db = threadStore.localData().database();
	if(!db.transaction()) {
		qCritical() << "Failed to create transaction with error:"
					<< qPrintable(db.lastError().text());
		return false;
	}

	// insert/update the data
	QSqlQuery saveQuery(db);
	saveQuery.prepare(QStringLiteral("INSERT INTO data (userid, type, key, data) VALUES(?, ?, ?, ?) "
									 "ON CONFLICT (userid, type, key) DO UPDATE "
									 "SET data = EXCLUDED.data "
									 "RETURNING index"));
	saveQuery.addBindValue(userId);
	saveQuery.addBindValue(type);
	saveQuery.addBindValue(key);
	saveQuery.addBindValue(jsonToString(object));
	if(!saveQuery.exec() || !saveQuery.first()) {
		qCritical() << "Failed to insert/update data with error:"
					<< qPrintable(saveQuery.lastError().text());
		db.rollback();
		return false;
	}
	auto index = saveQuery.value(0).toULongLong();

	//update the change state
	QSqlQuery updateStateQuery(db);
	updateStateQuery.prepare(QStringLiteral("INSERT INTO states (dataindex, deviceid) "
											"SELECT ?, id FROM devices "
											"WHERE userid = ? AND deviceid != ? "
											"ON CONFLICT DO NOTHING"));
	updateStateQuery.addBindValue(index);
	updateStateQuery.addBindValue(userId);
	updateStateQuery.addBindValue(deviceId);
	if(!updateStateQuery.exec()) {
		qCritical() << "Failed to update device states with error:"
					<< qPrintable(updateStateQuery.lastError().text());
		db.rollback();
		return false;
	}

	//notify all connected devices

	if(db.commit())
		return true;
	else {
		qCritical() << "Failed to commit transaction with error:"
					<< qPrintable(db.lastError().text());
		return false;
	}
}

void DatabaseController::initDatabase()
{
	auto db = threadStore.localData().database();

	if(!db.tables().contains("users")) {
		QSqlQuery createUsers(db);
		if(!createUsers.exec(QStringLiteral("CREATE TABLE users ( "
											"	identity	UUID PRIMARY KEY NOT NULL UNIQUE "
											")"))) {
			qCritical() << "Failed to create users table with error:"
						<< qPrintable(createUsers.lastError().text());
			return;
		}
	}
	if(!db.tables().contains("devices")) {
		QSqlQuery createDevices(db);
		if(!createDevices.exec(QStringLiteral("CREATE TABLE devices ( "
											  "		id			SERIAL PRIMARY KEY NOT NULL, "
											  "		deviceid	UUID NOT NULL, "
											  "		userid		UUID NOT NULL REFERENCES users(identity), "
											  "		CONSTRAINT device_id UNIQUE (deviceid, userid)"
											  ")"))) {
			qCritical() << "Failed to create devices table with error:"
						<< qPrintable(createDevices.lastError().text());
			return;
		}
	}
	if(!db.tables().contains("data")) {
		QSqlQuery createData(db);
		if(!createData.exec(QStringLiteral("CREATE TABLE data ( "
										   "	index	SERIAL PRIMARY KEY NOT NULL, "
										   "	userid	UUID NOT NULL REFERENCES users(identity), "
										   "	type	TEXT NOT NULL, "
										   "	key		TEXT NOT NULL, "
										   "	data	JSONB, "
										   "	CONSTRAINT data_id UNIQUE (userid, type, key)"
										   ")"))) {
			qCritical() << "Failed to create data table with error:"
						<< qPrintable(createData.lastError().text());
			return;
		}
	}
	if(!db.tables().contains("states")) {
		QSqlQuery createStates(db);
		if(!createStates.exec(QStringLiteral("CREATE TABLE states ( "
											 "	dataindex	INTEGER NOT NULL REFERENCES data(index), "
											 "	deviceid	INTEGER NOT NULL REFERENCES devices(id), "
											 "	PRIMARY KEY (dataindex, deviceid)"
											 ")"))) {
			qCritical() << "Failed to create states table with error:"
						<< qPrintable(createStates.lastError().text());
			return;
		}
	}
}

QString DatabaseController::jsonToString(const QJsonObject &object) const
{
	return QJsonDocument(object).toJson(QJsonDocument::Compact);
}

DatabaseController::DatabaseWrapper::DatabaseWrapper() :
	dbName(QUuid::createUuid().toString())
{
	auto config = qApp->configuration();
	auto db = QSqlDatabase::addDatabase(config->value("database/driver", "QPSQL").toString(), dbName);
	db.setDatabaseName(config->value("database/name", "QtDataSync").toString());
	db.setHostName(config->value("database/host").toString());
	db.setPort(config->value("database/port").toInt());
	db.setUserName(config->value("database/username").toString());
	db.setPassword(config->value("database/password").toString());
	db.setConnectOptions(config->value("database/options").toString());

	if(!db.open()) {
		qCritical() << "Failed to open database with error:"
					<< qPrintable(db.lastError().text());
	} else
		qInfo() << "DB connected for thread" << QThread::currentThreadId();
}

DatabaseController::DatabaseWrapper::~DatabaseWrapper()
{
	QSqlDatabase::database(dbName).close();
	QSqlDatabase::removeDatabase(dbName);
	qInfo() << "DB disconnected for thread" << QThread::currentThreadId();
}

QSqlDatabase DatabaseController::DatabaseWrapper::database() const
{
	return QSqlDatabase::database(dbName);
}
<|endoftext|>


<commit_before>/***********************************************************************
created:    Sep 15 2014
author:     Luca Ebach <lucaebach@gmail.com>
*************************************************************************/
/***************************************************************************
*   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
*
*   Permission is hereby granted, free of charge, to any person obtaining
*   a copy of this software and associated documentation files (the
*   "Software"), to deal in the Software without restriction, including
*   without limitation the rights to use, copy, modify, merge, publish,
*   distribute, sublicense, and/or sell copies of the Software, and to
*   permit persons to whom the Software is furnished to do so, subject to
*   the following conditions:
*
*   The above copyright notice and this permission notice shall be
*   included in all copies or substantial portions of the Software.
*
*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
*   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
*   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
*   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
*   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*   OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/

/**************************************************************************
* The following libs (and corresponding headers) are needed to compile and to link:
* CEGUIBase
* CEGUIOpenGLRenderer
* CEGUICoreWindowRendererSet
* default CEGUI xml parser (and dependencies)
* GLFW3
* OpengGL
* glm headers (as part of CEGUIBase)
***************************************************************************/

#include <iostream>

#include <CEGUI/CEGUI.h>
#include <CEGUI/RendererModules/OpenGL/GL3Renderer.h>

#include <GLFW/glfw3.h>

static GLFWwindow* window;

CEGUI::MouseButton toCEGUIButton(int button)
{
    switch (button)
    {
    case GLFW_MOUSE_BUTTON_LEFT:
        return CEGUI::LeftButton;

    case GLFW_MOUSE_BUTTON_MIDDLE:
        return CEGUI::MiddleButton;

    case GLFW_MOUSE_BUTTON_RIGHT:
        return CEGUI::RightButton;

    default:
        return CEGUI::MouseButtonCount;
    }
}

CEGUI::Key::Scan toCEGUIKey(int glfwKey)
{
    switch (glfwKey)
    {
    case GLFW_KEY_ESCAPE: return CEGUI::Key::Escape;
    case GLFW_KEY_F1: return CEGUI::Key::F1;
    case GLFW_KEY_F2: return CEGUI::Key::F2;
    case GLFW_KEY_F3: return CEGUI::Key::F3;
    case GLFW_KEY_F4: return CEGUI::Key::F4;
    case GLFW_KEY_F5: return CEGUI::Key::F5;
    case GLFW_KEY_F6: return CEGUI::Key::F6;
    case GLFW_KEY_F7: return CEGUI::Key::F7;
    case GLFW_KEY_F8: return CEGUI::Key::F8;
    case GLFW_KEY_F9: return CEGUI::Key::F9;
    case GLFW_KEY_F10: return CEGUI::Key::F10;
    case GLFW_KEY_F11: return CEGUI::Key::F11;
    case GLFW_KEY_F12: return CEGUI::Key::F12;
    case GLFW_KEY_F13: return CEGUI::Key::F13;
    case GLFW_KEY_F14: return CEGUI::Key::F14;
    case GLFW_KEY_F15: return CEGUI::Key::F15;
    case GLFW_KEY_UP: return CEGUI::Key::ArrowUp;
    case GLFW_KEY_DOWN: return CEGUI::Key::ArrowDown;
    case GLFW_KEY_LEFT: return CEGUI::Key::ArrowLeft;
    case GLFW_KEY_RIGHT: return CEGUI::Key::ArrowRight;
    case GLFW_KEY_LEFT_SHIFT: return CEGUI::Key::LeftShift;
    case GLFW_KEY_RIGHT_SHIFT: return CEGUI::Key::RightShift;
    case GLFW_KEY_LEFT_CONTROL: return CEGUI::Key::LeftControl;
    case GLFW_KEY_RIGHT_CONTROL: return CEGUI::Key::RightControl;
    case GLFW_KEY_LEFT_ALT: return CEGUI::Key::LeftAlt;
    case GLFW_KEY_RIGHT_ALT: return CEGUI::Key::RightAlt;
    case GLFW_KEY_TAB: return CEGUI::Key::Tab;
    case GLFW_KEY_ENTER: return CEGUI::Key::Return;
    case GLFW_KEY_BACKSPACE: return CEGUI::Key::Backspace;
    case GLFW_KEY_INSERT: return CEGUI::Key::Insert;
    case GLFW_KEY_DELETE: return CEGUI::Key::Delete;
    case GLFW_KEY_PAGE_UP: return CEGUI::Key::PageUp;
    case GLFW_KEY_PAGE_DOWN: return CEGUI::Key::PageDown;
    case GLFW_KEY_HOME: return CEGUI::Key::Home;
    case GLFW_KEY_END: return CEGUI::Key::End;
    case GLFW_KEY_KP_ENTER: return CEGUI::Key::NumpadEnter;
    case GLFW_KEY_SPACE: return CEGUI::Key::Space;
    case 'A': return CEGUI::Key::A;
    case 'B': return CEGUI::Key::B;
    case 'C': return CEGUI::Key::C;
    case 'D': return CEGUI::Key::D;
    case 'E': return CEGUI::Key::E;
    case 'F': return CEGUI::Key::F;
    case 'G': return CEGUI::Key::G;
    case 'H': return CEGUI::Key::H;
    case 'I': return CEGUI::Key::I;
    case 'J': return CEGUI::Key::J;
    case 'K': return CEGUI::Key::K;
    case 'L': return CEGUI::Key::L;
    case 'M': return CEGUI::Key::M;
    case 'N': return CEGUI::Key::N;
    case 'O': return CEGUI::Key::O;
    case 'P': return CEGUI::Key::P;
    case 'Q': return CEGUI::Key::Q;
    case 'R': return CEGUI::Key::R;
    case 'S': return CEGUI::Key::S;
    case 'T': return CEGUI::Key::T;
    case 'U': return CEGUI::Key::U;
    case 'V': return CEGUI::Key::V;
    case 'W': return CEGUI::Key::W;
    case 'X': return CEGUI::Key::X;
    case 'Y': return CEGUI::Key::Y;
    case 'Z': return CEGUI::Key::Z;
    default: return CEGUI::Key::Unknown;
    }
}

void charCallback(GLFWwindow* window, unsigned int char_pressed)
{
    CEGUI::System::getSingleton().getDefaultGUIContext().injectChar(char_pressed);
}

void cursorPosCallback(GLFWwindow* window, double x, double y)
{
    CEGUI::System::getSingleton().getDefaultGUIContext().injectMousePosition(x, y);
}

void keyCallback(GLFWwindow* window, int key, int scan, int action, int mod)
{
    CEGUI::Key::Scan cegui_key = toCEGUIKey(key);
    if (action == GLFW_PRESS)
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyDown(cegui_key);
    }
    else
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyUp(cegui_key);
    }
}

void mouseButtonCallback(GLFWwindow* window, int button, int state, int mod)
{
    if (state == GLFW_PRESS)
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(toCEGUIButton(button));
    }
    else
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(toCEGUIButton(button));
    }
}

void mouseWheelCallback(GLFWwindow* window, double x, double y)
{
    if (y < 0.f)
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(-1.f);
    else
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(+1.f);
}

void windowResizedCallback(GLFWwindow* window, int width, int height)
{
    CEGUI::System::getSingleton().notifyDisplaySizeChanged(
        CEGUI::Sizef(static_cast<float>(width), static_cast<float>(height)));
    glViewport(0, 0, width, height);
}

void errorCallback(int error, const char* message)
{
    CEGUI::Logger::getSingleton().logEvent(message, CEGUI::Errors);
}

void setupCallbacks()
{
    // input callbacks
    glfwSetCharCallback(window, charCallback);
    glfwSetCursorPosCallback(window, cursorPosCallback);
    glfwSetKeyCallback(window, keyCallback);
    glfwSetMouseButtonCallback(window, mouseButtonCallback);
    glfwSetScrollCallback(window, mouseWheelCallback);

    // window callback
    glfwSetWindowSizeCallback(window, windowResizedCallback);

    // error callback
    glfwSetErrorCallback(errorCallback);
}

void initGLFW()
{
    // init everything from glfw
    if (glfwInit() != GL_TRUE)
    {
        std::cerr << "glfw could not be initialized!" << std::endl;
        exit(1);
    }

    // create glfw window with size of 800x600px
    window = glfwCreateWindow(800, 600, "CEGUI + glfw3 window", NULL, NULL);
    if (!window)
    {
        std::cerr << "Could not create glfw window!" << std::endl;
        glfwTerminate();
        exit(1);
    }

    // makes this window's gl context the current one
    glfwMakeContextCurrent(window);

    // hide native mouse cursor when it is over the window
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);

    // disable VSYNC
    glfwSwapInterval(0);

    // clear error messages
    glGetError();
}

void initCEGUI()
{
    using namespace CEGUI;

    // create renderer and enable extra states
    OpenGL3Renderer& cegui_renderer = OpenGL3Renderer::create(Sizef(800.f, 600.f));
    cegui_renderer.enableExtraStateSettings(true);

    // create CEGUI system object
    CEGUI::System::create(cegui_renderer);

    // setup resource directories
    DefaultResourceProvider* rp = static_cast<DefaultResourceProvider*>(System::getSingleton().getResourceProvider());
    rp->setResourceGroupDirectory("schemes", "datafiles/schemes/");
    rp->setResourceGroupDirectory("imagesets", "datafiles/imagesets/");
    rp->setResourceGroupDirectory("fonts", "datafiles/fonts/");
    rp->setResourceGroupDirectory("layouts", "datafiles/layouts/");
    rp->setResourceGroupDirectory("looknfeels", "datafiles/looknfeel/");
    rp->setResourceGroupDirectory("lua_scripts", "datafiles/lua_scripts/");
    rp->setResourceGroupDirectory("schemas", "datafiles/xml_schemas/");

    // set default resource groups
    ImageManager::setImagesetDefaultResourceGroup("imagesets");
    Font::setDefaultResourceGroup("fonts");
    Scheme::setDefaultResourceGroup("schemes");
    WidgetLookManager::setDefaultResourceGroup("looknfeels");
    WindowManager::setDefaultResourceGroup("layouts");
    ScriptModule::setDefaultResourceGroup("lua_scripts");

    XMLParser* parser = System::getSingleton().getXMLParser();
    if (parser->isPropertyPresent("SchemaDefaultResourceGroup"))
        parser->setProperty("SchemaDefaultResourceGroup", "schemas");

    // load TaharezLook scheme and DejaVuSans-10 font
    SchemeManager::getSingleton().createFromFile("TaharezLook.scheme", "schemes");
    FontManager::getSingleton().createFromFile("DejaVuSans-10.font");

    // set default font and cursor image and tooltip type
    System::getSingleton().getDefaultGUIContext().setDefaultFont("DejaVuSans-10");
    System::getSingleton().getDefaultGUIContext().getMouseCursor().setDefaultImage("TaharezLook/MouseArrow");
    System::getSingleton().getDefaultGUIContext().setDefaultTooltipType("TaharezLook/Tooltip");
}

void initWindows()
{
    using namespace CEGUI;

    /////////////////////////////////////////////////////////////
    // Add your gui initialisation code in here.
    // You should preferably use layout loading because you won't
    // have to recompile everytime you change the layout. But you
    // can also use static window creation code here, of course.
    /////////////////////////////////////////////////////////////

    // load layout
    Window* root = WindowManager::getSingleton().loadLayoutFromFile("application_templates.layout");
    System::getSingleton().getDefaultGUIContext().setRootWindow(root);
}

#ifdef _MSC_VER
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
#else
int main(int argc, char* argv[])
#endif
{
    using namespace CEGUI;

    // init glfw
    initGLFW();

    // init cegui
    initCEGUI();

    // setup glfw callbacks
    setupCallbacks();

    // notify system of the window size
    System::getSingleton().notifyDisplaySizeChanged(Sizef(800.f, 600.f));
    glViewport(0, 0, 800, 600);

    // initialise windows and setup layout
    initWindows();

    // set gl clear color
    glClearColor(0, 0, 0, 255);

    float time = glfwGetTime();

    OpenGL3Renderer* renderer = static_cast<OpenGL3Renderer*>(System::getSingleton().getRenderer());

    // repeat until a quit is requested
    while (glfwWindowShouldClose(window) == GL_FALSE)
    {
        // clear screen
        glClear(GL_COLOR_BUFFER_BIT);

        // inject time pulses
        const float newtime = glfwGetTime();
        const float time_elapsed = newtime - time;
        System::getSingleton().injectTimePulse(time_elapsed);
        System::getSingleton().getDefaultGUIContext().injectTimePulse(time_elapsed);
        time = newtime;

        // render gui
        renderer->beginRendering();
        System::getSingleton().renderAllGUIContexts();
        renderer->endRendering();

        // swap buffers
        glfwSwapBuffers(window);

        // poll events
        glfwPollEvents();
    }

    // destroy system and renderer
    System::destroy();
    OpenGL3Renderer::destroy(*renderer);
    renderer = 0;

    // destroy glfw window
    glfwDestroyWindow(window);

    // cleanup glfw
    glfwTerminate();

    return 0;
}<commit_msg>MOD: docu<commit_after>/***********************************************************************
created:    Sep 15 2014
author:     Luca Ebach <bitcket@lucebac.net>
*************************************************************************/
/***************************************************************************
*   Copyright (C) 2004 - 2015 Paul D Turner & The CEGUI Development Team
*
*   Permission is hereby granted, free of charge, to any person obtaining
*   a copy of this software and associated documentation files (the
*   "Software"), to deal in the Software without restriction, including
*   without limitation the rights to use, copy, modify, merge, publish,
*   distribute, sublicense, and/or sell copies of the Software, and to
*   permit persons to whom the Software is furnished to do so, subject to
*   the following conditions:
*
*   The above copyright notice and this permission notice shall be
*   included in all copies or substantial portions of the Software.
*
*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
*   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
*   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
*   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
*   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*   OTHER DEALINGS IN THE SOFTWARE.
***************************************************************************/

/**************************************************************************
* The following libs (and corresponding headers) are needed to compile and to link:
* CEGUIBase
* CEGUIOpenGLRenderer
* CEGUICoreWindowRendererSet
* default CEGUI xml parser (and dependencies)
* GLFW3
* OpengGL
* glm headers (as part of CEGUIBase)
***************************************************************************/

#include <iostream>

#include <CEGUI/CEGUI.h>
#include <CEGUI/RendererModules/OpenGL/GL3Renderer.h>

#include <GLFW/glfw3.h>

static GLFWwindow* window;

CEGUI::MouseButton toCEGUIButton(int button)
{
    switch (button)
    {
    case GLFW_MOUSE_BUTTON_LEFT:
        return CEGUI::LeftButton;

    case GLFW_MOUSE_BUTTON_MIDDLE:
        return CEGUI::MiddleButton;

    case GLFW_MOUSE_BUTTON_RIGHT:
        return CEGUI::RightButton;

    default:
        return CEGUI::MouseButtonCount;
    }
}

CEGUI::Key::Scan toCEGUIKey(int glfwKey)
{
    switch (glfwKey)
    {
    case GLFW_KEY_ESCAPE: return CEGUI::Key::Escape;
    case GLFW_KEY_F1: return CEGUI::Key::F1;
    case GLFW_KEY_F2: return CEGUI::Key::F2;
    case GLFW_KEY_F3: return CEGUI::Key::F3;
    case GLFW_KEY_F4: return CEGUI::Key::F4;
    case GLFW_KEY_F5: return CEGUI::Key::F5;
    case GLFW_KEY_F6: return CEGUI::Key::F6;
    case GLFW_KEY_F7: return CEGUI::Key::F7;
    case GLFW_KEY_F8: return CEGUI::Key::F8;
    case GLFW_KEY_F9: return CEGUI::Key::F9;
    case GLFW_KEY_F10: return CEGUI::Key::F10;
    case GLFW_KEY_F11: return CEGUI::Key::F11;
    case GLFW_KEY_F12: return CEGUI::Key::F12;
    case GLFW_KEY_F13: return CEGUI::Key::F13;
    case GLFW_KEY_F14: return CEGUI::Key::F14;
    case GLFW_KEY_F15: return CEGUI::Key::F15;
    case GLFW_KEY_UP: return CEGUI::Key::ArrowUp;
    case GLFW_KEY_DOWN: return CEGUI::Key::ArrowDown;
    case GLFW_KEY_LEFT: return CEGUI::Key::ArrowLeft;
    case GLFW_KEY_RIGHT: return CEGUI::Key::ArrowRight;
    case GLFW_KEY_LEFT_SHIFT: return CEGUI::Key::LeftShift;
    case GLFW_KEY_RIGHT_SHIFT: return CEGUI::Key::RightShift;
    case GLFW_KEY_LEFT_CONTROL: return CEGUI::Key::LeftControl;
    case GLFW_KEY_RIGHT_CONTROL: return CEGUI::Key::RightControl;
    case GLFW_KEY_LEFT_ALT: return CEGUI::Key::LeftAlt;
    case GLFW_KEY_RIGHT_ALT: return CEGUI::Key::RightAlt;
    case GLFW_KEY_TAB: return CEGUI::Key::Tab;
    case GLFW_KEY_ENTER: return CEGUI::Key::Return;
    case GLFW_KEY_BACKSPACE: return CEGUI::Key::Backspace;
    case GLFW_KEY_INSERT: return CEGUI::Key::Insert;
    case GLFW_KEY_DELETE: return CEGUI::Key::Delete;
    case GLFW_KEY_PAGE_UP: return CEGUI::Key::PageUp;
    case GLFW_KEY_PAGE_DOWN: return CEGUI::Key::PageDown;
    case GLFW_KEY_HOME: return CEGUI::Key::Home;
    case GLFW_KEY_END: return CEGUI::Key::End;
    case GLFW_KEY_KP_ENTER: return CEGUI::Key::NumpadEnter;
    case GLFW_KEY_SPACE: return CEGUI::Key::Space;
    case 'A': return CEGUI::Key::A;
    case 'B': return CEGUI::Key::B;
    case 'C': return CEGUI::Key::C;
    case 'D': return CEGUI::Key::D;
    case 'E': return CEGUI::Key::E;
    case 'F': return CEGUI::Key::F;
    case 'G': return CEGUI::Key::G;
    case 'H': return CEGUI::Key::H;
    case 'I': return CEGUI::Key::I;
    case 'J': return CEGUI::Key::J;
    case 'K': return CEGUI::Key::K;
    case 'L': return CEGUI::Key::L;
    case 'M': return CEGUI::Key::M;
    case 'N': return CEGUI::Key::N;
    case 'O': return CEGUI::Key::O;
    case 'P': return CEGUI::Key::P;
    case 'Q': return CEGUI::Key::Q;
    case 'R': return CEGUI::Key::R;
    case 'S': return CEGUI::Key::S;
    case 'T': return CEGUI::Key::T;
    case 'U': return CEGUI::Key::U;
    case 'V': return CEGUI::Key::V;
    case 'W': return CEGUI::Key::W;
    case 'X': return CEGUI::Key::X;
    case 'Y': return CEGUI::Key::Y;
    case 'Z': return CEGUI::Key::Z;
    default: return CEGUI::Key::Unknown;
    }
}

void charCallback(GLFWwindow* window, unsigned int char_pressed)
{
    CEGUI::System::getSingleton().getDefaultGUIContext().injectChar(char_pressed);
}

void cursorPosCallback(GLFWwindow* window, double x, double y)
{
    CEGUI::System::getSingleton().getDefaultGUIContext().injectMousePosition(x, y);
}

void keyCallback(GLFWwindow* window, int key, int scan, int action, int mod)
{
    CEGUI::Key::Scan cegui_key = toCEGUIKey(key);
    if (action == GLFW_PRESS)
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyDown(cegui_key);
    }
    else
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectKeyUp(cegui_key);
    }
}

void mouseButtonCallback(GLFWwindow* window, int button, int state, int mod)
{
    if (state == GLFW_PRESS)
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(toCEGUIButton(button));
    }
    else
    {
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(toCEGUIButton(button));
    }
}

void mouseWheelCallback(GLFWwindow* window, double x, double y)
{
    if (y < 0.f)
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(-1.f);
    else
        CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseWheelChange(+1.f);
}

void windowResizedCallback(GLFWwindow* window, int width, int height)
{
    CEGUI::System::getSingleton().notifyDisplaySizeChanged(
        CEGUI::Sizef(static_cast<float>(width), static_cast<float>(height)));
    glViewport(0, 0, width, height);
}

void errorCallback(int error, const char* message)
{
    CEGUI::Logger::getSingleton().logEvent(message, CEGUI::Errors);
}

void setupCallbacks()
{
    // input callbacks
    glfwSetCharCallback(window, charCallback);
    glfwSetCursorPosCallback(window, cursorPosCallback);
    glfwSetKeyCallback(window, keyCallback);
    glfwSetMouseButtonCallback(window, mouseButtonCallback);
    glfwSetScrollCallback(window, mouseWheelCallback);

    // window callback
    glfwSetWindowSizeCallback(window, windowResizedCallback);

    // error callback
    glfwSetErrorCallback(errorCallback);
}

void initGLFW()
{
    // init everything from glfw
    if (glfwInit() != GL_TRUE)
    {
        std::cerr << "glfw could not be initialized!" << std::endl;
        exit(1);
    }

    // create glfw window with size of 800x600px
    window = glfwCreateWindow(800, 600, "CEGUI + glfw3 window", NULL, NULL);
    if (!window)
    {
        std::cerr << "Could not create glfw window!" << std::endl;
        glfwTerminate();
        exit(1);
    }

    // makes this window's gl context the current one
    glfwMakeContextCurrent(window);

    // hide native mouse cursor when it is over the window
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);

    // disable VSYNC
    glfwSwapInterval(0);

    // clear error messages
    glGetError();
}

void initCEGUI()
{
    using namespace CEGUI;

    // create renderer and enable extra states
    OpenGL3Renderer& cegui_renderer = OpenGL3Renderer::create(Sizef(800.f, 600.f));
    cegui_renderer.enableExtraStateSettings(true);

    // create CEGUI system object
    CEGUI::System::create(cegui_renderer);

    // setup resource directories
    DefaultResourceProvider* rp = static_cast<DefaultResourceProvider*>(System::getSingleton().getResourceProvider());
    rp->setResourceGroupDirectory("schemes", "datafiles/schemes/");
    rp->setResourceGroupDirectory("imagesets", "datafiles/imagesets/");
    rp->setResourceGroupDirectory("fonts", "datafiles/fonts/");
    rp->setResourceGroupDirectory("layouts", "datafiles/layouts/");
    rp->setResourceGroupDirectory("looknfeels", "datafiles/looknfeel/");
    rp->setResourceGroupDirectory("lua_scripts", "datafiles/lua_scripts/");
    rp->setResourceGroupDirectory("schemas", "datafiles/xml_schemas/");

    // set default resource groups
    ImageManager::setImagesetDefaultResourceGroup("imagesets");
    Font::setDefaultResourceGroup("fonts");
    Scheme::setDefaultResourceGroup("schemes");
    WidgetLookManager::setDefaultResourceGroup("looknfeels");
    WindowManager::setDefaultResourceGroup("layouts");
    ScriptModule::setDefaultResourceGroup("lua_scripts");

    XMLParser* parser = System::getSingleton().getXMLParser();
    if (parser->isPropertyPresent("SchemaDefaultResourceGroup"))
        parser->setProperty("SchemaDefaultResourceGroup", "schemas");

    // load TaharezLook scheme and DejaVuSans-10 font
    SchemeManager::getSingleton().createFromFile("TaharezLook.scheme", "schemes");
    FontManager::getSingleton().createFromFile("DejaVuSans-10.font");

    // set default font and cursor image and tooltip type
    System::getSingleton().getDefaultGUIContext().setDefaultFont("DejaVuSans-10");
    System::getSingleton().getDefaultGUIContext().getMouseCursor().setDefaultImage("TaharezLook/MouseArrow");
    System::getSingleton().getDefaultGUIContext().setDefaultTooltipType("TaharezLook/Tooltip");
}

void initWindows()
{
    using namespace CEGUI;

    /////////////////////////////////////////////////////////////
    // Add your gui initialisation code in here.
    // You should preferably use layout loading because you won't
    // have to recompile everytime you change the layout. But you
    // can also use static window creation code here, of course.
    /////////////////////////////////////////////////////////////

    // load layout
    Window* root = WindowManager::getSingleton().loadLayoutFromFile("application_templates.layout");
    System::getSingleton().getDefaultGUIContext().setRootWindow(root);
}

#ifdef _MSC_VER
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
#else
int main(int argc, char* argv[])
#endif
{
    using namespace CEGUI;

    // init glfw
    initGLFW();

    // init cegui
    initCEGUI();

    // setup glfw callbacks
    setupCallbacks();

    // notify system of the window size
    System::getSingleton().notifyDisplaySizeChanged(Sizef(800.f, 600.f));
    glViewport(0, 0, 800, 600);

    // initialise windows and setup layout
    initWindows();

    // set gl clear color
    glClearColor(0, 0, 0, 255);

    float time = glfwGetTime();

    OpenGL3Renderer* renderer = static_cast<OpenGL3Renderer*>(System::getSingleton().getRenderer());

    // repeat until a quit is requested
    while (glfwWindowShouldClose(window) == GL_FALSE)
    {
        // clear screen
        glClear(GL_COLOR_BUFFER_BIT);

        // inject time pulses
        const float newtime = glfwGetTime();
        const float time_elapsed = newtime - time;
        System::getSingleton().injectTimePulse(time_elapsed);
        System::getSingleton().getDefaultGUIContext().injectTimePulse(time_elapsed);
        time = newtime;

        // render gui
        renderer->beginRendering();
        System::getSingleton().renderAllGUIContexts();
        renderer->endRendering();

        // swap buffers
        glfwSwapBuffers(window);

        // poll events
        glfwPollEvents();
    }

    // destroy system and renderer
    System::destroy();
    OpenGL3Renderer::destroy(*renderer);
    renderer = 0;

    // destroy glfw window
    glfwDestroyWindow(window);

    // cleanup glfw
    glfwTerminate();

    return 0;
}<|endoftext|>


<commit_before>// $Id$

/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include <cassert>
#include <cstring>
#include <iostream>
#include "lm/binary_format.hh"
#include "lm/enumerate_vocab.hh"
#include "lm/model.hh"

#include "LanguageModelKen.h"
#include "FFState.h"
#include "TypeDef.h"
#include "Util.h"
#include "FactorCollection.h"
#include "Phrase.h"
#include "InputFileStream.h"
#include "StaticData.h"

using namespace std;

namespace Moses
{

namespace {

class MappingBuilder : public lm::ngram::EnumerateVocab {
	public:
		MappingBuilder(FactorType factorType, FactorCollection &factorCollection, std::vector<lm::WordIndex> &mapping)
		: m_factorType(factorType), m_factorCollection(factorCollection), m_mapping(mapping) {}

		void Add(lm::WordIndex index, const StringPiece &str) {
			m_word.assign(str.data(), str.size());
			std::size_t factorId = m_factorCollection.AddFactor(Output, m_factorType, m_word)->GetId();
			if (m_mapping.size() <= factorId) {
				// 0 is <unk> :-)
				m_mapping.resize(factorId + 1);
			}
			m_mapping[factorId] = index;
		}

	private:
		std::string m_word;
		FactorType m_factorType;
		FactorCollection &m_factorCollection;
	std::vector<lm::WordIndex> &m_mapping;
};

struct KenLMState : public FFState {
	lm::ngram::State state;
	int Compare(const FFState &o) const {
		const KenLMState &other = static_cast<const KenLMState &>(o);
		if (state.valid_length_ < other.state.valid_length_) return -1;
		if (state.valid_length_ > other.state.valid_length_) return 1;
		return std::memcmp(state.history_, other.state.history_, sizeof(lm::WordIndex) * state.valid_length_);
	}
};

/** Implementation of single factor LM using Ken's code.
*/
template <class Model> class LanguageModelKen : public LanguageModelSingleFactor
{
private:
	Model *m_ngram;
	std::vector<lm::WordIndex> m_lmIdLookup;
	bool m_lazy;
	FFState *m_nullContextState;
	FFState *m_beginSentenceState;

	void TranslateIDs(const std::vector<const Word*> &contextFactor, lm::WordIndex *indices) const;

public:
	LanguageModelKen(bool lazy);
	~LanguageModelKen();

	bool Load(const std::string &filePath
					, FactorType factorType
					, size_t nGramOrder);

	float GetValueGivenState(const std::vector<const Word*> &contextFactor, FFState &state, unsigned int* len = 0) const;
	float GetValueForgotState(const std::vector<const Word*> &contextFactor, FFState &outState, unsigned int* len=0) const;
	void GetState(const std::vector<const Word*> &contextFactor, FFState &outState) const;

	FFState *GetNullContextState() const;
	FFState *GetBeginSentenceState() const;
	FFState *NewState(const FFState *from = NULL) const;

	lm::WordIndex GetLmID(const std::string &str) const;

	void CleanUpAfterSentenceProcessing() {}
	void InitializeBeforeSentenceProcessing() {}

};

template <class Model> void LanguageModelKen<Model>::TranslateIDs(const std::vector<const Word*> &contextFactor, lm::WordIndex *indices) const
{
	FactorType factorType = GetFactorType();
	// set up context
	for (size_t i = 0 ; i < contextFactor.size(); i++)
	{
		std::size_t factor = contextFactor[i]->GetFactor(factorType)->GetId();
		lm::WordIndex new_word = (factor >= m_lmIdLookup.size() ? 0 : m_lmIdLookup[factor]);
		indices[contextFactor.size() - 1 - i] = new_word;
	}
}

template <class Model> LanguageModelKen<Model>::LanguageModelKen(bool lazy)
:m_ngram(NULL), m_lazy(lazy)
{
}

template <class Model> LanguageModelKen<Model>::~LanguageModelKen()
{
	delete m_ngram;
}

template <class Model> bool LanguageModelKen<Model>::Load(const std::string &filePath,
			     FactorType factorType,
			     size_t /*nGramOrder*/)
{
	m_factorType  = factorType;
	m_filePath    = filePath;

	FactorCollection &factorCollection = FactorCollection::Instance();
	m_sentenceStart = factorCollection.AddFactor(Output, m_factorType, BOS_);
	m_sentenceStartArray[m_factorType] = m_sentenceStart;
	m_sentenceEnd = factorCollection.AddFactor(Output, m_factorType, EOS_);
	m_sentenceEndArray[m_factorType] = m_sentenceEnd;

	MappingBuilder builder(m_factorType, factorCollection, m_lmIdLookup);
	lm::ngram::Config config;
	config.enumerate_vocab = &builder;
	config.load_method = m_lazy ? util::LAZY : util::POPULATE_OR_READ;

	m_ngram = new Model(filePath.c_str(), config);
	m_nGramOrder  = m_ngram->Order();

	KenLMState *tmp = new KenLMState();
	tmp->state = m_ngram->NullContextState();
	m_nullContextState = tmp;
	tmp = new KenLMState();
	tmp->state = m_ngram->BeginSentenceState();
	m_beginSentenceState = tmp;
	return true;
}

template <class Model> float LanguageModelKen<Model>::GetValueGivenState(const std::vector<const Word*> &contextFactor, FFState &state, unsigned int* len) const
{
	if (contextFactor.empty())
	{
		return 0;
	}
	lm::ngram::State &realState = static_cast<KenLMState&>(state).state;
	std::size_t factor = contextFactor.back()->GetFactor(GetFactorType())->GetId();
	lm::WordIndex new_word = (factor >= m_lmIdLookup.size() ? 0 : m_lmIdLookup[factor]);
	lm::ngram::State copied(realState);
	lm::FullScoreReturn ret(m_ngram->FullScore(copied, new_word, realState));

	if (len)
	{
		*len = ret.ngram_length;
	}
	return TransformLMScore(ret.prob);
}

template <class Model> float LanguageModelKen<Model>::GetValueForgotState(const vector<const Word*> &contextFactor, FFState &outState, unsigned int* len) const
{
	if (contextFactor.empty())
	{
		static_cast<KenLMState&>(outState).state = m_ngram->NullContextState();
		return 0;
	}

	lm::WordIndex indices[contextFactor.size()];
	TranslateIDs(contextFactor, indices);

	lm::FullScoreReturn ret(m_ngram->FullScoreForgotState(indices + 1, indices + contextFactor.size(), indices[0], static_cast<KenLMState&>(outState).state));
	if (len)
	{
		*len = ret.ngram_length;
	}
	return TransformLMScore(ret.prob);
}

template <class Model> void LanguageModelKen<Model>::GetState(const std::vector<const Word*> &contextFactor, FFState &outState) const {
	if (contextFactor.empty()) {
		static_cast<KenLMState&>(outState).state = m_ngram->NullContextState();
		return;
	}
	lm::WordIndex indices[contextFactor.size()];
	TranslateIDs(contextFactor, indices);
	m_ngram->GetState(indices, indices + contextFactor.size(), static_cast<KenLMState&>(outState).state);
}

template <class Model> FFState *LanguageModelKen<Model>::GetNullContextState() const {
	return m_nullContextState;
}

template <class Model> FFState *LanguageModelKen<Model>::GetBeginSentenceState() const {
	return m_beginSentenceState;
}

template <class Model> FFState *LanguageModelKen<Model>::NewState(const FFState *from) const {
	KenLMState *ret = new KenLMState;
	if (from) {
		ret->state = static_cast<const KenLMState&>(*from).state;
	}
	return ret;
}

template <class Model> lm::WordIndex LanguageModelKen<Model>::GetLmID(const std::string &str) const {
	return m_ngram->GetVocabulary().Index(str);
}

} // namespace

LanguageModelSingleFactor *ConstructKenLM(const std::string &file, bool lazy) {
	lm::ngram::ModelType model_type;
	if (lm::ngram::RecognizeBinary(file.c_str(), model_type)) {
		switch(model_type) {
			case lm::ngram::HASH_PROBING:
				return new LanguageModelKen<lm::ngram::ProbingModel>(lazy);
			case lm::ngram::HASH_SORTED:
				return new LanguageModelKen<lm::ngram::SortedModel>(lazy);
			case lm::ngram::TRIE_SORTED:
				return new LanguageModelKen<lm::ngram::TrieModel>(lazy);
			default:
				std::cerr << "Unrecognized kenlm model type " << model_type << std::endl;
				abort();
		}
	} else {
		return new LanguageModelKen<lm::ngram::ProbingModel>(lazy);
	}
}

}

<commit_msg>Respect -v 0<commit_after>// $Id$

/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include <cassert>
#include <cstring>
#include <iostream>
#include "lm/binary_format.hh"
#include "lm/enumerate_vocab.hh"
#include "lm/model.hh"

#include "LanguageModelKen.h"
#include "FFState.h"
#include "TypeDef.h"
#include "Util.h"
#include "FactorCollection.h"
#include "Phrase.h"
#include "InputFileStream.h"
#include "StaticData.h"

using namespace std;

namespace Moses
{

namespace {

class MappingBuilder : public lm::ngram::EnumerateVocab {
	public:
		MappingBuilder(FactorType factorType, FactorCollection &factorCollection, std::vector<lm::WordIndex> &mapping)
		: m_factorType(factorType), m_factorCollection(factorCollection), m_mapping(mapping) {}

		void Add(lm::WordIndex index, const StringPiece &str) {
			m_word.assign(str.data(), str.size());
			std::size_t factorId = m_factorCollection.AddFactor(Output, m_factorType, m_word)->GetId();
			if (m_mapping.size() <= factorId) {
				// 0 is <unk> :-)
				m_mapping.resize(factorId + 1);
			}
			m_mapping[factorId] = index;
		}

	private:
		std::string m_word;
		FactorType m_factorType;
		FactorCollection &m_factorCollection;
	std::vector<lm::WordIndex> &m_mapping;
};

struct KenLMState : public FFState {
	lm::ngram::State state;
	int Compare(const FFState &o) const {
		const KenLMState &other = static_cast<const KenLMState &>(o);
		if (state.valid_length_ < other.state.valid_length_) return -1;
		if (state.valid_length_ > other.state.valid_length_) return 1;
		return std::memcmp(state.history_, other.state.history_, sizeof(lm::WordIndex) * state.valid_length_);
	}
};

/** Implementation of single factor LM using Ken's code.
*/
template <class Model> class LanguageModelKen : public LanguageModelSingleFactor
{
private:
	Model *m_ngram;
	std::vector<lm::WordIndex> m_lmIdLookup;
	bool m_lazy;
	FFState *m_nullContextState;
	FFState *m_beginSentenceState;

	void TranslateIDs(const std::vector<const Word*> &contextFactor, lm::WordIndex *indices) const;

public:
	LanguageModelKen(bool lazy);
	~LanguageModelKen();

	bool Load(const std::string &filePath
					, FactorType factorType
					, size_t nGramOrder);

	float GetValueGivenState(const std::vector<const Word*> &contextFactor, FFState &state, unsigned int* len = 0) const;
	float GetValueForgotState(const std::vector<const Word*> &contextFactor, FFState &outState, unsigned int* len=0) const;
	void GetState(const std::vector<const Word*> &contextFactor, FFState &outState) const;

	FFState *GetNullContextState() const;
	FFState *GetBeginSentenceState() const;
	FFState *NewState(const FFState *from = NULL) const;

	lm::WordIndex GetLmID(const std::string &str) const;

	void CleanUpAfterSentenceProcessing() {}
	void InitializeBeforeSentenceProcessing() {}

};

template <class Model> void LanguageModelKen<Model>::TranslateIDs(const std::vector<const Word*> &contextFactor, lm::WordIndex *indices) const
{
	FactorType factorType = GetFactorType();
	// set up context
	for (size_t i = 0 ; i < contextFactor.size(); i++)
	{
		std::size_t factor = contextFactor[i]->GetFactor(factorType)->GetId();
		lm::WordIndex new_word = (factor >= m_lmIdLookup.size() ? 0 : m_lmIdLookup[factor]);
		indices[contextFactor.size() - 1 - i] = new_word;
	}
}

template <class Model> LanguageModelKen<Model>::LanguageModelKen(bool lazy)
:m_ngram(NULL), m_lazy(lazy)
{
}

template <class Model> LanguageModelKen<Model>::~LanguageModelKen()
{
	delete m_ngram;
}

template <class Model> bool LanguageModelKen<Model>::Load(const std::string &filePath,
			     FactorType factorType,
			     size_t /*nGramOrder*/)
{
	m_factorType  = factorType;
	m_filePath    = filePath;

	FactorCollection &factorCollection = FactorCollection::Instance();
	m_sentenceStart = factorCollection.AddFactor(Output, m_factorType, BOS_);
	m_sentenceStartArray[m_factorType] = m_sentenceStart;
	m_sentenceEnd = factorCollection.AddFactor(Output, m_factorType, EOS_);
	m_sentenceEndArray[m_factorType] = m_sentenceEnd;

	MappingBuilder builder(m_factorType, factorCollection, m_lmIdLookup);
	lm::ngram::Config config;

	IFVERBOSE(1) {
		config.messages = &std::cerr;
	} else {
		config.messages = NULL;
	}

	config.enumerate_vocab = &builder;
	config.load_method = m_lazy ? util::LAZY : util::POPULATE_OR_READ;

	m_ngram = new Model(filePath.c_str(), config);
	m_nGramOrder  = m_ngram->Order();

	KenLMState *tmp = new KenLMState();
	tmp->state = m_ngram->NullContextState();
	m_nullContextState = tmp;
	tmp = new KenLMState();
	tmp->state = m_ngram->BeginSentenceState();
	m_beginSentenceState = tmp;
	return true;
}

template <class Model> float LanguageModelKen<Model>::GetValueGivenState(const std::vector<const Word*> &contextFactor, FFState &state, unsigned int* len) const
{
	if (contextFactor.empty())
	{
		return 0;
	}
	lm::ngram::State &realState = static_cast<KenLMState&>(state).state;
	std::size_t factor = contextFactor.back()->GetFactor(GetFactorType())->GetId();
	lm::WordIndex new_word = (factor >= m_lmIdLookup.size() ? 0 : m_lmIdLookup[factor]);
	lm::ngram::State copied(realState);
	lm::FullScoreReturn ret(m_ngram->FullScore(copied, new_word, realState));

	if (len)
	{
		*len = ret.ngram_length;
	}
	return TransformLMScore(ret.prob);
}

template <class Model> float LanguageModelKen<Model>::GetValueForgotState(const vector<const Word*> &contextFactor, FFState &outState, unsigned int* len) const
{
	if (contextFactor.empty())
	{
		static_cast<KenLMState&>(outState).state = m_ngram->NullContextState();
		return 0;
	}

	lm::WordIndex indices[contextFactor.size()];
	TranslateIDs(contextFactor, indices);

	lm::FullScoreReturn ret(m_ngram->FullScoreForgotState(indices + 1, indices + contextFactor.size(), indices[0], static_cast<KenLMState&>(outState).state));
	if (len)
	{
		*len = ret.ngram_length;
	}
	return TransformLMScore(ret.prob);
}

template <class Model> void LanguageModelKen<Model>::GetState(const std::vector<const Word*> &contextFactor, FFState &outState) const {
	if (contextFactor.empty()) {
		static_cast<KenLMState&>(outState).state = m_ngram->NullContextState();
		return;
	}
	lm::WordIndex indices[contextFactor.size()];
	TranslateIDs(contextFactor, indices);
	m_ngram->GetState(indices, indices + contextFactor.size(), static_cast<KenLMState&>(outState).state);
}

template <class Model> FFState *LanguageModelKen<Model>::GetNullContextState() const {
	return m_nullContextState;
}

template <class Model> FFState *LanguageModelKen<Model>::GetBeginSentenceState() const {
	return m_beginSentenceState;
}

template <class Model> FFState *LanguageModelKen<Model>::NewState(const FFState *from) const {
	KenLMState *ret = new KenLMState;
	if (from) {
		ret->state = static_cast<const KenLMState&>(*from).state;
	}
	return ret;
}

template <class Model> lm::WordIndex LanguageModelKen<Model>::GetLmID(const std::string &str) const {
	return m_ngram->GetVocabulary().Index(str);
}

} // namespace

LanguageModelSingleFactor *ConstructKenLM(const std::string &file, bool lazy) {
	lm::ngram::ModelType model_type;
	if (lm::ngram::RecognizeBinary(file.c_str(), model_type)) {
		switch(model_type) {
			case lm::ngram::HASH_PROBING:
				return new LanguageModelKen<lm::ngram::ProbingModel>(lazy);
			case lm::ngram::HASH_SORTED:
				return new LanguageModelKen<lm::ngram::SortedModel>(lazy);
			case lm::ngram::TRIE_SORTED:
				return new LanguageModelKen<lm::ngram::TrieModel>(lazy);
			default:
				std::cerr << "Unrecognized kenlm model type " << model_type << std::endl;
				abort();
		}
	} else {
		return new LanguageModelKen<lm::ngram::ProbingModel>(lazy);
	}
}

}

<|endoftext|>


<commit_before>// testdrive.cpp : An example of how to use rosserial in Windows
//

#include "stdafx.h"
#include <string>
#include <stdio.h>
#include "ros.h"
#include <geometry_msgs/Twist.h>
#include <windows.h>

using std::string;

int main(int argc, char* argv[])
{
	ros::NodeHandle  nh;
	if (argc != 2) {
		printf("Usage: testdrive host[:port]\n");
		return 0;
	}

	printf("Connecting to server at %s\n", argv[1]);
	nh.initNode(argv[1]);

	printf("Advertising cmd_vel message\n");
	geometry_msgs::Twist twist_msg;
	ros::Publisher cmd_vel_pub("husky/cmd_vel", &twist_msg);
	nh.advertise(cmd_vel_pub);

	printf("Go husky go!\n");
	while (1) {
		twist_msg.linear.x = 5.1f;
		twist_msg.angular.z = -1.8f;
		cmd_vel_pub.publish(&twist_msg);

		nh.spinOnce();
		Sleep(100);
	}
	return 0;
}
<commit_msg>Updated sample code to be robot agnostic and fixed unitialized message fields.<commit_after>// testdrive.cpp : An example of how to use rosserial in Windows
//

#include "stdafx.h"
#include <string>
#include <stdio.h>
#include "ros.h"
#include <geometry_msgs/Twist.h>
#include <windows.h>

using std::string;

int main(int argc, char* argv[])
{
	ros::NodeHandle  nh;
	if (argc != 2) {
		printf("Usage: testdrive host[:port]\n");
		return 0;
	}

	printf("Connecting to server at %s\n", argv[1]);
	nh.initNode(argv[1]);

	printf("Advertising cmd_vel message\n");
	geometry_msgs::Twist twist_msg;
	ros::Publisher cmd_vel_pub("cmd_vel", &twist_msg);
	nh.advertise(cmd_vel_pub);

	printf("Go robot go!\n");
	while (1) {
		twist_msg.linear.x = 5.1;
		twist_msg.linear.y = 0;
		twist_msg.linear.z = 0;
		twist_msg.angular.x = 0;
		twist_msg.angular.y = 0;
		twist_msg.angular.z = -1.8;
		cmd_vel_pub.publish(&twist_msg);

		nh.spinOnce();
		Sleep(100);
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "machine/test/test.hpp"

#include "marshal.hpp"

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

class StringUnMarshaller : public UnMarshaller {
public:
  std::istringstream sstream;

  StringUnMarshaller(STATE) : UnMarshaller(state, sstream) { }
};

class TestUnMarshal : public CxxTest::TestSuite, public VMTest {
public:
  StringUnMarshaller* mar;

  void setUp() {
    create();
    mar = new StringUnMarshaller(state);
  }

  void tearDown() {
    destroy();
    delete mar;
  }

  bool tuple_equals(Tuple* x, Tuple* y) {
    if(x->num_fields() != y->num_fields()) return false;
    for(native_int i = 0; i < x->num_fields(); i++) {
      Object* x1 = x->at(state, i);
      Object* y1 = y->at(state, i);

      if(kind_of<Tuple>(x1)) {
        if(!tuple_equals(as<Tuple>(x1), as<Tuple>(y1))) return false;
      } else {
        if(x1 != y1) return false;
      }
    }

    return true;
  }

  void test_nil() {
    mar->sstream.str(std::string("n\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT_EQUALS(obj, cNil);
  }

  void test_true() {
    mar->sstream.str(std::string("t\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT_EQUALS(obj, cTrue);
  }

  void test_false() {
    mar->sstream.str(std::string("f\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT_EQUALS(obj, cFalse);
  }

  void test_int() {
    mar->sstream.str(std::string("I\n42\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT(obj->fixnum_p());
    TS_ASSERT_EQUALS(as<Integer>(obj)->to_native(), 66);
  }

  void test_large_int() {
    mar->sstream.str(std::string("I\n100000000\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<Integer>(obj));
    TS_ASSERT_EQUALS(as<Integer>(obj)->to_ulong_long(), 4294967296ULL);
  }

  void test_larger_int() {
    mar->sstream.str(std::string("I\n9d89d89d89d89dc\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<Integer>(obj));
    TS_ASSERT_EQUALS(as<Integer>(obj)->to_ulong_long(), 709490156681136604ULL);
  }

  void test_string_with_encoding() {
    mar->sstream.str(std::string("s\nE\n10\nASCII-8BIT\n4\nblah\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<String>(obj));
    String *str = as<String>(obj);
    TS_ASSERT_EQUALS(std::string(str->c_str(state)), "blah");
    TS_ASSERT_EQUALS(std::string(str->encoding()->name()->c_str(state)), "ASCII-8BIT");
  }

  void test_string_no_encoding() {
    mar->sstream.str(std::string("s\nE\n0\n\n4\nblah\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<String>(obj));
    String *str = as<String>(obj);
    TS_ASSERT_EQUALS(std::string(str->c_str(state)), "blah");
    TS_ASSERT_EQUALS(str->encoding(), cNil);
  }

  void test_symbol() {
    mar->sstream.str(std::string("x\nE\n8\nUS-ASCII\n4\nblah\n"));
    Object* obj = mar->unmarshal();

    TS_ASSERT(obj->symbol_p());
    TS_ASSERT_EQUALS(obj, state->symbol("blah"));
  }

  void test_tuple() {
    mar->sstream.str(std::string("p\n2\nI\n2\nI\n2f\n"));

    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<Tuple>(obj));

    Tuple* tup = as<Tuple>(obj);

    TS_ASSERT_EQUALS(tup->at(state, 0), Fixnum::from(2));
    TS_ASSERT_EQUALS(tup->at(state, 1), Fixnum::from(47));
  }

  void test_float() {
    mar->sstream.str(
        std::string("d\n +0.666666666666666629659232512494781985878944396972656250    -2\n"));

    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<Float>(obj));

    Float* flt = as<Float>(obj);

    TS_ASSERT_EQUALS(flt->value(), 1.0 / 6.0);

    mar->sstream.str(
        std::string("d\n +0.999999999999999888977697537484345957636833190917968750  1024\n"));
    obj = mar->unmarshal();

    TS_ASSERT(kind_of<Float>(obj));

    flt = as<Float>(obj);

    double diff = flt->value() - DBL_MAX;
    TS_ASSERT(diff < 0.00000001 && diff > - 0.00000001);
  }

  void test_float_infinity() {
    mar->sstream.str(std::string("d\nInfinity\n"));

    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<Float>(obj));

    Float* flt = as<Float>(obj);

    TS_ASSERT(std::isinf(flt->value()));
  }

  void test_float_neg_infinity() {
    mar->sstream.str(std::string("d\n-Infinity\n"));

    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<Float>(obj));

    Float* flt = as<Float>(obj);

    TS_ASSERT(std::isinf(flt->value()));
    TS_ASSERT(flt->value() < 0.0);
  }

  void test_float_nan() {
    mar->sstream.str(std::string("d\nNaN\n"));

    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<Float>(obj));

    Float* flt = as<Float>(obj);

    TS_ASSERT(std::isnan(flt->value()));
  }

  void test_iseq() {
    mar->sstream.str(std::string("i\n1\n0\n"));

    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<InstructionSequence>(obj));

    InstructionSequence* seq = as<InstructionSequence>(obj);

    TS_ASSERT(kind_of<Tuple>(seq->opcodes()));

    TS_ASSERT_EQUALS(seq->opcodes()->num_fields(), 1);

    TS_ASSERT_EQUALS(seq->opcodes()->at(state, 0), Fixnum::from(0));
  }

  void test_compiled_code() {
    std::string str = "M\n1\nn\nx\nE\n8\nUS-ASCII\n12\nobject_equal\nx\nE\n8\nUS-ASCII\n4\ntest\ni\n1\n0\nI\na\nI\n0\nI\n0\nI\n0\nI\n0\nn\np\n2\nx\nE\n8\nUS-ASCII\n1\na\nt\nI\n1\np\n2\nI\n1\nI\n2\np\n1\np\n3\nI\n0\nI\n1\nI\n1\nx\nE\n8\nUS-ASCII\n8\nnot_real\np\n1\nx\nE\n8\nUS-ASCII\n4\nblah\n";
    mar->sstream.str(str);

    Object* obj = mar->unmarshal();

    TS_ASSERT(kind_of<CompiledCode>(obj));

    CompiledCode* code = as<CompiledCode>(obj);

    TS_ASSERT_EQUALS(code->ivars(), cNil);
    TS_ASSERT_EQUALS(code->primitive(), state->symbol("object_equal"));
    TS_ASSERT_EQUALS(code->name(), state->symbol("test"));
    TS_ASSERT(tuple_equals(code->iseq()->opcodes(), Tuple::from(state, 1, Fixnum::from(0))));
    TS_ASSERT_EQUALS(code->stack_size(), Fixnum::from(10));
    TS_ASSERT_EQUALS(code->local_count(), Fixnum::from(0));
    TS_ASSERT_EQUALS(code->required_args(), Fixnum::from(0));
    TS_ASSERT_EQUALS(code->post_args(), Fixnum::from(0));
    TS_ASSERT_EQUALS(code->total_args(), Fixnum::from(0));
    TS_ASSERT_EQUALS(code->splat(), cNil);
    TS_ASSERT(tuple_equals(code->keywords(), Tuple::from(state, 2, state->symbol("a"), cTrue)));
    TS_ASSERT_EQUALS(code->arity(), Fixnum::from(1));
    TS_ASSERT(tuple_equals(code->literals(), Tuple::from(state, 2, Fixnum::from(1), Fixnum::from(2))));
    TS_ASSERT(tuple_equals(code->lines(), Tuple::from(state, 1,
          Tuple::from(state, 3, Fixnum::from(0), Fixnum::from(1), Fixnum::from(1)))));

    TS_ASSERT_EQUALS(code->file(), state->symbol("not_real"));
    TS_ASSERT(tuple_equals(code->local_names(), Tuple::from(state, 1, state->symbol("blah"))));
  }

};
<commit_msg>Remove VM unmarshal tests.<commit_after><|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of the copyright holders may not 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 Intel Corporation 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.
//
//M*/

#ifndef __OPENCV_VIDEOSTAB_HPP__
#define __OPENCV_VIDEOSTAB_HPP__

/**
  @defgroup videostab Video Stabilization

The video stabilization module contains a set of functions and classes that can be used to solve the
problem of video stabilization. There are a few methods implemented, most of them are descibed in
the papers @cite OF06 and @cite G11 . However, there are some extensions and deviations from the orginal
paper methods.

### References

 1. "Full-Frame Video Stabilization with Motion Inpainting"
     Yasuyuki Matsushita, Eyal Ofek, Weina Ge, Xiaoou Tang, Senior Member, and Heung-Yeung Shum
 2. "Auto-Directed Video Stabilization with Robust L1 Optimal Camera Paths"
     Matthias Grundmann, Vivek Kwatra, Irfan Essa

     @{
         @defgroup videostab_motion Global Motion Estimation

The video stabilization module contains a set of functions and classes for global motion estimation
between point clouds or between images. In the last case features are extracted and matched
internally. For the sake of convenience the motion estimation functions are wrapped into classes.
Both the functions and the classes are available.

         @defgroup videostab_marching Fast Marching Method

The Fast Marching Method @cite Telea04 is used in of the video stabilization routines to do motion and
color inpainting. The method is implemented is a flexible way and it's made public for other users.

     @}

*/

#include "opencv2/videostab/stabilizer.hpp"
#include "opencv2/videostab/ring_buffer.hpp"

#endif
<commit_msg>Fixes minor typos.<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of the copyright holders may not 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 Intel Corporation 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.
//
//M*/

#ifndef __OPENCV_VIDEOSTAB_HPP__
#define __OPENCV_VIDEOSTAB_HPP__

/**
  @defgroup videostab Video Stabilization

The video stabilization module contains a set of functions and classes that can be used to solve the
problem of video stabilization. There are a few methods implemented, most of them are described in
the papers @cite OF06 and @cite G11 . However, there are some extensions and deviations from the original
paper methods.

### References

 1. "Full-Frame Video Stabilization with Motion Inpainting"
     Yasuyuki Matsushita, Eyal Ofek, Weina Ge, Xiaoou Tang, Senior Member, and Heung-Yeung Shum
 2. "Auto-Directed Video Stabilization with Robust L1 Optimal Camera Paths"
     Matthias Grundmann, Vivek Kwatra, Irfan Essa

     @{
         @defgroup videostab_motion Global Motion Estimation

The video stabilization module contains a set of functions and classes for global motion estimation
between point clouds or between images. In the last case features are extracted and matched
internally. For the sake of convenience the motion estimation functions are wrapped into classes.
Both the functions and the classes are available.

         @defgroup videostab_marching Fast Marching Method

The Fast Marching Method @cite Telea04 is used in of the video stabilization routines to do motion and
color inpainting. The method is implemented is a flexible way and it's made public for other users.

     @}

*/

#include "opencv2/videostab/stabilizer.hpp"
#include "opencv2/videostab/ring_buffer.hpp"

#endif
<|endoftext|>


<commit_before>
#include "stdafx.h"
#include "fixes.h"

class SizeColossalFix : public TempleFix {
public:
	const char* name() override {
		return "fixes size_colossal (was misspelled as size_clossal)";
	}

	void apply() override {
		writeHex(0x10278078, "73 69 7A 65 5F 63 6F 6C 6F 73 73 61 6C");
	}
} sizeColossalFix;
<commit_msg>Kukri as Martial Weapon partial fix<commit_after>
#include "stdafx.h"
#include "fixes.h"

class SizeColossalFix : public TempleFix {
public:
	const char* name() override {
		return "fixes size_colossal (was misspelled as size_clossal)";
	}

	void apply() override {
		writeHex(0x10278078, "73 69 7A 65 5F 63 6F 6C 6F 73 73 61 6C");
	}
} sizeColossalFix;

class KukriFix : public TempleFix {
public:
	const char* name() override {
		return "Makes Kukri Proficiency Martial";
	}

	void apply() override {
		writeHex(0x102BFD78 + 30*4, "00 09"); // marks Kukri as Martial in the sense that picking "Martial Weapons Proficiency" will now list Kukri
		// TODO: makes the feat "Martial Weapons Proficiency: All" include Kukri proficiency
	}
} kukriFix;
<|endoftext|>