<commit_before>/**
* Copyright (c) 2014-2016 Dallin Wellington
*
*/

#include <Platform/Platform.h>

#ifdef MONSOON_OS_WINDOWS

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <sstream>

#include <App/Application.h>
#include <Math/Vector.h>
#include <D3D11Renderer.h>

#include "HgtReader.h"
#include "GCS.h"

#include <fstream>

using namespace Monsoon;
using namespace Monsoon::Math;

const U32 numChunks = 4; // The number of chunks to render as a square. (Must be greater than 2).
const int chunkXOffset = 8;
const int chunkYOffset = 12;

const float peakViewX = -1897.81921;
const float peakViewZ = -3074.84082;

const float WorldScale = 1.0f;

float FirstPersonCameraSpeed = 1000.0f;

/**
 * Viewing Modes
 */
enum VIEW_MODE
{
	DEFAULT,
	PEAK,
	TRAIL,
	FIRST_PERSON
};

VIEW_MODE cameraMode = VIEW_MODE::FIRST_PERSON;
const GcsLocation startLocation = GcsLocation(GcsCoord(39, 0, 0), GcsCoord(107, 0, 0));

class TerrainApplication : public Application
{
public:
	TerrainApplication()
		: Application((Renderer::Renderer*)(new Renderer::D3D11Renderer(Renderer::RendererSettings(), &mEventManager, &mTransformSystem)))
		, mFileReader()
		, mFirstPersonPosition(0.0f, 0.0f, 0.0f)
		, mFirstPersonDirection(0.0f, 0.0f, 0.0f)
		, cameraTheta(0.0f)
		, cameraPhi(0.0f)
		, mFirstPersonCursorOn(false) {

		std::stringstream filename;
		filename << "I:/terrain/" << "N" << startLocation.latitude.degrees << "W" << startLocation.longitude.degrees << "-2.hgt";
		mFileReader.Load(filename.str().c_str());
		chunkSize = ceil(sqrt((mFileReader.GetResolution() * mFileReader.GetResolution()) / 256));
	}

	~TerrainApplication() {

	}

protected:
	float cameraTheta; // Yaw
	float cameraPhi; // Pitch
	float cameraZoom;
	Vector3 mFirstPersonPosition;
	Vector3 mFirstPersonDirection;
	HGTReader mFileReader;
	float cursorX;
	float cursorY;
	float cursorDiffX;
	float cursorDiffY;
	bool mFirstPersonCursorOn;
	U32 chunkSize = 0; // The number of points on a single side of a chunk. The number of total points is chunkSize ^ 2. Set dynamically after loading the HGT file.

	Renderer::VertexBufferHandle* chunkVertexBuffers;
	Renderer::MeshComponent* chunkMeshes;
	Scene::TransformComponent* chunkPositions;
	Renderer::TextureHandle* chunkTextures;
	std::stringstream*	textureFiles;
	Renderer::MeshComponent skydomeMesh;

	void OnInitialize() {
		chunkVertexBuffers = new Renderer::VertexBufferHandle[numChunks * numChunks]();
		chunkMeshes = new Renderer::MeshComponent[numChunks * numChunks]();
		chunkPositions = new Scene::TransformComponent[numChunks * numChunks]();
		chunkTextures = new Renderer::TextureHandle[numChunks * numChunks]();
		textureFiles = new std::stringstream[numChunks * numChunks]();

		Vector2 cartesian = GcsToCartesian(GcsCoord(35, 0, 0), GcsCoord(112, 0, 0));
		mFirstPersonPosition = Vector3(cartesian.mX * 90.0f * WorldScale, 4394.12f, cartesian.mY * 90.0f * WorldScale);

		//
		// Generate Skydome
		//
		mRenderer->CreateGradientSkydome(Math::Vector3(0.0f, 0.0f, 0.0f), Math::Vector3(0.0f, 0.0f, 0.0f));

		//
		// Generate Texture Map
		//
		int textureMap[16][16];
		int x = 0;
		int y = 0;
		int index = 0;
		for (int i = 0; i < (256/4); i++)
		{
			textureMap[x][y] = index + 1;
			textureMap[1+x][y] = index;
			textureMap[x][1+y] = index + 3;
			textureMap[1+x][1+y] = index + 2;
			x += 2;

			if (x >= 16) {
				x = 0;
				y += 2;
			}

			index += 4;
		}

		for (int x = 0; x < numChunks; x++)
		{
			for (int y = 0; y < numChunks; y++)
			{
				int index = y + (x * numChunks);

				textureFiles[index] << "I:/terrain/" << "N" << startLocation.latitude.degrees << "W" << startLocation.longitude.degrees << "/" << textureMap[x + chunkXOffset][y + chunkYOffset] << ".tif" << '\0';

				chunkVertexBuffers[index] = generateTerrain(x + chunkXOffset, y + chunkYOffset);
				chunkTextures[index] = mRenderer->LoadTexture(textureFiles[index].str());

				chunkMeshes[index].TextureId = chunkTextures[index];
				chunkMeshes[index].VertexBuffer = chunkVertexBuffers[index];

				chunkPositions[index].position += Vector3((y * 90.0f * WorldScale * (chunkSize - 1)), 0.0f, (x * 90.0f * WorldScale * (chunkSize - 1)));
				Vector2 cartesian = GcsToCartesian(startLocation.latitude, startLocation.longitude);
				chunkPositions[index].position += Vector3(cartesian.mX, 0.0f, cartesian.mY);

				mRenderer->AttachMeshComponent(index, chunkMeshes[index]);
				mTransformSystem.AttachComponent(index, chunkPositions[index]);
			}
		}

		cameraTheta = 0.0f;
		cameraZoom = 1.0f;

		Renderer::Camera& camera = mRenderer->GetCamera();
		camera.y = mFileReader.mMaxHeight + 3000.0f;
		camera.lookAtY = mFileReader.mMinHeight + 1700.0f;

		PollMousePosition();
	}

	void PollMousePosition() {
		float x = 0;
		float y = 0;

		POINT cursorPosition;
		GetCursorPos(&cursorPosition);

		x = cursorPosition.x;
		y = cursorPosition.y;

		cursorDiffX = x - cursorX;
		cursorDiffY = y - cursorY;

		cursorX = x;
		cursorY = y;
	}

	void OnUpdate() {
		Renderer::Camera& camera = mRenderer->GetCamera();

		switch (cameraMode)
		{
		case VIEW_MODE::DEFAULT:
			camera.lookAtX = 0;
			camera.lookAtZ = 0;
			camera.x = cos(cameraTheta) * ((float)chunkSize * (float)numChunks / 2.0f * WorldScale) * cameraZoom;
			camera.z = sin(cameraTheta) * ((float)chunkSize * (float)numChunks / 2.0f * WorldScale) * cameraZoom;
			break;
		case VIEW_MODE::PEAK:
			camera.x = peakViewX;
			camera.z = peakViewZ;
			camera.lookAtX = camera.x + (cos(cameraTheta) * 500.0f);
			camera.lookAtZ = camera.z + (sin(cameraTheta) * 500.0f);
			camera.lookAtY = 4394.12f; //mFileReader.mHeightMap[(int)camera.x][(int)camera.z] + 5.0f;
			camera.y = 4394.12f; //mFileReader.mHeightMap[(int)camera.x][(int)camera.z] + 5.0f;
			break;
		case VIEW_MODE::FIRST_PERSON:
			mFirstPersonDirection = Vector3(cos(cameraTheta), sin(cameraPhi), sin(cameraTheta));
			camera.x = mFirstPersonPosition.mX;
			camera.z = mFirstPersonPosition.mZ;
			camera.y = mFirstPersonPosition.mY;
			camera.lookAtX = camera.x + (mFirstPersonDirection.mX);
			camera.lookAtZ = camera.z + (mFirstPersonDirection.mZ);
			camera.lookAtY = camera.y + (mFirstPersonDirection.mY);
			break;
		}

		camera.farClip = 1000000.0f;

		U16 leftKeyState = GetAsyncKeyState(VK_LEFT);
		U16 rightKeyState = GetAsyncKeyState(VK_RIGHT);
		U16 upKeyState = GetAsyncKeyState(VK_UP);
		U16 downKeyState = GetAsyncKeyState(VK_DOWN);
		U16 spaceKeyState = GetAsyncKeyState(VK_SPACE);
		U16 leftShiftKeyState = GetAsyncKeyState(0xA0);

		U16 rightMouseState = GetAsyncKeyState(VK_RBUTTON);
		U16 leftMouseState = GetAsyncKeyState(VK_LBUTTON);

		U16 wKeyState = GetAsyncKeyState(0x57);
		U16 aKeyState = GetAsyncKeyState(0x41);
		U16 sKeyState = GetAsyncKeyState(0x53);
		U16 dKeyState = GetAsyncKeyState(0x44);
		U16 qKeyState = GetAsyncKeyState(0x51);
		U16 eKeyState = GetAsyncKeyState(0x45);

		//
		// Default View Controls
		//
		if (leftKeyState)
			cameraTheta += mGameClock.getDeltaTime()/4.0f;
		if (rightKeyState)
			cameraTheta -= mGameClock.getDeltaTime() / 4.0f;
		if (upKeyState)
			cameraZoom -= mGameClock.getDeltaTime() / 4.0f;
		if (downKeyState)
			cameraZoom += mGameClock.getDeltaTime() / 4.0f;

		//
		// First Person View Controls
		//
		if (wKeyState)
		{
			mFirstPersonPosition += mFirstPersonDirection * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (aKeyState)
		{
			mFirstPersonPosition += Vector3(cos((3 * PI) / 2 + cameraTheta), 0.0f, sin((3 * PI) / 2 + cameraTheta)) * -1.0f * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (sKeyState)
		{
			mFirstPersonPosition += mFirstPersonDirection * (-1.0f) * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (dKeyState)
		{
			mFirstPersonPosition += Vector3(cos((3 * PI) / 2 + cameraTheta), 0.0f, sin((3 * PI) / 2 + cameraTheta)) * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (spaceKeyState)
			mQuit = true;

		if (leftMouseState)
			FirstPersonCameraSpeed += mGameClock.getDeltaTime() * 100.0f;
		if (rightMouseState)
			FirstPersonCameraSpeed -= mGameClock.getDeltaTime() * 100.0f;

		if (cameraZoom <= 0.0f)
			cameraZoom = 0.001f;

		if (!mFirstPersonCursorOn)
		{
			ShowCursor(false);
			PollMousePosition();

			cameraTheta -= cursorDiffX * mGameClock.getDeltaTime() / 10.0f;
			cameraPhi -= cursorDiffY * mGameClock.getDeltaTime() / 10.0f;

			if (cameraPhi > PI / 2)
				cameraPhi = PI / 2;
			if (cameraPhi < -PI/2)
				cameraPhi = -PI / 2;

			SetCursorPos(1280.0f / 2.0f, 800.0f / 2.0f);
			cursorX = 1280.0f / 2.0f;
			cursorY = 800.0f / 2.0f;
		}
	}

	void OnShutdown() {
		for (int x = 0; x < numChunks / 2.0f; x++)
		{
			for (int y = 0; y < numChunks / 2.0f; y++)
			{
				int index = (x * chunkSize) + y;

				mTransformSystem.DetachComponent(index);
				mRenderer->DetachMeshComponent(index);
				mRenderer->ReleaseTexture(index);
			}
		}

		mRenderer->DetachMeshComponent(1000);
		mTransformSystem.DetachComponent(1000);

		delete textureFiles;
		delete chunkTextures;
		delete chunkPositions;
		delete chunkMeshes;
		delete chunkVertexBuffers;
	}

	Renderer::VertexBufferHandle generateTerrain(U32 chunkX, U32 chunkY) {
		Renderer::VertexType* vertices = new Renderer::VertexType[chunkSize * chunkSize];
		unsigned int* indicies = new unsigned int[6 * ((chunkSize - 1) * (chunkSize - 1))];

		int yOffset = chunkX * (chunkSize - 1);
		int xOffset = chunkY * (chunkSize - 1);

		// Generate Vertices
		for (int x = 0; x < chunkSize; x++)
		{
			for (int y = 0; y < chunkSize; y++)
			{
				float height = mFileReader.mHeightMap[x + xOffset][y + yOffset];
				float color = (mFileReader.mHeightMap[x + xOffset][y + yOffset] - mFileReader.mMinHeight) / (mFileReader.mMaxHeight - mFileReader.mMinHeight);
				vertices[(x * chunkSize) + y].SetPosition(x * 90.0f * WorldScale, mFileReader.mHeightMap[x + xOffset][y + yOffset] * 4.0f, y * 90.0f * WorldScale); // This is where i'll convert to simulation world coords for scaling.
				vertices[(x * chunkSize) + y].SetColor(color, color, color, 1.0f);
				vertices[(x * chunkSize) + y].SetUV((float)(y) / (float)chunkSize, (float)(x) / (float)chunkSize);
			}
		}

		// Generate Indicies
		int i = 0;
		for (int z = 0; z < (chunkSize - 1); z++)
		{
			for (int d = 0; d < (chunkSize - 1); d++)
			{
				int index = (z * chunkSize) + d;
				indicies[i] = index + chunkSize;
				indicies[i + 1] = index;
				indicies[i + 2] = index + 1;
				indicies[i + 3] = index + chunkSize;
				indicies[i + 4] = index + 1;
				indicies[i + 5] = index + chunkSize + 1;

				i += 6;
			}
		}

		return mRenderer->CreateVertexBuffer(vertices, chunkSize * chunkSize, indicies, 6 * ((chunkSize - 1) * (chunkSize - 1)));
	}

};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) {
	TerrainApplication application;
	application.Run();
	return 0;
}

#endif<commit_msg>Improved estimation of true scale.<commit_after>/**
* Copyright (c) 2014-2016 Dallin Wellington
*
*/

#include <Platform/Platform.h>

#ifdef MONSOON_OS_WINDOWS

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <sstream>

#include <App/Application.h>
#include <Math/Vector.h>
#include <D3D11Renderer.h>

#include "HgtReader.h"
#include "GCS.h"

#include <fstream>

using namespace Monsoon;
using namespace Monsoon::Math;

const U32 numChunks = 4; // The number of chunks to render as a square. (Must be greater than 2).
const int chunkXOffset = 8;
const int chunkYOffset = 12;

const float peakViewX = -1897.81921;
const float peakViewZ = -3074.84082;

const float SurfaceLengthMi = 2 * PI *  3959.0f;
const float WorldScale = SurfaceLengthMi / (360.0f);

float FirstPersonCameraSpeed = 4.0f;

/**
 * Viewing Modes
 */
enum VIEW_MODE
{
	DEFAULT,
	PEAK,
	TRAIL,
	FIRST_PERSON
};

VIEW_MODE cameraMode = VIEW_MODE::FIRST_PERSON;
const GcsLocation startLocation = GcsLocation(GcsCoord(39, 0, 0), GcsCoord(107, 0, 0));

class TerrainApplication : public Application
{
public:
	TerrainApplication()
		: Application((Renderer::Renderer*)(new Renderer::D3D11Renderer(Renderer::RendererSettings(), &mEventManager, &mTransformSystem)))
		, mFileReader()
		, mFirstPersonPosition(0.0f, 0.0f, 0.0f)
		, mFirstPersonDirection(0.0f, 0.0f, 0.0f)
		, cameraTheta(0.0f)
		, cameraPhi(0.0f)
		, mFirstPersonCursorOn(false) {

		std::stringstream filename;
		filename << "I:/terrain/" << "N" << abs(startLocation.latitude.degrees) << "W" << abs(startLocation.longitude.degrees) << "-2.hgt";
		mFileReader.Load(filename.str().c_str());
		chunkSize = ceil(sqrt((mFileReader.GetResolution() * mFileReader.GetResolution()) / 256));
	}

	~TerrainApplication() {

	}

protected:
	float cameraTheta; // Yaw
	float cameraPhi; // Pitch
	float cameraZoom;
	Vector3 mFirstPersonPosition;
	Vector3 mFirstPersonDirection;
	HGTReader mFileReader;
	float cursorX;
	float cursorY;
	float cursorDiffX;
	float cursorDiffY;
	bool mFirstPersonCursorOn;
	U32 chunkSize = 0; // The number of points on a single side of a chunk. The number of total points is chunkSize ^ 2. Set dynamically after loading the HGT file.

	Renderer::VertexBufferHandle* chunkVertexBuffers;
	Renderer::MeshComponent* chunkMeshes;
	Scene::TransformComponent* chunkPositions;
	Renderer::TextureHandle* chunkTextures;
	std::stringstream*	textureFiles;
	Renderer::MeshComponent skydomeMesh;

	void OnInitialize() {
		chunkVertexBuffers = new Renderer::VertexBufferHandle[numChunks * numChunks]();
		chunkMeshes = new Renderer::MeshComponent[numChunks * numChunks]();
		chunkPositions = new Scene::TransformComponent[numChunks * numChunks]();
		chunkTextures = new Renderer::TextureHandle[numChunks * numChunks]();
		textureFiles = new std::stringstream[numChunks * numChunks]();

		Vector2 cartesian = GcsToCartesian(startLocation.latitude, startLocation.longitude);
		mFirstPersonPosition = Vector3(cartesian.mX, 4394.12f/80.0f, cartesian.mY);

		//
		// Generate Skydome
		//
		mRenderer->CreateGradientSkydome(Math::Vector3(0.0f, 0.0f, 0.0f), Math::Vector3(0.0f, 0.0f, 0.0f));

		//
		// Generate Texture Map
		//
		int textureMap[16][16];
		int x = 0;
		int y = 0;
		int index = 0;
		for (int i = 0; i < (256/4); i++)
		{
			textureMap[x][y] = index + 1;
			textureMap[1+x][y] = index;
			textureMap[x][1+y] = index + 3;
			textureMap[1+x][1+y] = index + 2;
			x += 2;

			if (x >= 16) {
				x = 0;
				y += 2;
			}

			index += 4;
		}

		for (int x = 0; x < numChunks; x++)
		{
			for (int y = 0; y < numChunks; y++)
			{
				int index = y + (x * numChunks);

				textureFiles[index] << "I:/terrain/" << "N" << startLocation.latitude.degrees << "W" << startLocation.longitude.degrees << "/" << textureMap[x + chunkXOffset][y + chunkYOffset] << ".tif" << '\0';

				chunkVertexBuffers[index] = generateTerrain(x + chunkXOffset, y + chunkYOffset);
				chunkTextures[index] = mRenderer->LoadTexture(textureFiles[index].str());

				chunkMeshes[index].TextureId = chunkTextures[index];
				chunkMeshes[index].VertexBuffer = chunkVertexBuffers[index];

				chunkPositions[index].position += Vector3((((float)y/(float)chunkSize) * WorldScale * (chunkSize - 1)), 0.0f, (((float)x/(float)chunkSize) * WorldScale * (chunkSize - 1)));
				Vector2 cartesian = GcsToCartesian(startLocation.latitude, startLocation.longitude);
				chunkPositions[index].position += Vector3(cartesian.mX, 0.0f, cartesian.mY);

				mRenderer->AttachMeshComponent(index, chunkMeshes[index]);
				mTransformSystem.AttachComponent(index, chunkPositions[index]);
			}
		}

		cameraTheta = 0.0f;
		cameraZoom = 1.0f;

		Renderer::Camera& camera = mRenderer->GetCamera();
		camera.y = mFileReader.mMaxHeight + 3000.0f;

		PollMousePosition();
	}

	void PollMousePosition() {
		float x = 0;
		float y = 0;

		POINT cursorPosition;
		GetCursorPos(&cursorPosition);

		x = cursorPosition.x;
		y = cursorPosition.y;

		cursorDiffX = x - cursorX;
		cursorDiffY = y - cursorY;

		cursorX = x;
		cursorY = y;
	}

	void OnUpdate() {
		Renderer::Camera& camera = mRenderer->GetCamera();

		switch (cameraMode)
		{
		case VIEW_MODE::DEFAULT:
			camera.lookAtX = 0;
			camera.lookAtZ = 0;
			camera.x = cos(cameraTheta) * ((float)chunkSize * (float)numChunks / 2.0f * WorldScale) * cameraZoom;
			camera.z = sin(cameraTheta) * ((float)chunkSize * (float)numChunks / 2.0f * WorldScale) * cameraZoom;
			break;
		case VIEW_MODE::PEAK:
			camera.x = peakViewX;
			camera.z = peakViewZ;
			camera.lookAtX = camera.x + (cos(cameraTheta) * 500.0f);
			camera.lookAtZ = camera.z + (sin(cameraTheta) * 500.0f);
			camera.lookAtY = 4394.12f; //mFileReader.mHeightMap[(int)camera.x][(int)camera.z] + 5.0f;
			camera.y = 4394.12f; //mFileReader.mHeightMap[(int)camera.x][(int)camera.z] + 5.0f;
			break;
		case VIEW_MODE::FIRST_PERSON:
			mFirstPersonDirection = Vector3(cos(cameraTheta), sin(cameraPhi), sin(cameraTheta));
			camera.x = mFirstPersonPosition.mX;
			camera.z = mFirstPersonPosition.mZ;
			camera.y = mFirstPersonPosition.mY;
			camera.lookAtX = camera.x + (mFirstPersonDirection.mX);
			camera.lookAtZ = camera.z + (mFirstPersonDirection.mZ);
			camera.lookAtY = camera.y + (mFirstPersonDirection.mY);
			break;
		}

		camera.farClip = 1000000.0f;

		U16 leftKeyState = GetAsyncKeyState(VK_LEFT);
		U16 rightKeyState = GetAsyncKeyState(VK_RIGHT);
		U16 upKeyState = GetAsyncKeyState(VK_UP);
		U16 downKeyState = GetAsyncKeyState(VK_DOWN);
		U16 spaceKeyState = GetAsyncKeyState(VK_SPACE);
		U16 leftShiftKeyState = GetAsyncKeyState(0xA0);

		U16 rightMouseState = GetAsyncKeyState(VK_RBUTTON);
		U16 leftMouseState = GetAsyncKeyState(VK_LBUTTON);

		U16 wKeyState = GetAsyncKeyState(0x57);
		U16 aKeyState = GetAsyncKeyState(0x41);
		U16 sKeyState = GetAsyncKeyState(0x53);
		U16 dKeyState = GetAsyncKeyState(0x44);
		U16 qKeyState = GetAsyncKeyState(0x51);
		U16 eKeyState = GetAsyncKeyState(0x45);

		//
		// Default View Controls
		//
		if (leftKeyState)
			cameraTheta += mGameClock.getDeltaTime()/4.0f;
		if (rightKeyState)
			cameraTheta -= mGameClock.getDeltaTime() / 4.0f;
		if (upKeyState)
			cameraZoom -= mGameClock.getDeltaTime() / 4.0f;
		if (downKeyState)
			cameraZoom += mGameClock.getDeltaTime() / 4.0f;

		//
		// First Person View Controls
		//
		if (wKeyState)
		{
			mFirstPersonPosition += mFirstPersonDirection * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (aKeyState)
		{
			mFirstPersonPosition += Vector3(cos((3 * PI) / 2 + cameraTheta), 0.0f, sin((3 * PI) / 2 + cameraTheta)) * -1.0f * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (sKeyState)
		{
			mFirstPersonPosition += mFirstPersonDirection * (-1.0f) * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (dKeyState)
		{
			mFirstPersonPosition += Vector3(cos((3 * PI) / 2 + cameraTheta), 0.0f, sin((3 * PI) / 2 + cameraTheta)) * mGameClock.getDeltaTime() * FirstPersonCameraSpeed;
		}
		if (spaceKeyState)
			mQuit = true;

		if (leftMouseState)
			FirstPersonCameraSpeed += mGameClock.getDeltaTime() * 100.0f;
		if (rightMouseState)
			FirstPersonCameraSpeed -= mGameClock.getDeltaTime() * 100.0f;

		if (cameraZoom <= 0.0f)
			cameraZoom = 0.001f;

		if (!mFirstPersonCursorOn)
		{
			ShowCursor(false);
			PollMousePosition();

			cameraTheta -= cursorDiffX * mGameClock.getDeltaTime() / 10.0f;
			cameraPhi -= cursorDiffY * mGameClock.getDeltaTime() / 10.0f;

			if (cameraPhi > PI / 2)
				cameraPhi = PI / 2;
			if (cameraPhi < -PI/2)
				cameraPhi = -PI / 2;

			SetCursorPos(1280.0f / 2.0f, 800.0f / 2.0f);
			cursorX = 1280.0f / 2.0f;
			cursorY = 800.0f / 2.0f;
		}
	}

	void OnShutdown() {
		for (int x = 0; x < numChunks / 2.0f; x++)
		{
			for (int y = 0; y < numChunks / 2.0f; y++)
			{
				int index = (x * chunkSize) + y;

				mTransformSystem.DetachComponent(index);
				mRenderer->DetachMeshComponent(index);
				mRenderer->ReleaseTexture(index);
			}
		}

		mRenderer->DetachMeshComponent(1000);
		mTransformSystem.DetachComponent(1000);

		delete textureFiles;
		delete chunkTextures;
		delete chunkPositions;
		delete chunkMeshes;
		delete chunkVertexBuffers;
	}

	Renderer::VertexBufferHandle generateTerrain(U32 chunkX, U32 chunkY) {
		Renderer::VertexType* vertices = new Renderer::VertexType[chunkSize * chunkSize];
		unsigned int* indicies = new unsigned int[6 * ((chunkSize - 1) * (chunkSize - 1))];

		int yOffset = chunkX * (chunkSize - 1);
		int xOffset = chunkY * (chunkSize - 1);

		// Generate Vertices
		for (int x = 0; x < chunkSize; x++)
		{
			for (int y = 0; y < chunkSize; y++)
			{
				float height = mFileReader.mHeightMap[x + xOffset][y + yOffset];
				float color = (mFileReader.mHeightMap[x + xOffset][y + yOffset] - mFileReader.mMinHeight) / (mFileReader.mMaxHeight - mFileReader.mMinHeight);
				vertices[(x * chunkSize) + y].SetPosition(((float)x/(float)chunkSize) * WorldScale, mFileReader.mHeightMap[x + xOffset][y + yOffset]/80.0f, ((float)y/(float)chunkSize) * WorldScale); // This is where i'll convert to simulation world coords for scaling.
				vertices[(x * chunkSize) + y].SetColor(color, color, color, 1.0f);
				vertices[(x * chunkSize) + y].SetUV((float)(y) / (float)chunkSize, (float)(x) / (float)chunkSize);
			}
		}

		// Generate Indicies
		int i = 0;
		for (int z = 0; z < (chunkSize - 1); z++)
		{
			for (int d = 0; d < (chunkSize - 1); d++)
			{
				int index = (z * chunkSize) + d;
				indicies[i] = index + chunkSize;
				indicies[i + 1] = index;
				indicies[i + 2] = index + 1;
				indicies[i + 3] = index + chunkSize;
				indicies[i + 4] = index + 1;
				indicies[i + 5] = index + chunkSize + 1;

				i += 6;
			}
		}

		return mRenderer->CreateVertexBuffer(vertices, chunkSize * chunkSize, indicies, 6 * ((chunkSize - 1) * (chunkSize - 1)));
	}

};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) {
	TerrainApplication application;
	application.Run();
	return 0;
}

#endif<|endoftext|>


<commit_before>#include <QSettings>
#include <QDebug>
#include <QCoreApplication>
#include <QFile>
#include <QSound>

#include "QGC.h"
#include "QGCAudioWorker.h"
#include "GAudioOutput.h"

#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
#include <ApplicationServices/ApplicationServices.h>
#endif

// Speech synthesis is only supported with MSVC compiler
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
#include <sapi.h>
#endif

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
// Using eSpeak for speech synthesis: following https://github.com/mondhs/espeak-sample/blob/master/sampleSpeak.cpp
#include <espeak/speak_lib.h>
#endif

#define QGC_GAUDIOOUTPUT_KEY QString("QGC_AUDIOOUTPUT_")

QGCAudioWorker::QGCAudioWorker(QObject *parent) :
    QObject(parent),
    voiceIndex(0),
    emergency(false),
    muted(false),
    #if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice(NULL),
    #endif
    sound(NULL)
{
    // Load settings
    QSettings settings;
    muted = settings.value(QGC_GAUDIOOUTPUT_KEY + "muted", muted).toBool();
}

void QGCAudioWorker::init()
{
    sound = new QSound("");

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 500, NULL, 0); // initialize for playback with 500ms buffer and no options (see speak_lib.h)
    espeak_VOICE *espeak_voice = espeak_GetCurrentVoice();
    espeak_voice->languages = "en-uk"; // Default to British English
    espeak_voice->identifier = NULL; // no specific voice file specified
    espeak_voice->name = "klatt"; // espeak voice name
    espeak_voice->gender = 2; // Female
    espeak_voice->age = 0; // age not specified
    espeak_SetVoiceByProperties(espeak_voice);
#endif

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED

    if (FAILED(::CoInitialize(NULL)))
    {
        qDebug() << "ERROR: Creating COM object for audio output failed!";
    }
    else
    {

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

        if (FAILED(hr))
        {
            qDebug() << "ERROR: Initializing voice for audio output failed!";
        }
    }

#endif

    // Prepare regular emergency signal, will be fired off on calling startEmergency()
    emergencyTimer = new QTimer();
    connect(emergencyTimer, SIGNAL(timeout()), this, SLOT(beep()));
}

QGCAudioWorker::~QGCAudioWorker()
{
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice->Release();
    pVoice = NULL;
    ::CoUninitialize();
#endif
}

void QGCAudioWorker::say(QString text, int severity)
{
    if (!muted)
    {
        // Prepend high priority text with alert beep
        if (severity < GAudioOutput::AUDIO_SEVERITY_CRITICAL) {
            beep();
        }

        // Wait for the last sound to finish
        while (!sound->isFinished()) {
            QGC::SLEEP::msleep(100);
        }

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
        pVoice->Speak(text.toStdWString().c_str(), SPF_DEFAULT, NULL);

#elif defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
        // Set size of string for espeak: +1 for the null-character
        unsigned int espeak_size = strlen(text.toStdString().c_str()) + 1;
        espeak_Synth(text.toStdString().c_str(), espeak_size, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);

#elif defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
        // Slashes necessary to have the right start to the sentence
        // copying data prevents SpeakString from reading additional chars
        text = "\\" + text;
        std::wstring str = text.toStdWString();
        unsigned char str2[1024] = {};
        memcpy(str2, text.toLatin1().data(), str.length());
        SpeakString(str2);

        // Block the thread while busy
        // because we run in our own thread, this doesn't
        // halt the main application
        while (SpeechBusy()) {
            QGC::SLEEP::msleep(100);
        }

#else
        // Make sure there isn't an unused variable warning when speech output is disabled
        Q_UNUSED(text);
#endif
    }
}

void QGCAudioWorker::mute(bool mute)
{
    if (mute != muted)
    {
        this->muted = mute;
        QSettings settings;
        settings.setValue(QGC_GAUDIOOUTPUT_KEY + "muted", this->muted);
//        emit mutedChanged(muted);
    }
}

void QGCAudioWorker::beep()
{

    if (!muted)
    {
        // Use QFile to transform path for all OS
        QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/alert.wav"));
        sound->play(f.fileName());
    }
}

bool QGCAudioWorker::isMuted()
{
    return this->muted;
}
<commit_msg>Revert "Make eSpeak on Linux synchronous"<commit_after>#include <QSettings>
#include <QDebug>
#include <QCoreApplication>
#include <QFile>
#include <QSound>

#include "QGC.h"
#include "QGCAudioWorker.h"
#include "GAudioOutput.h"

#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
#include <ApplicationServices/ApplicationServices.h>
#endif

// Speech synthesis is only supported with MSVC compiler
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
#include <sapi.h>
#endif

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
// Using eSpeak for speech synthesis: following https://github.com/mondhs/espeak-sample/blob/master/sampleSpeak.cpp
#include <espeak/speak_lib.h>
#endif

#define QGC_GAUDIOOUTPUT_KEY QString("QGC_AUDIOOUTPUT_")

QGCAudioWorker::QGCAudioWorker(QObject *parent) :
    QObject(parent),
    voiceIndex(0),
    emergency(false),
    muted(false),
    #if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice(NULL),
    #endif
    sound(NULL)
{
    // Load settings
    QSettings settings;
    muted = settings.value(QGC_GAUDIOOUTPUT_KEY + "muted", muted).toBool();
}

void QGCAudioWorker::init()
{
    sound = new QSound("");

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 500, NULL, 0); // initialize for playback with 500ms buffer and no options (see speak_lib.h)
    espeak_VOICE *espeak_voice = espeak_GetCurrentVoice();
    espeak_voice->languages = "en-uk"; // Default to British English
    espeak_voice->identifier = NULL; // no specific voice file specified
    espeak_voice->name = "klatt"; // espeak voice name
    espeak_voice->gender = 2; // Female
    espeak_voice->age = 0; // age not specified
    espeak_SetVoiceByProperties(espeak_voice);
#endif

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED

    if (FAILED(::CoInitialize(NULL)))
    {
        qDebug() << "ERROR: Creating COM object for audio output failed!";
    }
    else
    {

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

        if (FAILED(hr))
        {
            qDebug() << "ERROR: Initializing voice for audio output failed!";
        }
    }

#endif

    // Prepare regular emergency signal, will be fired off on calling startEmergency()
    emergencyTimer = new QTimer();
    connect(emergencyTimer, SIGNAL(timeout()), this, SLOT(beep()));
}

QGCAudioWorker::~QGCAudioWorker()
{
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice->Release();
    pVoice = NULL;
    ::CoUninitialize();
#endif
}

void QGCAudioWorker::say(QString text, int severity)
{
    if (!muted)
    {
        // Prepend high priority text with alert beep
        if (severity < GAudioOutput::AUDIO_SEVERITY_CRITICAL) {
            beep();
        }

        // Wait for the last sound to finish
        while (!sound->isFinished()) {
            QGC::SLEEP::msleep(100);
        }

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
        pVoice->Speak(text.toStdWString().c_str(), SPF_DEFAULT, NULL);

#elif defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
        // Set size of string for espeak: +1 for the null-character
        unsigned int espeak_size = strlen(text.toStdString().c_str()) + 1;
        espeak_Synth(text.toStdString().c_str(), espeak_size, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);

#elif defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
        // Slashes necessary to have the right start to the sentence
        // copying data prevents SpeakString from reading additional chars
        text = "\\" + text;
        std::wstring str = text.toStdWString();
        unsigned char str2[1024] = {};
        memcpy(str2, text.toLatin1().data(), str.length());
        SpeakString(str2);

        // Block the thread while busy
        // because we run in our own thread, this doesn't
        // halt the main application
        while (SpeechBusy()) {
            QGC::SLEEP::msleep(100);
        }

#else
        // Make sure there isn't an unused variable warning when speech output is disabled
        Q_UNUSED(text);
#endif
    }
}

void QGCAudioWorker::mute(bool mute)
{
    if (mute != muted)
    {
        this->muted = mute;
        QSettings settings;
        settings.setValue(QGC_GAUDIOOUTPUT_KEY + "muted", this->muted);
//        emit mutedChanged(muted);
    }
}

void QGCAudioWorker::beep()
{

    if (!muted)
    {
        // Use QFile to transform path for all OS
        QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/alert.wav"));
        sound->play(f.fileName());
    }
}

bool QGCAudioWorker::isMuted()
{
    return this->muted;
}
<|endoftext|>


<commit_before><commit_msg>Remove unnecessary forward declaration<commit_after><|endoftext|>


<commit_before>/*
 *  Author(s):
 *  - Laurent LEC <llec@aldebaran-robotics.com>
 *
 *  Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 */

#include <gtest/gtest.h>

#include <QCoreApplication>

#include <qimessaging/qt/QiTransportSocket>
#include <qimessaging/qt/QiTransportServer>

static QCoreApplication* app = 0;

TEST(TransportServer, Listen)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serverUrl = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(serverUrl);

  ASSERT_TRUE(server.isListening());
}

TEST(TransportServer, ListeningUrl)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serverUrl = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(serverUrl);

  ASSERT_EQ(server.listeningUrl(), serverUrl);
}

TEST(TransportServer, ListenOnBadProtocol)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serveurUrl = QString("chiche://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(serveurUrl);

  ASSERT_FALSE(server.isListening());
}

TEST(TransportServer, ListenOnBadHost)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serverUrl = QString("tcp://this.host.should.not.exist:%1").arg(port);

  QiTransportServer server;
  server.listen(serverUrl);

  ASSERT_FALSE(server.isListening());
}

TEST(TransportServer, CloseAfterListen)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(service);
  server.close();

  ASSERT_FALSE(server.isListening());
}

TEST(TransportServer, HasPendingConnection)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(service);

  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  QiTransportSocket socket;
  socket.connectToHost(service);

  app->exec();

  ASSERT_TRUE(server.hasPendingConnections());
}

TEST(TransportServer, NextPendingConnection)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(service);

  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  QiTransportSocket socket;
  socket.connectToHost(service);

  app->exec();

  QiTransportSocket* incomingSocket = server.nextPendingConnection();

  ASSERT_TRUE(incomingSocket != 0);

  if (incomingSocket)
  {
    incomingSocket->close();
    delete incomingSocket;
  }

  ASSERT_FALSE(server.hasPendingConnections());
}

TEST(TransportServer, MultipleConnections)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  server.listen(service);

  for (int nbRetry = 100; nbRetry > 0; --nbRetry)
  {
    QiTransportSocket socket;
    socket.connectToHost(service);

    app->exec();

    QiTransportSocket* incomingSocket = server.nextPendingConnection();

    ASSERT_TRUE(incomingSocket != 0);

    incomingSocket->close();
    delete incomingSocket;

    ASSERT_FALSE(server.hasPendingConnections());
  }

  server.close();
}

TEST(TransportServer, MultipleListens)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  for (int nbRetry = 100; nbRetry > 0; --nbRetry)
  {
    server.listen(service);

    QiTransportSocket socket;
    socket.connectToHost(service);

    app->exec();

    QiTransportSocket* incomingSocket = server.nextPendingConnection();

    ASSERT_TRUE(incomingSocket != 0);

    if (incomingSocket)
    {
      incomingSocket->close();
      delete incomingSocket;
    }

    ASSERT_FALSE(server.hasPendingConnections());

    server.close();
  }
}

int main(int argc, char *argv[])
{
  ::testing::InitGoogleTest(&argc, argv);
  app = new QCoreApplication (argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Test listening on port 0<commit_after>/*
 *  Author(s):
 *  - Laurent LEC <llec@aldebaran-robotics.com>
 *
 *  Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 */

#include <gtest/gtest.h>

#include <QCoreApplication>

#include <qimessaging/qt/QiTransportSocket>
#include <qimessaging/qt/QiTransportServer>

static QCoreApplication* app = 0;

TEST(TransportServer, Listen)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serverUrl = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(serverUrl);

  ASSERT_TRUE(server.isListening());
}

TEST(TransportServer, ListeningUrl)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serverUrl = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(serverUrl);

  ASSERT_EQ(server.listeningUrl(), serverUrl);
}

TEST(TransportServer, ListenOnBadProtocol)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serveurUrl = QString("chiche://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(serveurUrl);

  ASSERT_FALSE(server.isListening());
}

TEST(TransportServer, ListenOnBadHost)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString serverUrl = QString("tcp://this.host.should.not.exist:%1").arg(port);

  QiTransportServer server;
  server.listen(serverUrl);

  ASSERT_FALSE(server.isListening());
}

TEST(TransportServer, CloseAfterListen)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(service);
  server.close();

  ASSERT_FALSE(server.isListening());
}

TEST(TransportServer, HasPendingConnection)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(service);

  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  QiTransportSocket socket;
  socket.connectToHost(service);

  app->exec();

  ASSERT_TRUE(server.hasPendingConnections());
}

TEST(TransportServer, ListenPort0)
{
  QString service = QString("tcp://0.0.0.0:0");

  QiTransportServer server;
  server.listen(service);

  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  QiTransportSocket socket;
  socket.connectToHost(server.listeningUrl());

  app->exec();

  ASSERT_TRUE(server.hasPendingConnections());
}

TEST(TransportServer, NextPendingConnection)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  server.listen(service);

  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  QiTransportSocket socket;
  socket.connectToHost(service);

  app->exec();

  QiTransportSocket* incomingSocket = server.nextPendingConnection();

  ASSERT_TRUE(incomingSocket != 0);

  if (incomingSocket)
  {
    incomingSocket->close();
    delete incomingSocket;
  }

  ASSERT_FALSE(server.hasPendingConnections());
}

TEST(TransportServer, MultipleConnections)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  server.listen(service);

  for (int nbRetry = 100; nbRetry > 0; --nbRetry)
  {
    QiTransportSocket socket;
    socket.connectToHost(service);

    app->exec();

    QiTransportSocket* incomingSocket = server.nextPendingConnection();

    ASSERT_TRUE(incomingSocket != 0);

    incomingSocket->close();
    delete incomingSocket;

    ASSERT_FALSE(server.hasPendingConnections());
  }

  server.close();
}

TEST(TransportServer, MultipleListens)
{
  unsigned short port = qi::os::findAvailablePort(0);
  QString service = QString("tcp://0.0.0.0:%1").arg(port);

  QiTransportServer server;
  QObject::connect(&server, SIGNAL(newConnection()), app, SLOT(quit()));

  for (int nbRetry = 100; nbRetry > 0; --nbRetry)
  {
    server.listen(service);

    QiTransportSocket socket;
    socket.connectToHost(service);

    app->exec();

    QiTransportSocket* incomingSocket = server.nextPendingConnection();

    ASSERT_TRUE(incomingSocket != 0);

    if (incomingSocket)
    {
      incomingSocket->close();
      delete incomingSocket;
    }

    ASSERT_FALSE(server.hasPendingConnections());

    server.close();
  }
}

int main(int argc, char *argv[])
{
  ::testing::InitGoogleTest(&argc, argv);
  app = new QCoreApplication (argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#pragma once

#define GRAPHENE_SYMBOL "PIC"
#define GRAPHENE_ADDRESS_PREFIX "PIC"

#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH 1
#define GRAPHENE_MAX_ACCOUNT_NAME_LENGTH 63

#define GRAPHENE_MIN_ASSET_SYMBOL_LENGTH 3
#define GRAPHENE_MAX_ASSET_SYMBOL_LENGTH 16

#define GRAPHENE_MAX_SHARE_SUPPLY int64_t(1000000000000ll)
#define GRAPHENE_MAX_PAY_RATE 10000 /* 100% */
#define GRAPHENE_MAX_SIG_CHECK_DEPTH 2
/**
 * Don't allow the committee_members to publish a limit that would
 * make the network unable to operate.
 */
#define GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT 1024
#define GRAPHENE_MAX_BLOCK_INTERVAL  30 /* seconds */
#define GRAPHENE_MIN_BLOCK_INTERVAL   1 /* seconds */

#define GRAPHENE_DEFAULT_BLOCK_INTERVAL  3 /* seconds */
#define GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE 2048
#define GRAPHENE_DEFAULT_MAX_BLOCK_SIZE  (GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE*GRAPHENE_DEFAULT_BLOCK_INTERVAL*200000)
#define GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION (60*60*24) // seconds,  aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL  (60*60*24) // seconds, aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS 3  // number of slots to skip for maintenance interval

#define GRAPHENE_MIN_UNDO_HISTORY 10
#define GRAPHENE_MAX_UNDO_HISTORY 10000

#define GRAPHENE_MIN_BLOCK_SIZE_LIMIT (GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT*5) // 5 transactions per block
#define GRAPHENE_MIN_TRANSACTION_EXPIRATION_LIMIT (GRAPHENE_MAX_BLOCK_INTERVAL * 5) // 5 transactions per block
#define GRAPHENE_BLOCKCHAIN_PRECISION                           uint64_t( 100000 )

#define GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS                    5
#define GRAPHENE_DEFAULT_TRANSFER_FEE                           (1*GRAPHENE_BLOCKCHAIN_PRECISION)
#define GRAPHENE_MAX_INSTANCE_ID                                (uint64_t(-1)>>16)
/** percentage fields are fixed point with a denominator of 10,000 */
#define GRAPHENE_100_PERCENT                                    10000
#define GRAPHENE_1_PERCENT                                      (GRAPHENE_100_PERCENT/100)
/** NOTE: making this a power of 2 (say 2^15) would greatly accelerate fee calcs */
#define GRAPHENE_MAX_MARKET_FEE_PERCENT                         GRAPHENE_100_PERCENT
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_DELAY                 (60*60*24) ///< 1 day
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_OFFSET                0 ///< 1%
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_MAX_VOLUME            (20* GRAPHENE_1_PERCENT) ///< 20%
#define GRAPHENE_DEFAULT_PRICE_FEED_LIFETIME                    (60*60*24) ///< 1 day
#define GRAPHENE_MAX_FEED_PRODUCERS                             200
#define GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP               10
#define GRAPHENE_DEFAULT_MAX_ASSET_WHITELIST_AUTHORITIES        10
#define GRAPHENE_DEFAULT_MAX_ASSET_FEED_PUBLISHERS              10

/**
 *  These ratios are fixed point numbers with a denominator of GRAPHENE_COLLATERAL_RATIO_DENOM, the
 *  minimum maitenance collateral is therefore 1.001x and the default
 *  maintenance ratio is 1.75x
 */
///@{
#define GRAPHENE_COLLATERAL_RATIO_DENOM                 1000
#define GRAPHENE_MIN_COLLATERAL_RATIO                   1001  ///< lower than this could result in divide by 0
#define GRAPHENE_MAX_COLLATERAL_RATIO                   32000 ///< higher than this is unnecessary and may exceed int16 storage
#define GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO   1750 ///< Call when collateral only pays off 175% the debt
#define GRAPHENE_DEFAULT_MAX_SHORT_SQUEEZE_RATIO        1500 ///< Stop calling when collateral only pays off 150% of the debt
///@}
#define GRAPHENE_DEFAULT_MARGIN_PERIOD_SEC              (30*60*60*24)

#define GRAPHENE_DEFAULT_MIN_WITNESS_COUNT                    (11)
#define GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT           (11)
#define GRAPHENE_DEFAULT_MAX_WITNESSES                        (101) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_COMMITTEE                        (101) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC            (60*60*24*7*4) // Four weeks
#define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24) // One Day
#define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE               (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE     (30*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_MAX_BULK_DISCOUNT_PERCENT            (50*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN          ( GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(1000) )
#define GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MAX          ( GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN*int64_t(100) )
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_PERIOD_SEC          (60*60*24*365) ///< 1 year
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD           (GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(100))
#define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE                  (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_WITNESS_PAY_PERCENT_PRECISION                (1000000000)
#define GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE                    1
#define GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD            GRAPHENE_BLOCKCHAIN_PRECISION * 100;
#define GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE               1000
#define GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS          4
#define GRAPHENE_DEFAULT_MAX_BUYBACK_MARKETS                  4

#define GRAPHENE_MAX_WORKER_NAME_LENGTH                       63

#define GRAPHENE_MAX_URL_LENGTH                               127

// counter initialization values used to derive near and far future seeds for shuffling witnesses
// we use the fractional bits of sqrt(2) in hex
#define GRAPHENE_NEAR_SCHEDULE_CTR_IV                    ( (uint64_t( 0x6a09 ) << 0x30)    \
                                                         | (uint64_t( 0xe667 ) << 0x20)    \
                                                         | (uint64_t( 0xf3bc ) << 0x10)    \
                                                         | (uint64_t( 0xc908 )        ) )

// and the fractional bits of sqrt(3) in hex
#define GRAPHENE_FAR_SCHEDULE_CTR_IV                     ( (uint64_t( 0xbb67 ) << 0x30)    \
                                                         | (uint64_t( 0xae85 ) << 0x20)    \
                                                         | (uint64_t( 0x84ca ) << 0x10)    \
                                                         | (uint64_t( 0xa73b )        ) )

/**
 * every second, the fraction of burned core asset which cycles is
 * GRAPHENE_CORE_ASSET_CYCLE_RATE / (1 << GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS)
 */
#define GRAPHENE_CORE_ASSET_CYCLE_RATE                        17
#define GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS                   32

#define GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t( 10) )
#define GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS      (60*60*24)
#define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 )

#define GRAPHENE_DEFAULT_MINIMUM_FEEDS                       7

#define GRAPHENE_MAX_INTEREST_APR                            uint16_t( 10000 )

#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT             4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT             3

#define GRAPHENE_CURRENT_DB_VERSION                          "PIC1.0"

#define GRAPHENE_IRREVERSIBLE_THRESHOLD                      (70 * GRAPHENE_1_PERCENT)

/**
 *  Reserved Account IDs with special meaning
 */
///@{
/// Represents the current committee members, two-week review period
#define GRAPHENE_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(0))
/// Represents the current witnesses
#define GRAPHENE_WITNESS_ACCOUNT (graphene::chain::account_id_type(1))
/// Represents the current committee members
#define GRAPHENE_RELAXED_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(2))
/// Represents the canonical account with NO authority (nobody can access funds in null account)
#define GRAPHENE_NULL_ACCOUNT (graphene::chain::account_id_type(3))
/// Represents the canonical account with WILDCARD authority (anybody can access funds in temp account)
#define GRAPHENE_TEMP_ACCOUNT (graphene::chain::account_id_type(4))
/// Represents the canonical account for specifying you will vote directly (as opposed to a proxy)
#define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5))
/// Represents the account who receives all construction capital
#define GRAPHENE_CONSTRUCTION_CAPITAL_ACCOUNT (graphene::chain::account_id_type(6))
/// Represents the account who receives market found generated by construction capital
#define GRAPHENE_MARKET_FOUND_ACCOUNT (graphene::chain::account_id_type(7))
/// Represents the account who issue the deflation
#define GRAPHENE_DEFLATION_ISSUE_ACCOUNT (graphene::chain::account_id_type(30306))
/// Represents the very first account who will not be deflated as a marker
#define GRAPHENE_DEFLATION_ACCOUNT_START_MARKER (graphene::chain::account_id_type(8))
/// Sentinel value used in the scheduler.
#define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0))
///@}

#define GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET (asset_id_type(743))

/**
 * Incentive and Construction Capital defines
 */
#define GRAPHENE_DEFAULT_MAX_INCENTIVE_OPERATIONS_PER_BLOCK         256
#define GRAPHENE_DEFAULT_MAX_DEFLATION_OPERATIONS_PER_BLOCK         1024 // 128
#define GRAPHENE_DEFAULT_MIN_CONSTRUCTION_CAPITAL_AMOUNT            30000000
#define GRAPHENE_DEFAULT_MIN_CONSTRUCTION_CAPITAL_PERIOD            604800
#define GRAPHENE_DEFAULT_MAX_CONSTRUCTION_CAPITAL_PERIOD            31536000    //1 year
#define GRAPHENE_DEFAULT_MIN_CONSTRUCTION_CAPITAL_PERIOD_LEN        50
#define GRAPHENE_DEFAULT_MAX_CONSTRUCTION_CAPITAL_PERIOD_LEN        600
#define GRAPHENE_DEFAULT_MAX_CONSTRUCTION_CAPITAL_VOTE              5
#define GRAPHENE_DEFAULT_MAX_INCENTIVE_ACCELERATE_RATE              100
#define GRAPHENE_SECONDS_PER_YEAR                                   31536000
#define GRAPHENE_ISSUANCE_RATE_SCALE                                100000000
#define GRAPHENE_DEFAULT_ISSUANCE_RATE                              104285714
#define GRAPHENE_DEFAULT_INSTANT_PAYBACL_RATE                       15000000
#define GRAPHENE_EXCHANGE_RATE_SCALE                                10000000

#define GRAPHENE_MINIMUM_DEFLATION_INTERVAL 300 //(3600*24 - 600)
#define GRAPHENE_DEFLATION_RATE_SCALE (100000000)
<commit_msg>deflation config<commit_after>/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#pragma once

#define GRAPHENE_SYMBOL "PIC"
#define GRAPHENE_ADDRESS_PREFIX "PIC"

#define GRAPHENE_MIN_ACCOUNT_NAME_LENGTH 1
#define GRAPHENE_MAX_ACCOUNT_NAME_LENGTH 63

#define GRAPHENE_MIN_ASSET_SYMBOL_LENGTH 3
#define GRAPHENE_MAX_ASSET_SYMBOL_LENGTH 16

#define GRAPHENE_MAX_SHARE_SUPPLY int64_t(1000000000000ll)
#define GRAPHENE_MAX_PAY_RATE 10000 /* 100% */
#define GRAPHENE_MAX_SIG_CHECK_DEPTH 2
/**
 * Don't allow the committee_members to publish a limit that would
 * make the network unable to operate.
 */
#define GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT 1024
#define GRAPHENE_MAX_BLOCK_INTERVAL  30 /* seconds */
#define GRAPHENE_MIN_BLOCK_INTERVAL   1 /* seconds */

#define GRAPHENE_DEFAULT_BLOCK_INTERVAL  3 /* seconds */
#define GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE 2048
#define GRAPHENE_DEFAULT_MAX_BLOCK_SIZE  (GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE*GRAPHENE_DEFAULT_BLOCK_INTERVAL*200000)
#define GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION (60*60*24) // seconds,  aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL  (60*60*24) // seconds, aka: 1 day
#define GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS 3  // number of slots to skip for maintenance interval

#define GRAPHENE_MIN_UNDO_HISTORY 10
#define GRAPHENE_MAX_UNDO_HISTORY 10000

#define GRAPHENE_MIN_BLOCK_SIZE_LIMIT (GRAPHENE_MIN_TRANSACTION_SIZE_LIMIT*5) // 5 transactions per block
#define GRAPHENE_MIN_TRANSACTION_EXPIRATION_LIMIT (GRAPHENE_MAX_BLOCK_INTERVAL * 5) // 5 transactions per block
#define GRAPHENE_BLOCKCHAIN_PRECISION                           uint64_t( 100000 )

#define GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS                    5
#define GRAPHENE_DEFAULT_TRANSFER_FEE                           (1*GRAPHENE_BLOCKCHAIN_PRECISION)
#define GRAPHENE_MAX_INSTANCE_ID                                (uint64_t(-1)>>16)
/** percentage fields are fixed point with a denominator of 10,000 */
#define GRAPHENE_100_PERCENT                                    10000
#define GRAPHENE_1_PERCENT                                      (GRAPHENE_100_PERCENT/100)
/** NOTE: making this a power of 2 (say 2^15) would greatly accelerate fee calcs */
#define GRAPHENE_MAX_MARKET_FEE_PERCENT                         GRAPHENE_100_PERCENT
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_DELAY                 (60*60*24) ///< 1 day
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_OFFSET                0 ///< 1%
#define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_MAX_VOLUME            (20* GRAPHENE_1_PERCENT) ///< 20%
#define GRAPHENE_DEFAULT_PRICE_FEED_LIFETIME                    (60*60*24) ///< 1 day
#define GRAPHENE_MAX_FEED_PRODUCERS                             200
#define GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP               10
#define GRAPHENE_DEFAULT_MAX_ASSET_WHITELIST_AUTHORITIES        10
#define GRAPHENE_DEFAULT_MAX_ASSET_FEED_PUBLISHERS              10

/**
 *  These ratios are fixed point numbers with a denominator of GRAPHENE_COLLATERAL_RATIO_DENOM, the
 *  minimum maitenance collateral is therefore 1.001x and the default
 *  maintenance ratio is 1.75x
 */
///@{
#define GRAPHENE_COLLATERAL_RATIO_DENOM                 1000
#define GRAPHENE_MIN_COLLATERAL_RATIO                   1001  ///< lower than this could result in divide by 0
#define GRAPHENE_MAX_COLLATERAL_RATIO                   32000 ///< higher than this is unnecessary and may exceed int16 storage
#define GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO   1750 ///< Call when collateral only pays off 175% the debt
#define GRAPHENE_DEFAULT_MAX_SHORT_SQUEEZE_RATIO        1500 ///< Stop calling when collateral only pays off 150% of the debt
///@}
#define GRAPHENE_DEFAULT_MARGIN_PERIOD_SEC              (30*60*60*24)

#define GRAPHENE_DEFAULT_MIN_WITNESS_COUNT                    (11)
#define GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT           (11)
#define GRAPHENE_DEFAULT_MAX_WITNESSES                        (101) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_COMMITTEE                        (101) // SHOULD BE ODD
#define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC            (60*60*24*7*4) // Four weeks
#define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24) // One Day
#define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE               (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE     (30*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_MAX_BULK_DISCOUNT_PERCENT            (50*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN          ( GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(1000) )
#define GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MAX          ( GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN*int64_t(100) )
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_PERIOD_SEC          (60*60*24*365) ///< 1 year
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD           (GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(100))
#define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE                  (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_WITNESS_PAY_PERCENT_PRECISION                (1000000000)
#define GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE                    1
#define GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD            GRAPHENE_BLOCKCHAIN_PRECISION * 100;
#define GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE               1000
#define GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS          4
#define GRAPHENE_DEFAULT_MAX_BUYBACK_MARKETS                  4

#define GRAPHENE_MAX_WORKER_NAME_LENGTH                       63

#define GRAPHENE_MAX_URL_LENGTH                               127

// counter initialization values used to derive near and far future seeds for shuffling witnesses
// we use the fractional bits of sqrt(2) in hex
#define GRAPHENE_NEAR_SCHEDULE_CTR_IV                    ( (uint64_t( 0x6a09 ) << 0x30)    \
                                                         | (uint64_t( 0xe667 ) << 0x20)    \
                                                         | (uint64_t( 0xf3bc ) << 0x10)    \
                                                         | (uint64_t( 0xc908 )        ) )

// and the fractional bits of sqrt(3) in hex
#define GRAPHENE_FAR_SCHEDULE_CTR_IV                     ( (uint64_t( 0xbb67 ) << 0x30)    \
                                                         | (uint64_t( 0xae85 ) << 0x20)    \
                                                         | (uint64_t( 0x84ca ) << 0x10)    \
                                                         | (uint64_t( 0xa73b )        ) )

/**
 * every second, the fraction of burned core asset which cycles is
 * GRAPHENE_CORE_ASSET_CYCLE_RATE / (1 << GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS)
 */
#define GRAPHENE_CORE_ASSET_CYCLE_RATE                        17
#define GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS                   32

#define GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t( 10) )
#define GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS      (60*60*24)
#define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY            (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 )

#define GRAPHENE_DEFAULT_MINIMUM_FEEDS                       7

#define GRAPHENE_MAX_INTEREST_APR                            uint16_t( 10000 )

#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT             4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT             3

#define GRAPHENE_CURRENT_DB_VERSION                          "PIC1.0"

#define GRAPHENE_IRREVERSIBLE_THRESHOLD                      (70 * GRAPHENE_1_PERCENT)

/**
 *  Reserved Account IDs with special meaning
 */
///@{
/// Represents the current committee members, two-week review period
#define GRAPHENE_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(0))
/// Represents the current witnesses
#define GRAPHENE_WITNESS_ACCOUNT (graphene::chain::account_id_type(1))
/// Represents the current committee members
#define GRAPHENE_RELAXED_COMMITTEE_ACCOUNT (graphene::chain::account_id_type(2))
/// Represents the canonical account with NO authority (nobody can access funds in null account)
#define GRAPHENE_NULL_ACCOUNT (graphene::chain::account_id_type(3))
/// Represents the canonical account with WILDCARD authority (anybody can access funds in temp account)
#define GRAPHENE_TEMP_ACCOUNT (graphene::chain::account_id_type(4))
/// Represents the canonical account for specifying you will vote directly (as opposed to a proxy)
#define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5))
/// Represents the account who receives all construction capital
#define GRAPHENE_CONSTRUCTION_CAPITAL_ACCOUNT (graphene::chain::account_id_type(6))
/// Represents the account who receives market found generated by construction capital
#define GRAPHENE_MARKET_FOUND_ACCOUNT (graphene::chain::account_id_type(7))
/// Represents the account who issue the deflation
#define GRAPHENE_DEFLATION_ISSUE_ACCOUNT (graphene::chain::account_id_type(55120))
/// Represents the very first account who will not be deflated as a marker
#define GRAPHENE_DEFLATION_ACCOUNT_START_MARKER (graphene::chain::account_id_type(8))
/// Sentinel value used in the scheduler.
#define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0))
///@}

#define GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET (asset_id_type(743))

/**
 * Incentive and Construction Capital defines
 */
#define GRAPHENE_DEFAULT_MAX_INCENTIVE_OPERATIONS_PER_BLOCK         256
#define GRAPHENE_DEFAULT_MAX_DEFLATION_OPERATIONS_PER_BLOCK         256
#define GRAPHENE_DEFAULT_MIN_CONSTRUCTION_CAPITAL_AMOUNT            30000000
#define GRAPHENE_DEFAULT_MIN_CONSTRUCTION_CAPITAL_PERIOD            604800
#define GRAPHENE_DEFAULT_MAX_CONSTRUCTION_CAPITAL_PERIOD            31536000    //1 year
#define GRAPHENE_DEFAULT_MIN_CONSTRUCTION_CAPITAL_PERIOD_LEN        50
#define GRAPHENE_DEFAULT_MAX_CONSTRUCTION_CAPITAL_PERIOD_LEN        600
#define GRAPHENE_DEFAULT_MAX_CONSTRUCTION_CAPITAL_VOTE              5
#define GRAPHENE_DEFAULT_MAX_INCENTIVE_ACCELERATE_RATE              100
#define GRAPHENE_SECONDS_PER_YEAR                                   31536000
#define GRAPHENE_ISSUANCE_RATE_SCALE                                100000000
#define GRAPHENE_DEFAULT_ISSUANCE_RATE                              104285714
#define GRAPHENE_DEFAULT_INSTANT_PAYBACL_RATE                       15000000
#define GRAPHENE_EXCHANGE_RATE_SCALE                                10000000

#define GRAPHENE_MINIMUM_DEFLATION_INTERVAL 600 //(3600*24 - 600)
#define GRAPHENE_DEFLATION_RATE_SCALE (100000000)
<|endoftext|>


<commit_before>//
//  ex9_43.cpp
//  Exercise 9.43
//
//  Created by pezy on 6/18/15.
//  Updated by sanerror on 10/16/16.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  @Brief  Write a function that takes three strings, s, oldVal, and newVal.
//          Using iterators, and the insert and erase functions replace
//          all instances of oldVal that appear in s by newVal.
//          Test your function by using it to replace common abbreviations,
//          such as "tho" by "though" and "thru" by "through".

#include <string>
using std::string;

#include <iostream>

void Replace(string& s, const string& oldVal, const string& newVal)
{
	for (auto beg = s.begin(); beg != s.end(); ) {
		if (std::distance(beg, s.end()) <
			std::distance(oldVal.begin(), oldVal.end()))
			break;
		if (*beg == oldVal.front() && string{ beg, beg + oldVal.size() } == oldVal) {
			beg = s.erase(beg, beg + oldVal.size());
			beg = s.insert(beg, newVal.cbegin(), newVal.cend()) + newVal.size();
		}
		else {
			++beg;
		}
	}
}
int main()
{
    {
        string str{"To drive straight thru is a foolish, tho courageous act."};
        Replace(str, "thru", "through");
        Replace(str, "tho", "though");
        std::cout << str << std::endl;
    }
    {
        string str{
            "To drive straight thruthru is a foolish, thotho courageous act."};
        Replace(str, "thru", "through");
        Replace(str, "tho", "though");
        std::cout << str << std::endl;
    }
    {
        string str{"To drive straight thru is a foolish, tho courageous act."};
        Replace(str, "thru", "thruthru");
        Replace(str, "tho", "though");
        std::cout << str << std::endl;
    }
    {
        string str{"my world is a big world"};
        Replace(str, "world",
                "worldddddddddddddddddddddddddddddddddddddddddddddddd");
        std::cout << str << std::endl;
    }
    return 0;
}
<commit_msg>improving #84 format.<commit_after>//
//  ex9_43.cpp
//  Exercise 9.43
//
//  Created by pezy on 6/18/15.
//  Updated by sanerror on 10/16/16.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  @Brief  Write a function that takes three strings, s, oldVal, and newVal.
//          Using iterators, and the insert and erase functions replace
//          all instances of oldVal that appear in s by newVal.
//          Test your function by using it to replace common abbreviations,
//          such as "tho" by "though" and "thru" by "through".

#include <string>
using std::string;

#include <iostream>

void Replace(string& s, const string& oldVal, const string& newVal)
{
    for (auto beg = s.begin(); std::distance(beg, s.end()) >=
                               std::distance(oldVal.begin(), oldVal.end());) {
        if (string{beg, beg + oldVal.size()} == oldVal) {
            beg = s.erase(beg, beg + oldVal.size());
            beg = s.insert(beg, newVal.cbegin(), newVal.cend());
            std::advance(beg, newVal.size());
        }
        else
            ++beg;
    }
}

int main()
{
    {
        string str{"To drive straight thru is a foolish, tho courageous act."};
        Replace(str, "thru", "through");
        Replace(str, "tho", "though");
        std::cout << str << std::endl;
    }
    {
        string str{
            "To drive straight thruthru is a foolish, thotho courageous act."};
        Replace(str, "thru", "through");
        Replace(str, "tho", "though");
        std::cout << str << std::endl;
    }
    {
        string str{"To drive straight thru is a foolish, tho courageous act."};
        Replace(str, "thru", "thruthru");
        Replace(str, "tho", "though");
        std::cout << str << std::endl;
    }
    {
        string str{"my world is a big world"};
        Replace(str, "world",
                "worldddddddddddddddddddddddddddddddddddddddddddddddd");
        std::cout << str << std::endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation of Kalman-specific code in beacon-based pose
   estimator, to reduce incremental build times.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

#include <iostream>
#include <osvr/Util/EigenCoreGeometry.h>
#if 0
template <typename T>
inline void dumpKalmanDebugOuput(const char name[], const char expr[],
                                 T const &value) {
    std::cout << "\n(Kalman Debug Output) " << name << " [" << expr << "]:\n"
              << value << std::endl;
}
#endif

// Internal Includes
#include "BeaconBasedPoseEstimator.h"
#include "ImagePointMeasurement.h"
#include "cvToEigen.h"

// Library/third-party includes
#include <osvr/Kalman/FlexibleKalmanFilter.h>
#include <osvr/Kalman/AugmentedProcessModel.h>
#include <osvr/Kalman/AugmentedState.h>
#include <osvr/Kalman/ConstantProcess.h>

#include <osvr/Util/EigenInterop.h>

#include <opencv2/core/eigen.hpp>

// Standard includes
// - none

namespace osvr {
namespace vbtracker {
    static const auto LOW_BEACON_CUTOFF = 5;

    static const auto DIM_BEACON_CUTOFF_TO_SKIP_BRIGHTS = 4;

    static const auto MAX_Z_COMPONENT = -0.3;

    bool BeaconBasedPoseEstimator::m_kalmanAutocalibEstimator(LedGroup &leds,
                                                              double dt) {
        auto const beaconsSize = m_beacons.size();
        // Default measurement variance (for now, factor) per axis.
        double varianceFactor = 1;

        auto maxBoxRatio = m_params.boundingBoxFilterRatio;
        auto minBoxRatio = 1.f / m_params.boundingBoxFilterRatio;

        // Default to using all the measurements we can
        auto skipBright = false;
        {
            auto totalLeds = leds.size();
            auto identified = std::size_t{0};
            auto inBoundsID = std::size_t{0};
            auto inBoundsBright = std::size_t{0};
            auto inBoundsRound = std::size_t{0};
            for (auto const &led : leds) {
                if (!led.identified()) {
                    continue;
                }
                identified++;
                auto id = led.getID();
                if (id >= beaconsSize) {
                    continue;
                }
                inBoundsID++;
                if (led.isBright()) {
                    inBoundsBright++;
                }

                if (led.getMeasurement().knowBoundingBox) {
                    auto boundingBoxRatio =
                        led.getMeasurement().boundingBox.height /
                        led.getMeasurement().boundingBox.width;
                    if (boundingBoxRatio > minBoxRatio &&
                        boundingBoxRatio < maxBoxRatio) {
                        inBoundsRound++;
                    }
                }
            }

            // Now we decide if we want to cut the variance artificially to
            // reduce latency in low-beacon situations
            if (inBoundsID < LOW_BEACON_CUTOFF) {
                varianceFactor = 0.5;
            }
            if (inBoundsID - inBoundsBright >
                DIM_BEACON_CUTOFF_TO_SKIP_BRIGHTS) {
                skipBright = true;
            } else {
#if 0
                if (m_params.debug) {
                    std::cout << "Can't afford to skip brights this frame"
                              << std::endl;
                }
#endif
            }
        }

        CameraModel cam;
        cam.focalLength = m_camParams.focalLength();
        cam.principalPoint = cvToVector(m_camParams.principalPoint());
        ImagePointMeasurement meas{cam};

        kalman::ConstantProcess<kalman::PureVectorState<>> beaconProcess;
        Eigen::Vector2d pt;

        const auto maxSquaredResidual =
            m_params.maxResidual * m_params.maxResidual;

        kalman::predict(m_state, m_model, dt);

        /// @todo should we be recalculating this for each beacon after each
        /// correction step? The order we filter them in is rather arbitrary...
        Eigen::Matrix3d rotate =
            Eigen::Matrix3d(m_state.getCombinedQuaternion());
        auto numBad = std::size_t{0};
        auto numGood = std::size_t{0};
        for (auto &led : leds) {
            if (!led.identified()) {
                continue;
            }
            auto id = led.getID();
            if (id >= beaconsSize) {
                continue;
            }
            auto &debug = m_beaconDebugData[id];
            debug.seen = true;
            debug.measurement = led.getLocation();
            if (skipBright && led.isBright()) {
                continue;
            }

            // Angle of emission checking
            // If we transform the body-local emission vector, an LED pointed
            // right at the camera will be -Z. Anything with a 0 or positive z
            // component is clearly out, and realistically, anything with a z
            // component over -0.5 is probably fairly oblique. We don't want to
            // use such beacons since they can easily introduce substantial
            // error.
            double zComponent =
                (rotate * cvToVector(m_beaconEmissionDirection[id])).z();
            /// @todo if z component is positive, we shouldn't even be able to
            /// see this since it's pointed away from us.
            if (zComponent > MAX_Z_COMPONENT) {
                numBad++;
                continue;
            }

            if (led.getMeasurement().knowBoundingBox) {
                /// @todo For right now, if we don't have a bounding box, we're
                /// assuming it's square enough (and only testing for
                /// non-squareness on those who actually do have bounding
                /// boxes). This is very much a temporary situation.
                auto boundingBoxRatio =
                    led.getMeasurement().boundingBox.height /
                    led.getMeasurement().boundingBox.width;
                if (boundingBoxRatio < minBoxRatio ||
                    boundingBoxRatio > maxBoxRatio) {
                    /// skip non-circular blobs.
                    numBad++;
                    continue;
                }
            }
            auto localVarianceFactor = varianceFactor;
            auto newIdentificationVariancePenalty =
                std::pow(2.0, led.novelty());

            /// Stick a little bit of process model uncertainty in the beacon,
            /// if it's meant to have some
            if (m_beaconFixed[id]) {
                beaconProcess.setNoiseAutocorrelation(0);
            } else {
                beaconProcess.setNoiseAutocorrelation(
                    m_params.beaconProcessNoise);
                kalman::predict(*(m_beacons[id]), beaconProcess, dt);
            }

            meas.setMeasurement(
                Eigen::Vector2d(led.getLocation().x, led.getLocation().y));
            led.markAsUsed();
            auto state = kalman::makeAugmentedState(m_state, *(m_beacons[id]));
            meas.updateFromState(state);
            Eigen::Vector2d residual = meas.getResidual(state);
            if (residual.squaredNorm() > maxSquaredResidual) {
                // probably bad
                numBad++;
                localVarianceFactor *= m_params.highResidualVariancePenalty;
            } else {
                numGood++;
            }
            debug.residual.x = residual.x();
            debug.residual.y = residual.y();
            auto effectiveVariance =
                localVarianceFactor * m_params.measurementVarianceScaleFactor *
                newIdentificationVariancePenalty *
                m_beaconMeasurementVariance[id] / led.getMeasurement().area;
            debug.variance = effectiveVariance;
            meas.setVariance(effectiveVariance);

            /// Now, do the correction.
            auto model =
                kalman::makeAugmentedProcessModel(m_model, beaconProcess);
            kalman::correct(state, model, meas);
            m_gotMeasurement = true;
        }

        bool incrementProbation = false;
        if (0 == m_framesInProbation) {
            // Let's try to keep a 3:2 ratio of good to bad when not "in
            // probation"
            incrementProbation = (numBad * 3 > numGood * 2);

        } else {
            // Already in trouble, add a bit of hysteresis and raising the bar
            // so we don't hop out easily.
            incrementProbation = numBad * 2 > numGood;
            if (!incrementProbation) {
                // OK, we're good again
                m_framesInProbation = 0;
            }
        }
        if (incrementProbation) {
            m_framesInProbation++;
        }
        /// Output to the OpenCV state types so we can see the reprojection
        /// debug view.
        m_rvec = eiQuatToRotVec(m_state.getQuaternion());
        cv::eigen2cv(m_state.position().eval(), m_tvec);
        return true;
    }

    OSVR_PoseState
    BeaconBasedPoseEstimator::GetPredictedState(double dt) const {
        auto state = m_state;
        auto model = m_model;
        kalman::predict(state, model, dt);
        state.postCorrect();
        OSVR_PoseState ret;
        util::eigen_interop::map(ret).rotation() = state.getQuaternion();
        util::eigen_interop::map(ret).translation() =
            m_convertInternalPositionRepToExternal(state.position());
        return ret;
    }

} // namespace vbtracker
} // namespace osvr
<commit_msg>Add a little variance penalty if an LED is bright, to smooth out the sides (when we can't just skip bright ones)<commit_after>/** @file
    @brief Implementation of Kalman-specific code in beacon-based pose
   estimator, to reduce incremental build times.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

#include <iostream>
#include <osvr/Util/EigenCoreGeometry.h>
#if 0
template <typename T>
inline void dumpKalmanDebugOuput(const char name[], const char expr[],
                                 T const &value) {
    std::cout << "\n(Kalman Debug Output) " << name << " [" << expr << "]:\n"
              << value << std::endl;
}
#endif

// Internal Includes
#include "BeaconBasedPoseEstimator.h"
#include "ImagePointMeasurement.h"
#include "cvToEigen.h"

// Library/third-party includes
#include <osvr/Kalman/FlexibleKalmanFilter.h>
#include <osvr/Kalman/AugmentedProcessModel.h>
#include <osvr/Kalman/AugmentedState.h>
#include <osvr/Kalman/ConstantProcess.h>

#include <osvr/Util/EigenInterop.h>

#include <opencv2/core/eigen.hpp>

// Standard includes
// - none

namespace osvr {
namespace vbtracker {
    static const auto LOW_BEACON_CUTOFF = 5;

    static const auto DIM_BEACON_CUTOFF_TO_SKIP_BRIGHTS = 4;

    static const auto MAX_Z_COMPONENT = -0.3;

    bool BeaconBasedPoseEstimator::m_kalmanAutocalibEstimator(LedGroup &leds,
                                                              double dt) {
        auto const beaconsSize = m_beacons.size();
        // Default measurement variance (for now, factor) per axis.
        double varianceFactor = 1;

        auto maxBoxRatio = m_params.boundingBoxFilterRatio;
        auto minBoxRatio = 1.f / m_params.boundingBoxFilterRatio;

        // Default to using all the measurements we can
        auto skipBright = false;
        {
            auto totalLeds = leds.size();
            auto identified = std::size_t{0};
            auto inBoundsID = std::size_t{0};
            auto inBoundsBright = std::size_t{0};
            auto inBoundsRound = std::size_t{0};
            for (auto const &led : leds) {
                if (!led.identified()) {
                    continue;
                }
                identified++;
                auto id = led.getID();
                if (id >= beaconsSize) {
                    continue;
                }
                inBoundsID++;
                if (led.isBright()) {
                    inBoundsBright++;
                }

                if (led.getMeasurement().knowBoundingBox) {
                    auto boundingBoxRatio =
                        led.getMeasurement().boundingBox.height /
                        led.getMeasurement().boundingBox.width;
                    if (boundingBoxRatio > minBoxRatio &&
                        boundingBoxRatio < maxBoxRatio) {
                        inBoundsRound++;
                    }
                }
            }

            // Now we decide if we want to cut the variance artificially to
            // reduce latency in low-beacon situations
            if (inBoundsID < LOW_BEACON_CUTOFF) {
                varianceFactor = 0.5;
            }
            if (inBoundsID - inBoundsBright >
                DIM_BEACON_CUTOFF_TO_SKIP_BRIGHTS) {
                skipBright = true;
            } else {
#if 0
                if (m_params.debug) {
                    std::cout << "Can't afford to skip brights this frame"
                              << std::endl;
                }
#endif
            }
        }

        CameraModel cam;
        cam.focalLength = m_camParams.focalLength();
        cam.principalPoint = cvToVector(m_camParams.principalPoint());
        ImagePointMeasurement meas{cam};

        kalman::ConstantProcess<kalman::PureVectorState<>> beaconProcess;
        Eigen::Vector2d pt;

        const auto maxSquaredResidual =
            m_params.maxResidual * m_params.maxResidual;

        kalman::predict(m_state, m_model, dt);

        /// @todo should we be recalculating this for each beacon after each
        /// correction step? The order we filter them in is rather arbitrary...
        Eigen::Matrix3d rotate =
            Eigen::Matrix3d(m_state.getCombinedQuaternion());
        auto numBad = std::size_t{0};
        auto numGood = std::size_t{0};
        for (auto &led : leds) {
            if (!led.identified()) {
                continue;
            }
            auto id = led.getID();
            if (id >= beaconsSize) {
                continue;
            }
            auto &debug = m_beaconDebugData[id];
            debug.seen = true;
            debug.measurement = led.getLocation();
            if (skipBright && led.isBright()) {
                continue;
            }

            // Angle of emission checking
            // If we transform the body-local emission vector, an LED pointed
            // right at the camera will be -Z. Anything with a 0 or positive z
            // component is clearly out, and realistically, anything with a z
            // component over -0.5 is probably fairly oblique. We don't want to
            // use such beacons since they can easily introduce substantial
            // error.
            double zComponent =
                (rotate * cvToVector(m_beaconEmissionDirection[id])).z();
            /// @todo if z component is positive, we shouldn't even be able to
            /// see this since it's pointed away from us.
            if (zComponent > MAX_Z_COMPONENT) {
                numBad++;
                continue;
            }

            if (led.getMeasurement().knowBoundingBox) {
                /// @todo For right now, if we don't have a bounding box, we're
                /// assuming it's square enough (and only testing for
                /// non-squareness on those who actually do have bounding
                /// boxes). This is very much a temporary situation.
                auto boundingBoxRatio =
                    led.getMeasurement().boundingBox.height /
                    led.getMeasurement().boundingBox.width;
                if (boundingBoxRatio < minBoxRatio ||
                    boundingBoxRatio > maxBoxRatio) {
                    /// skip non-circular blobs.
                    numBad++;
                    continue;
                }
            }
            auto localVarianceFactor = varianceFactor;
            auto newIdentificationVariancePenalty =
                std::pow(2.0, led.novelty());

            /// Stick a little bit of process model uncertainty in the beacon,
            /// if it's meant to have some
            if (m_beaconFixed[id]) {
                beaconProcess.setNoiseAutocorrelation(0);
            } else {
                beaconProcess.setNoiseAutocorrelation(
                    m_params.beaconProcessNoise);
                kalman::predict(*(m_beacons[id]), beaconProcess, dt);
            }

            meas.setMeasurement(
                Eigen::Vector2d(led.getLocation().x, led.getLocation().y));
            led.markAsUsed();
            auto state = kalman::makeAugmentedState(m_state, *(m_beacons[id]));
            meas.updateFromState(state);
            Eigen::Vector2d residual = meas.getResidual(state);
            if (residual.squaredNorm() > maxSquaredResidual) {
                // probably bad
                numBad++;
                localVarianceFactor *= m_params.highResidualVariancePenalty;
            } else {
                numGood++;
            }
            debug.residual.x = residual.x();
            debug.residual.y = residual.y();
            auto effectiveVariance =
                localVarianceFactor * m_params.measurementVarianceScaleFactor *
                newIdentificationVariancePenalty * (led.isBright() ? 2 : 1) *
                m_beaconMeasurementVariance[id] / led.getMeasurement().area;
            debug.variance = effectiveVariance;
            meas.setVariance(effectiveVariance);

            /// Now, do the correction.
            auto model =
                kalman::makeAugmentedProcessModel(m_model, beaconProcess);
            kalman::correct(state, model, meas);
            m_gotMeasurement = true;
        }

        bool incrementProbation = false;
        if (0 == m_framesInProbation) {
            // Let's try to keep a 3:2 ratio of good to bad when not "in
            // probation"
            incrementProbation = (numBad * 3 > numGood * 2);

        } else {
            // Already in trouble, add a bit of hysteresis and raising the bar
            // so we don't hop out easily.
            incrementProbation = numBad * 2 > numGood;
            if (!incrementProbation) {
                // OK, we're good again
                m_framesInProbation = 0;
            }
        }
        if (incrementProbation) {
            m_framesInProbation++;
        }
        /// Output to the OpenCV state types so we can see the reprojection
        /// debug view.
        m_rvec = eiQuatToRotVec(m_state.getQuaternion());
        cv::eigen2cv(m_state.position().eval(), m_tvec);
        return true;
    }

    OSVR_PoseState
    BeaconBasedPoseEstimator::GetPredictedState(double dt) const {
        auto state = m_state;
        auto model = m_model;
        kalman::predict(state, model, dt);
        state.postCorrect();
        OSVR_PoseState ret;
        util::eigen_interop::map(ret).rotation() = state.getQuaternion();
        util::eigen_interop::map(ret).translation() =
            m_convertInternalPositionRepToExternal(state.position());
        return ret;
    }

} // namespace vbtracker
} // namespace osvr
<|endoftext|>