<commit_before>#include "stdafx.h"
#include "GameManager.h"
#include "FileStuff.h"
#include "ConstVars.h"
//̾
#include "GameLayer.h"
#include "UILayer.h"
//
#include "StageInformation.h"
#include "StageScene.h"
#include "GameScene.h"
//Ŵ
#include "CollectionManager.h"
#include "ColliderManager.h"
#include "TargetManager.h"
//ö̴
#include "Collider.h"
#include "Bullet.h"
#include "CrossBullet.h"
#include "Explosion.h"
//Ÿ
#include "Target.h"
//
#include "Sling.h"

GameManager* GameManager::m_instance = nullptr;

GameManager* GameManager::GetInstance()
{
	if (m_instance == nullptr)
	{
		m_instance = new GameManager();
	}
	return m_instance;
}

GameManager::GameManager()
{
	m_sling = nullptr;
	m_colliderManager = new ColliderManager();
	m_targetManager = new TargetManager();
	m_isJudged = false;
	m_lastTarget = nullptr;
}

void GameManager::Reset()
{
	m_sling = nullptr;
	delete m_colliderManager;
	m_colliderManager = new ColliderManager();
	delete m_targetManager;
	m_targetManager = new TargetManager();
	m_isJudged = false;
	m_lastTarget = nullptr;
}

GameManager::~GameManager() {}

void GameManager::SetStage(GameLayer* gameLayer, UILayer* uiLayer, int stageNum)
{
	Reset();
	StageInformation stageInfo(stageNum);
	m_targetManager->InitTargets(&stageInfo);
	AppendTargetsToLayer(gameLayer);
	m_colliderManager->InitBullets(&stageInfo);
	AppendBulletsToLayer(uiLayer);
	m_sling = InitSling(gameLayer);
	m_stage = stageNum;
}

Sling* GameManager::InitSling(GameLayer* gameLayer)
{
	Sling* sling = Sling::create();
	gameLayer->addChild(sling);
	sling->LoadBullet();
	return sling;
}

void GameManager::AppendTargetsToLayer(GameLayer* gameLayer)
{
	for (Target* target : m_targetManager->m_targets)
	{
		gameLayer->addChild(target);
	}
}

void GameManager::AppendBulletsToLayer(UILayer* uiLayer)
{
	for (int i = 0; i < m_colliderManager->m_bulletNum; i++)
	{
		Bullet* bullet = static_cast<Bullet*>(m_colliderManager->m_colliders.at(i));
		Sprite* bulletSpr = bullet->GetSprite();
		uiLayer->addChild(bulletSpr);
		bulletSpr->setPosition(Vec2(45 + i*25, 50));
	}
}

void GameManager::ShotBullet(Sling* sling)
{
	Bullet* bullet = m_colliderManager->GetBulletToShot(sling);

	if (bullet)
	{
		Scene* currentScene = Director::getInstance()->getRunningScene();
		GameScene* gameScene = static_cast<GameScene*>(currentScene->getChildByName("GameScene"));
		GameLayer* gameLayer = gameScene->GetGameLayer();
		UILayer* uiLayer = gameScene->GetUILayer();

		gameLayer->addChild(bullet);

		sling->ShotComplete();

		if (m_colliderManager->HasBulletToShot())
		{
			sling->LoadBullet();
		}
	}
}

void GameManager::Play(GameLayer* gameLayer, UILayer* uiLayer)
{
	Vector<Collider*>& colliders = m_colliderManager->m_colliders;
	Vector<Target*>& targets = m_targetManager->m_targets;
	Collider* collider = nullptr;

	for (int i = 0; i < colliders.size(); i++)
	{
		collider = colliders.at(i);
		if (collider->IsFlying())
		{
			collider->Act();
			CheckCollide(collider, targets);
		}

		if (collider->IsBullet())
		{
			Bullet* bullet = static_cast<Bullet*>(collider);
			if (bullet->IsToExplode())
			{
				Explosion* explosion = bullet->GetExplosion();
				m_colliderManager->AddExplosion(explosion);
				gameLayer->addChild(explosion);
			}
		}
	}

	m_colliderManager->EraseDeadColliders();
	m_targetManager->EraseDeadTargets();
	ControlWinFailProgress(uiLayer);
}

void GameManager::CheckCollide(Collider* collider, Vector<Target*>& targets)
{
	m_lastTarget = nullptr; // ѹ 浹 Ÿٿ  浹      浹üũ  ʵ .
	bool collidingCheck = false; // 浹 Ÿ ִ üũ. --> lastTarget  ʿ䰡 ִüũ
	for (Target* target : targets)
	{
		if (target == m_lastTarget)
		{
			break;
			collidingCheck = true;
		}

		if (target->IsEnemy())
		{
			m_targetManager->SaveEnemyPosition(target->getPosition());
			EnemyDyingEffect();
		}

		if (collider->IsBullet())
		{

			if (IsCollision(target, collider))
			{
				m_lastTarget = target;
				target->ApplyCollisionEffect(collider);
				collidingCheck = true;
			}
		}
		else
		{
			Explosion* explosion = static_cast<Explosion*>(collider);
			const float explosionRadius = explosion->GetBoundingRadius();
			const Vec2 explosionPosition = explosion->getPosition();
			const Rect targetBoundingBox = target->GetBoundingArea();

			if ( targetBoundingBox.intersectsCircle( explosionPosition, explosionRadius) )
			{
				target->ApplyCollisionEffect(explosion);
			}
		}
	}

	if (!collidingCheck)
	{
		m_lastTarget = nullptr;
	}
}

void GameManager::EnemyDyingEffect()
{
	/*
	ParticleSmoke* enemyDyingEffect = ParticleSmoke::create();
	enemyDyingEffect->setPosition(enemyPos);
	gameLayer->addChild(enemyDyingEffect);
	*/
}

void GameManager::SetCollectionPos(const Vec2& pos)
{
	const Vec2 compensateToParentPos = Vec2(160, 0);
	m_curCollection->setPosition(pos + compensateToParentPos);
}

void GameManager::EarnCollectionEvent(UILayer* uiLayer)
{
	GameScene* gameScene = static_cast<GameScene*>(uiLayer->getParent());
	const Point& enemyPos = m_targetManager->GetEnemyPosition();
	const Vec2& aboveCharacterPos = gameScene->GetCharacterPos() + Vec2(0, 100);

	m_curCollection = m_collectionManager->GetCollectionSprOfStage(m_stage);
	m_curCollection->setPosition(enemyPos);
	uiLayer->addChild(m_curCollection);

	//part 1
	MoveBy* moveBy_00 = MoveBy::create(1.50f, Point(0, -10));
	MoveBy* moveBy_01 = MoveBy::create(1.00f, Point(0, -10));

	Blink* blink_00 = Blink::create(1.50f, 5);
	Blink* blink_01 = Blink::create(1.00f, 5);

	FadeIn* fadeIn_00 = FadeIn::create(1.50f);
	FadeOut* fadeOut_00 = FadeOut::create(1.00f);

	Spawn* spawn_00 = Spawn::create(fadeIn_00, moveBy_00, blink_00, NULL);
	Spawn* spawn_01 = Spawn::create(fadeOut_00, moveBy_01, blink_01, NULL);

	//part 2
	CallFuncN* callFuncN = CallFuncN::create(CC_CALLBACK_0
		(GameManager::SetCollectionPos, this, aboveCharacterPos));

	MoveBy* moveBy_02 = MoveBy::create(1.50f, Point(0, -30));
	MoveBy* moveBy_03 = MoveBy::create(1.00f, Point(0, -20));

	Blink* blink_02 = Blink::create(1.50f, 5);
	Blink* blink_03 = Blink::create(1.00f, 5);

	FadeIn* fadeIn_01 = FadeIn::create(0.01f);
	FadeOut* fadeOut_01 = FadeOut::create(2.50f);

	Spawn* spawn_02 = Spawn::create(fadeIn_01, moveBy_02, blink_02, NULL);
	Spawn* spawn_03 = Spawn::create(fadeOut_01, moveBy_03, blink_03, NULL);

	Sequence* sequence = Sequence::create(
		spawn_00, spawn_01, callFuncN, spawn_02, spawn_03, NULL);

	m_curCollection->runAction(sequence);
}

void GameManager::WinProgress(UILayer* uiLayer)
{
	int lastStage = UserDefault::getInstance()->getIntegerForKey(ConstVars::LASTSTAGE);

	if (m_stage == lastStage &&
		(m_stage == CollectionManager::SHOES ||
		m_stage == CollectionManager::SCARF ||
		m_stage == CollectionManager::BOTTLE ||
		m_stage == CollectionManager::MONITOR ||
		m_stage == CollectionManager::LETTER))
	{
		//EarnCollectionEvent(uiLayer);

		//DelayTime* waitEventTime = DelayTime::create(4.50f);
		//CallFuncN* showWidget = CallFuncN::create(CC_CALLBACK_0(
		//	UILayer::MakeSuccessWidget, uiLayer, m_stage));
		//Sequence* waitAndshow = Sequence::create(waitEventTime, showWidget, NULL);

		//uiLayer->runAction(waitAndshow);
		uiLayer->MakeSuccessWidget(m_stage);
	}
	else
	{
		if (m_stage==0)
		{
			Director::getInstance()->popScene();
		}
		else
		{
			uiLayer->MakeSuccessWidget(m_stage);
		}
	}

	if (lastStage == m_stage && m_stage + 1 <= StageInformation::GetMaxStageNum())
	{
		UserDefault::getInstance()->setIntegerForKey(ConstVars::LASTSTAGE, m_stage + 1);
	}
}

void GameManager::FailProgress(UILayer* uiLayer)
{
	if (m_stage == 0)
	{
		Director::getInstance()->popScene();
	}
	else
	{
		uiLayer->MakeFailWidget(m_stage);
	}
}

void GameManager::ControlWinFailProgress(UILayer* uiLayer)
{
	if (!m_isJudged)
	{
		if (!m_targetManager->HasEnemy())
		{
			m_isJudged = true;
			m_sling->ShotComplete();
			WinProgress(uiLayer);
		}
		else if (!m_colliderManager->HasCollider()){
			m_isJudged = true;
			m_sling->ShotComplete();
			FailProgress(uiLayer);
		}
	}
}

bool GameManager::IsCollision(Target* target, Collider* collider)
{

	float rotation = target->getRotation();
	const Rect colliderBoundingBox = static_cast<Bullet*>(collider)->GetBoundingArea();
	const Rect targetBoundingBox = target->GetBoundingArea();

	if (rotation < 1 && rotation > -1){ //ȸ
		// 簢 浹
		if (targetBoundingBox.intersectsRect(colliderBoundingBox))
			return true;

		return false;
	}

	float colliderX = collider->getPosition().x;
	float colliderY = collider->getPosition().y;

	float minX = targetBoundingBox.getMinX(); // left margin
	float maxX = targetBoundingBox.getMaxX(); // right margin
	float minY = targetBoundingBox.getMinY(); // lower margin
	float maxY = targetBoundingBox.getMaxY(); // upper margin
	Point LL(minX, minY);
	Point LU(minX, maxY);
	Point RL(maxX, minY);
	Point RU(maxX, maxY);

	//ȸ簢
	LL.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));
	LU.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));
	RL.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));
	RU.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));

	// y = Ax + upperB
	// y = Ax + lowerB
	// y = -1/Ax + leftB
	// y = -1/Ax + rightB
	float a = (RU.y- LU.y) / (RU.x - LU.x); //

	// RU.y = a * RU.x + upperB
	float upperB = RU.y - a * (RU.x);
	float lowerB = LL.y - a * (LL.x);

	// LL.y = (-1/a) * LL.x + leftB
	float leftB = LL.y - (-1 / a) * LL.x;
	float rightB = RU.y - (-1 / a) * RU.x;

	// װ  ȿ ִ üũ.
	// uppermargin  lowermargin ̿ ִ X, Y  (y-uppermargin) *(y-lowermargin) < 0
	// left  right  .

	//׿ dot
	//makeDebugPoint(Point(colliderX, (colliderX * a + upperB)), target->getParent());
	//makeDebugPoint(Point(colliderX, (colliderX * a + lowerB)), target->getParent());
	//makeDebugPoint(Point(colliderX, (colliderX * (-1 / a) + rightB)), target->getParent());
	//makeDebugPoint(Point(colliderX, (colliderX * (-1 / a) + leftB)), target->getParent());

	if (
		((colliderX * a + upperB) - colliderY) * ((colliderX * a + lowerB) - colliderY) < 0
		&&
		((colliderX * (-1 / a) + leftB) - colliderY) * ((colliderX * (-1 / a) + rightB) - colliderY) < 0
		)
	{
		return true;
	}
	else
		return false;

}

void GameManager::makeDebugPoint(Point p, Node* spr)
{
	Sprite* dot = Sprite::create(FileStuff::DEBRIS);
	dot->setScale(2.);
	spr->addChild(dot);
	Point pos = spr->convertToWorldSpace(Point::ZERO);
	dot->setPosition(p -  pos);

	Sequence* action = Sequence::create(DelayTime::create(0.1), RemoveSelf::create(),NULL);
	dot->runAction(action);
}<commit_msg>add collision angle infinte bug<commit_after>#include "stdafx.h"
#include "GameManager.h"
#include "FileStuff.h"
#include "ConstVars.h"
//̾
#include "GameLayer.h"
#include "UILayer.h"
//
#include "StageInformation.h"
#include "StageScene.h"
#include "GameScene.h"
//Ŵ
#include "CollectionManager.h"
#include "ColliderManager.h"
#include "TargetManager.h"
//ö̴
#include "Collider.h"
#include "Bullet.h"
#include "CrossBullet.h"
#include "Explosion.h"
//Ÿ
#include "Target.h"
//
#include "Sling.h"

GameManager* GameManager::m_instance = nullptr;

GameManager* GameManager::GetInstance()
{
	if (m_instance == nullptr)
	{
		m_instance = new GameManager();
	}
	return m_instance;
}

GameManager::GameManager()
{
	m_sling = nullptr;
	m_colliderManager = new ColliderManager();
	m_targetManager = new TargetManager();
	m_isJudged = false;
	m_lastTarget = nullptr;
}

void GameManager::Reset()
{
	m_sling = nullptr;
	delete m_colliderManager;
	m_colliderManager = new ColliderManager();
	delete m_targetManager;
	m_targetManager = new TargetManager();
	m_isJudged = false;
	m_lastTarget = nullptr;
}

GameManager::~GameManager() {}

void GameManager::SetStage(GameLayer* gameLayer, UILayer* uiLayer, int stageNum)
{
	Reset();
	StageInformation stageInfo(stageNum);
	m_targetManager->InitTargets(&stageInfo);
	AppendTargetsToLayer(gameLayer);
	m_colliderManager->InitBullets(&stageInfo);
	AppendBulletsToLayer(uiLayer);
	m_sling = InitSling(gameLayer);
	m_stage = stageNum;
}

Sling* GameManager::InitSling(GameLayer* gameLayer)
{
	Sling* sling = Sling::create();
	gameLayer->addChild(sling);
	sling->LoadBullet();
	return sling;
}

void GameManager::AppendTargetsToLayer(GameLayer* gameLayer)
{
	for (Target* target : m_targetManager->m_targets)
	{
		gameLayer->addChild(target);
	}
}

void GameManager::AppendBulletsToLayer(UILayer* uiLayer)
{
	for (int i = 0; i < m_colliderManager->m_bulletNum; i++)
	{
		Bullet* bullet = static_cast<Bullet*>(m_colliderManager->m_colliders.at(i));
		Sprite* bulletSpr = bullet->GetSprite();
		uiLayer->addChild(bulletSpr);
		bulletSpr->setPosition(Vec2(45 + i*25, 50));
	}
}

void GameManager::ShotBullet(Sling* sling)
{
	Bullet* bullet = m_colliderManager->GetBulletToShot(sling);

	if (bullet)
	{
		Scene* currentScene = Director::getInstance()->getRunningScene();
		GameScene* gameScene = static_cast<GameScene*>(currentScene->getChildByName("GameScene"));
		GameLayer* gameLayer = gameScene->GetGameLayer();
		UILayer* uiLayer = gameScene->GetUILayer();

		gameLayer->addChild(bullet);

		sling->ShotComplete();

		if (m_colliderManager->HasBulletToShot())
		{
			sling->LoadBullet();
		}
	}
}

void GameManager::Play(GameLayer* gameLayer, UILayer* uiLayer)
{
	Vector<Collider*>& colliders = m_colliderManager->m_colliders;
	Vector<Target*>& targets = m_targetManager->m_targets;
	Collider* collider = nullptr;

	for (int i = 0; i < colliders.size(); i++)
	{
		collider = colliders.at(i);
		if (collider->IsFlying())
		{
			collider->Act();
			CheckCollide(collider, targets);
		}

		if (collider->IsBullet())
		{
			Bullet* bullet = static_cast<Bullet*>(collider);
			if (bullet->IsToExplode())
			{
				Explosion* explosion = bullet->GetExplosion();
				m_colliderManager->AddExplosion(explosion);
				gameLayer->addChild(explosion);
			}
		}
	}

	m_colliderManager->EraseDeadColliders();
	m_targetManager->EraseDeadTargets();
	ControlWinFailProgress(uiLayer);
}

void GameManager::CheckCollide(Collider* collider, Vector<Target*>& targets)
{
	m_lastTarget = nullptr; // ѹ 浹 Ÿٿ  浹      浹üũ  ʵ .
	bool collidingCheck = false; // 浹 Ÿ ִ üũ. --> lastTarget  ʿ䰡 ִüũ
	for (Target* target : targets)
	{
		if (target == m_lastTarget)
		{
			break;
			collidingCheck = true;
		}

		if (target->IsEnemy())
		{
			m_targetManager->SaveEnemyPosition(target->getPosition());
			EnemyDyingEffect();
		}

		if (collider->IsBullet())
		{

			if (IsCollision(target, collider))
			{
				m_lastTarget = target;
				target->ApplyCollisionEffect(collider);
				collidingCheck = true;
			}
		}
		else
		{
			Explosion* explosion = static_cast<Explosion*>(collider);
			const float explosionRadius = explosion->GetBoundingRadius();
			const Vec2 explosionPosition = explosion->getPosition();
			const Rect targetBoundingBox = target->GetBoundingArea();

			if ( targetBoundingBox.intersectsCircle( explosionPosition, explosionRadius) )
			{
				target->ApplyCollisionEffect(explosion);
			}
		}
	}

	if (!collidingCheck)
	{
		m_lastTarget = nullptr;
	}
}

void GameManager::EnemyDyingEffect()
{
	/*
	ParticleSmoke* enemyDyingEffect = ParticleSmoke::create();
	enemyDyingEffect->setPosition(enemyPos);
	gameLayer->addChild(enemyDyingEffect);
	*/
}

void GameManager::SetCollectionPos(const Vec2& pos)
{
	const Vec2 compensateToParentPos = Vec2(160, 0);
	m_curCollection->setPosition(pos + compensateToParentPos);
}

void GameManager::EarnCollectionEvent(UILayer* uiLayer)
{
	GameScene* gameScene = static_cast<GameScene*>(uiLayer->getParent());
	const Point& enemyPos = m_targetManager->GetEnemyPosition();
	const Vec2& aboveCharacterPos = gameScene->GetCharacterPos() + Vec2(0, 100);

	m_curCollection = m_collectionManager->GetCollectionSprOfStage(m_stage);
	m_curCollection->setPosition(enemyPos);
	uiLayer->addChild(m_curCollection);

	//part 1
	MoveBy* moveBy_00 = MoveBy::create(1.50f, Point(0, -10));
	MoveBy* moveBy_01 = MoveBy::create(1.00f, Point(0, -10));

	Blink* blink_00 = Blink::create(1.50f, 5);
	Blink* blink_01 = Blink::create(1.00f, 5);

	FadeIn* fadeIn_00 = FadeIn::create(1.50f);
	FadeOut* fadeOut_00 = FadeOut::create(1.00f);

	Spawn* spawn_00 = Spawn::create(fadeIn_00, moveBy_00, blink_00, NULL);
	Spawn* spawn_01 = Spawn::create(fadeOut_00, moveBy_01, blink_01, NULL);

	//part 2
	CallFuncN* callFuncN = CallFuncN::create(CC_CALLBACK_0
		(GameManager::SetCollectionPos, this, aboveCharacterPos));

	MoveBy* moveBy_02 = MoveBy::create(1.50f, Point(0, -30));
	MoveBy* moveBy_03 = MoveBy::create(1.00f, Point(0, -20));

	Blink* blink_02 = Blink::create(1.50f, 5);
	Blink* blink_03 = Blink::create(1.00f, 5);

	FadeIn* fadeIn_01 = FadeIn::create(0.01f);
	FadeOut* fadeOut_01 = FadeOut::create(2.50f);

	Spawn* spawn_02 = Spawn::create(fadeIn_01, moveBy_02, blink_02, NULL);
	Spawn* spawn_03 = Spawn::create(fadeOut_01, moveBy_03, blink_03, NULL);

	Sequence* sequence = Sequence::create(
		spawn_00, spawn_01, callFuncN, spawn_02, spawn_03, NULL);

	m_curCollection->runAction(sequence);
}

void GameManager::WinProgress(UILayer* uiLayer)
{
	int lastStage = UserDefault::getInstance()->getIntegerForKey(ConstVars::LASTSTAGE);

	if (m_stage == lastStage &&
		(m_stage == CollectionManager::SHOES ||
		m_stage == CollectionManager::SCARF ||
		m_stage == CollectionManager::BOTTLE ||
		m_stage == CollectionManager::MONITOR ||
		m_stage == CollectionManager::LETTER))
	{
		//EarnCollectionEvent(uiLayer);

		//DelayTime* waitEventTime = DelayTime::create(4.50f);
		//CallFuncN* showWidget = CallFuncN::create(CC_CALLBACK_0(
		//	UILayer::MakeSuccessWidget, uiLayer, m_stage));
		//Sequence* waitAndshow = Sequence::create(waitEventTime, showWidget, NULL);

		//uiLayer->runAction(waitAndshow);
		uiLayer->MakeSuccessWidget(m_stage);
	}
	else
	{
		if (m_stage==0)
		{
			Director::getInstance()->popScene();
		}
		else
		{
			uiLayer->MakeSuccessWidget(m_stage);
		}
	}

	if (lastStage == m_stage && m_stage + 1 <= StageInformation::GetMaxStageNum())
	{
		UserDefault::getInstance()->setIntegerForKey(ConstVars::LASTSTAGE, m_stage + 1);
	}
}

void GameManager::FailProgress(UILayer* uiLayer)
{
	if (m_stage == 0)
	{
		Director::getInstance()->popScene();
	}
	else
	{
		uiLayer->MakeFailWidget(m_stage);
	}
}

void GameManager::ControlWinFailProgress(UILayer* uiLayer)
{
	if (!m_isJudged)
	{
		if (!m_targetManager->HasEnemy())
		{
			m_isJudged = true;
			m_sling->ShotComplete();
			WinProgress(uiLayer);
		}
		else if (!m_colliderManager->HasCollider()){
			m_isJudged = true;
			m_sling->ShotComplete();
			FailProgress(uiLayer);
		}
	}
}

bool GameManager::IsCollision(Target* target, Collider* collider)
{

	float rotation = target->getRotation();
	const Rect colliderBoundingBox = static_cast<Bullet*>(collider)->GetBoundingArea();
	const Rect targetBoundingBox = target->GetBoundingArea();

	if (rotation< 3 && rotation > -3
		|| rotation< 93 && rotation > 87
		|| rotation< 183 && rotation > 177
		|| rotation< 273 && rotation > 267){ //ȸ
		// 簢 浹
		if (targetBoundingBox.intersectsRect(colliderBoundingBox))
			return true;

		return false;
	}

	float colliderX = collider->getPosition().x;
	float colliderY = collider->getPosition().y;

	float minX = targetBoundingBox.getMinX(); // left margin
	float maxX = targetBoundingBox.getMaxX(); // right margin
	float minY = targetBoundingBox.getMinY(); // lower margin
	float maxY = targetBoundingBox.getMaxY(); // upper margin
	Point LL(minX, minY);
	Point LU(minX, maxY);
	Point RL(maxX, minY);
	Point RU(maxX, maxY);

	//ȸ簢
	LL.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));
	LU.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));
	RL.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));
	RU.rotate(target->getPosition(), -CC_DEGREES_TO_RADIANS(target->getRotation()));

	// y = Ax + upperB
	// y = Ax + lowerB
	// y = -1/Ax + leftB
	// y = -1/Ax + rightB
	float a = (RU.y- LU.y) / (RU.x - LU.x); //

	// RU.y = a * RU.x + upperB
	float upperB = RU.y - a * (RU.x);
	float lowerB = LL.y - a * (LL.x);

	// LL.y = (-1/a) * LL.x + leftB
	float leftB = LL.y - (-1 / a) * LL.x;
	float rightB = RU.y - (-1 / a) * RU.x;

	// װ  ȿ ִ üũ.
	// uppermargin  lowermargin ̿ ִ X, Y  (y-uppermargin) *(y-lowermargin) < 0
	// left  right  .

	//׿ dot
	//makeDebugPoint(Point(colliderX, (colliderX * a + upperB)), target->getParent());
	//makeDebugPoint(Point(colliderX, (colliderX * a + lowerB)), target->getParent());
	//makeDebugPoint(Point(colliderX, (colliderX * (-1 / a) + rightB)), target->getParent());
	//makeDebugPoint(Point(colliderX, (colliderX * (-1 / a) + leftB)), target->getParent());

	if (
		((colliderX * a + upperB) - colliderY) * ((colliderX * a + lowerB) - colliderY) < 0
		&&
		((colliderX * (-1 / a) + leftB) - colliderY) * ((colliderX * (-1 / a) + rightB) - colliderY) < 0
		)
	{
		return true;
	}
	else
		return false;

}

void GameManager::makeDebugPoint(Point p, Node* spr)
{
	Sprite* dot = Sprite::create(FileStuff::DEBRIS);
	dot->setScale(2.);
	spr->addChild(dot);
	Point pos = spr->convertToWorldSpace(Point::ZERO);
	dot->setPosition(p -  pos);

	Sequence* action = Sequence::create(DelayTime::create(0.1), RemoveSelf::create(),NULL);
	dot->runAction(action);
}<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:
  Language:  C++
  Date:
  Version:

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAnalyzeImageIO.h"
#include "itkAnalyzeImageIOFactory.h"
#include "itkConvertPixelBuffer.txx"
#include "itkDICOMImageIO2.h"
#include "itkDICOMImageIO2Factory.h"
#include "itkDefaultConvertPixelTraits.h"
#include "itkDicomImageIO.h"
#include "itkDicomImageIOFactory.h"
#include "itkFileIteratorBase.h"
#include "itkGE4ImageIO.h"
#include "itkGE4ImageIOFactory.h"
#include "itkGE5ImageIO.h"
#include "itkGE5ImageIOFactory.h"
#include "itkGEAdwImageIO.h"
#include "itkGEAdwImageIOFactory.h"
#include "itkGEImageHeader.h"
#include "itkGiplImageIO.h"
#include "itkGiplImageIOFactory.h"
#include "itkIOCommon.h"
#include "itkIPLCommonImageIO.h"
#include "itkImageFileReader.txx"
#include "itkImageFileWriter.txx"
#include "itkImageIOBase.h"
#include "itkImageIOFactory.h"
#include "itkImageIORegion.h"
#include "itkImageSeriesReader.txx"
#include "itkImageSeriesWriter.txx"
#include "itkImageWriter.txx"
#include "itkMetaImageIO.h"
#include "itkMetaImageIOFactory.h"
#include "itkMvtSunf.h"
#include "itkNumericSeriesFileIterator.h"
#include "itkPNGImageIO.h"
#include "itkPNGImageIOFactory.h"
#include "itkRawImageIO.txx"
#include "itkRawImageWriter.txx"
#include "itkSiemensVisionImageIO.h"
#include "itkSiemensVisionImageIOFactory.h"
#include "itkStimulateImageIO.h"
#include "itkStimulateImageIOFactory.h"
#include "itkVOLImageIO.h"
#include "itkVOLImageIOFactory.h"
#include "itkVTKImageIO.h"
#include "itkVTKImageIOFactory.h"
#include "itkWriter.h"
#include "pixeldata.h"

int main ( int , char*  )
{

  return 0;
}

<commit_msg>ENH: Updated to latest headers<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit (ITK)
  Module:
  Language:  C++
  Date:
  Version:

Copyright (c) 2000 National Library of Medicine
All rights reserved.

See COPYRIGHT.txt for copyright details.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAnalyzeDbh.h"
#include "itkAnalyzeImageIO.h"
#include "itkAnalyzeImageIOFactory.h"
#include "itkConvertPixelBuffer.txx"
#include "itkDICOMImageIO2.h"
#include "itkDICOMImageIO2Factory.h"
#include "itkDefaultConvertPixelTraits.h"
#include "itkDicomImageIO.h"
#include "itkDicomImageIOFactory.h"
#include "itkFileIteratorBase.h"
#include "itkGE4ImageIO.h"
#include "itkGE4ImageIOFactory.h"
#include "itkGE5ImageIO.h"
#include "itkGE5ImageIOFactory.h"
#include "itkGEAdwImageIO.h"
#include "itkGEAdwImageIOFactory.h"
#include "itkGEImageHeader.h"
#include "itkGiplImageIO.h"
#include "itkGiplImageIOFactory.h"
#include "itkIOCommon.h"
#include "itkIPLCommonImageIO.h"
#include "itkImageFileReader.txx"
#include "itkImageFileWriter.txx"
#include "itkImageIOBase.h"
#include "itkImageIOFactory.h"
#include "itkImageIORegion.h"
#include "itkImageSeriesReader.txx"
#include "itkImageSeriesWriter.txx"
#include "itkImageWriter.txx"
#include "itkMetaImageIO.h"
#include "itkMetaImageIOFactory.h"
#include "itkMvtSunf.h"
#include "itkNumericSeriesFileIterator.h"
#include "itkPNGImageIO.h"
#include "itkPNGImageIOFactory.h"
#include "itkRawImageIO.txx"
#include "itkRawImageWriter.txx"
#include "itkSiemensVisionImageIO.h"
#include "itkSiemensVisionImageIOFactory.h"
#include "itkStimulateImageIO.h"
#include "itkStimulateImageIOFactory.h"
#include "itkVOLImageIO.h"
#include "itkVOLImageIOFactory.h"
#include "itkVTKImageIO.h"
#include "itkVTKImageIOFactory.h"
#include "itkWriter.h"
#include "pixeldata.h"

int main ( int , char*  )
{

  return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbMultiResolutionPyramid.h"

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbPerBandVectorImageFilter.h"
#include "itkDiscreteGaussianImageFilter.h"
#include "itkShrinkImageFilter.h"
#include "otbImageFileReader.h"
#include "otbObjectList.h"
#include "otbStreamingImageFileWriter.h"
#include "otbCommandLineArgumentParser.h"
#include "otbStandardWriterWatcher.h"

namespace otb
{

int MultiResolutionPyramid::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("Multi-resolution pyramid tool");
  descriptor->SetDescription("Build a multi-resolution pyramid of the image.");
  descriptor->AddInputImage();
  descriptor->AddOption("NumberOfLevels","Number of levels in the pyramid (default is 1)","level",1,false, ApplicationDescriptor::Integer);
  descriptor->AddOption("ShrinkFactor","Subsampling factor (default is 2)","sfactor",1,false, ApplicationDescriptor::Integer);
  descriptor->AddOption("VarianceFactor","Before subsampling, image is smoothed with a gaussian kernel of variance VarianceFactor*ShrinkFactor. Higher values will result in more blur, lower in more aliasing (default is 0.6)","vfactor",1,false,ApplicationDescriptor::Real);
  descriptor->AddOption("FastScheme","If used, this option allows to speed-up computation by iteratively subsampling previous level of pyramid instead of processing the full input image each time. Please note that this may result in extra blur or extra aliasing.","fast",0,false,ApplicationDescriptor::Integer);
  descriptor->AddOption("OutputPrefixAndExtextension","prefix for the output files, and extension","out",2,true,ApplicationDescriptor::String);
  descriptor->AddOption("AvailableMemory","Set the maximum of available memory for the pipeline execution in mega bytes (optional, 256 by default)","ram", 1, false, otb::ApplicationDescriptor::Integer);
  return EXIT_SUCCESS;
}

int MultiResolutionPyramid::Execute(otb::ApplicationOptionsResult* parseResult)
{
  const unsigned int Dimension = 2;
  typedef otb::Image<unsigned short, Dimension> USImageType;
  typedef otb::VectorImage<unsigned short, Dimension> USVectorImageType;
  typedef otb::Image<short, Dimension> SImageType;
  typedef otb::VectorImage<short, Dimension> SVectorImageType;
  typedef otb::ImageFileReader<USVectorImageType> ReaderType;
  typedef itk::DiscreteGaussianImageFilter<USImageType,SImageType> SmoothingImageFilterType;
  typedef otb::PerBandVectorImageFilter<USVectorImageType,SVectorImageType,
    SmoothingImageFilterType>                                               SmoothingVectorImageFilterType;
  typedef itk::ShrinkImageFilter<SVectorImageType,USVectorImageType> ShrinkFilterType;
  typedef otb::StreamingImageFileWriter<USVectorImageType> WriterType;

  unsigned int nbLevels = 1;

  if(parseResult->IsOptionPresent("NumberOfLevels"))
    {
    nbLevels = parseResult->GetParameterUInt("NumberOfLevels");
    }

  unsigned int shrinkFactor = 2;

  if(parseResult->IsOptionPresent("ShrinkFactor"))
    {
    shrinkFactor = parseResult->GetParameterUInt("ShrinkFactor");
    }

  double varianceFactor = 0.6;

  if(parseResult->IsOptionPresent("VarianceFactor"))
    {
    varianceFactor = parseResult->GetParameterDouble("VarianceFactor");
    }

  bool fastScheme = parseResult->IsOptionPresent("FastScheme");

  std::string prefix = parseResult->GetParameterString("OutputPrefixAndExtextension",0);
  std::string ext = parseResult->GetParameterString("OutputPrefixAndExtextension",1);

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(parseResult->GetInputImage());

  unsigned int currentLevel = 1;
  unsigned int currentFactor = shrinkFactor;

  while(currentLevel <= nbLevels)
    {
    std::cout<<"Processing level "<<currentLevel<<" with shrink factor "<<currentFactor<<std::endl;

    if(fastScheme && currentLevel > 1)
      {
      itk::OStringStream oss;
      oss<<prefix<<"_"<<currentLevel-1<<"."<<ext;
      reader = ReaderType::New();
      reader->SetFileName(oss.str().c_str());
      }

    SmoothingVectorImageFilterType::Pointer smoothingFilter = SmoothingVectorImageFilterType::New();
    smoothingFilter->SetInput(reader->GetOutput());

    // According to
    // http://www.ipol.im/pub/algo/gjmr_line_segment_detector/
    // This is a good balance between blur and aliasing
    double variance = varianceFactor * static_cast<double>(currentFactor);
    smoothingFilter->GetFilter()->SetVariance(variance);

    ShrinkFilterType::Pointer shrinkFilter = ShrinkFilterType::New();
    shrinkFilter->SetInput(smoothingFilter->GetOutput());
    shrinkFilter->SetShrinkFactors(currentFactor);

    itk::OStringStream oss;
    oss<<prefix<<"_"<<currentLevel<<"."<<ext;

    WriterType::Pointer writer = WriterType::New();
    writer->SetInput(shrinkFilter->GetOutput());
    writer->SetFileName(oss.str().c_str());

    unsigned int ram = 256;
    if (parseResult->IsOptionPresent("AvailableMemory"))
      {
      ram = parseResult->GetParameterUInt("AvailableMemory");
      }
    writer->SetAutomaticTiledStreaming(ram);

    oss.str("");
    oss<<"Writing "<<prefix<<"_"<<currentLevel<<"."<<ext;

    otb::StandardWriterWatcher watcher(writer,shrinkFilter,oss.str().c_str());

    writer->Update();

    if(!fastScheme)
      {
      currentFactor*=shrinkFactor;
      }

    ++currentLevel;
    }

  return EXIT_SUCCESS;
}

}

<commit_msg>STYLE<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbMultiResolutionPyramid.h"

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbPerBandVectorImageFilter.h"
#include "itkDiscreteGaussianImageFilter.h"
#include "itkShrinkImageFilter.h"
#include "otbImageFileReader.h"
#include "otbObjectList.h"
#include "otbStreamingImageFileWriter.h"
#include "otbCommandLineArgumentParser.h"
#include "otbStandardWriterWatcher.h"

namespace otb
{

int MultiResolutionPyramid::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("Multi-resolution pyramid tool");
  descriptor->SetDescription("Build a multi-resolution pyramid of the image.");
  descriptor->AddInputImage();
  descriptor->AddOption("NumberOfLevels","Number of levels in the pyramid (default is 1)","level", 1, false, ApplicationDescriptor::Integer);
  descriptor->AddOption("ShrinkFactor","Subsampling factor (default is 2)","sfactor", 1, false, ApplicationDescriptor::Integer);
  descriptor->AddOption("VarianceFactor","Before subsampling, image is smoothed with a gaussian kernel of variance VarianceFactor*ShrinkFactor. Higher values will result in more blur, lower in more aliasing (default is 0.6)","vfactor", 1, false, ApplicationDescriptor::Real);
  descriptor->AddOption("FastScheme","If used, this option allows to speed-up computation by iteratively subsampling previous level of pyramid instead of processing the full input image each time. Please note that this may result in extra blur or extra aliasing.","fast", 0, false, ApplicationDescriptor::Integer);
  descriptor->AddOption("OutputPrefixAndExtextension","prefix for the output files, and extension","out", 2, true, ApplicationDescriptor::String);
  descriptor->AddOption("AvailableMemory","Set the maximum of available memory for the pipeline execution in mega bytes (optional, 256 by default)","ram", 1, false, otb::ApplicationDescriptor::Integer);
  return EXIT_SUCCESS;
}

int MultiResolutionPyramid::Execute(otb::ApplicationOptionsResult* parseResult)
{
  const unsigned int Dimension = 2;
  typedef otb::Image<unsigned short, Dimension> USImageType;
  typedef otb::VectorImage<unsigned short, Dimension> USVectorImageType;
  typedef otb::Image<short, Dimension> SImageType;
  typedef otb::VectorImage<short, Dimension> SVectorImageType;
  typedef otb::ImageFileReader<USVectorImageType> ReaderType;
  typedef itk::DiscreteGaussianImageFilter<USImageType, SImageType> SmoothingImageFilterType;
  typedef otb::PerBandVectorImageFilter<USVectorImageType, SVectorImageType,
    SmoothingImageFilterType>                                               SmoothingVectorImageFilterType;
  typedef itk::ShrinkImageFilter<SVectorImageType, USVectorImageType> ShrinkFilterType;
  typedef otb::StreamingImageFileWriter<USVectorImageType> WriterType;

  unsigned int nbLevels = 1;

  if(parseResult->IsOptionPresent("NumberOfLevels"))
    {
    nbLevels = parseResult->GetParameterUInt("NumberOfLevels");
    }

  unsigned int shrinkFactor = 2;

  if(parseResult->IsOptionPresent("ShrinkFactor"))
    {
    shrinkFactor = parseResult->GetParameterUInt("ShrinkFactor");
    }

  double varianceFactor = 0.6;

  if(parseResult->IsOptionPresent("VarianceFactor"))
    {
    varianceFactor = parseResult->GetParameterDouble("VarianceFactor");
    }

  bool fastScheme = parseResult->IsOptionPresent("FastScheme");

  std::string prefix = parseResult->GetParameterString("OutputPrefixAndExtextension", 0);
  std::string ext = parseResult->GetParameterString("OutputPrefixAndExtextension", 1);

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(parseResult->GetInputImage());

  unsigned int currentLevel = 1;
  unsigned int currentFactor = shrinkFactor;

  while(currentLevel <= nbLevels)
    {
    std::cout<<"Processing level "<<currentLevel<<" with shrink factor "<<currentFactor<<std::endl;

    if(fastScheme && currentLevel > 1)
      {
      itk::OStringStream oss;
      oss<<prefix<<"_"<<currentLevel-1<<"."<<ext;
      reader = ReaderType::New();
      reader->SetFileName(oss.str().c_str());
      }

    SmoothingVectorImageFilterType::Pointer smoothingFilter = SmoothingVectorImageFilterType::New();
    smoothingFilter->SetInput(reader->GetOutput());

    // According to
    // http://www.ipol.im/pub/algo/gjmr_line_segment_detector/
    // This is a good balance between blur and aliasing
    double variance = varianceFactor * static_cast<double>(currentFactor);
    smoothingFilter->GetFilter()->SetVariance(variance);

    ShrinkFilterType::Pointer shrinkFilter = ShrinkFilterType::New();
    shrinkFilter->SetInput(smoothingFilter->GetOutput());
    shrinkFilter->SetShrinkFactors(currentFactor);

    itk::OStringStream oss;
    oss<<prefix<<"_"<<currentLevel<<"."<<ext;

    WriterType::Pointer writer = WriterType::New();
    writer->SetInput(shrinkFilter->GetOutput());
    writer->SetFileName(oss.str().c_str());

    unsigned int ram = 256;
    if (parseResult->IsOptionPresent("AvailableMemory"))
      {
      ram = parseResult->GetParameterUInt("AvailableMemory");
      }
    writer->SetAutomaticTiledStreaming(ram);

    oss.str("");
    oss<<"Writing "<<prefix<<"_"<<currentLevel<<"."<<ext;

    otb::StandardWriterWatcher watcher(writer, shrinkFilter, oss.str().c_str());

    writer->Update();

    if(!fastScheme)
      {
      currentFactor*=shrinkFactor;
      }

    ++currentLevel;
    }

  return EXIT_SUCCESS;
}

}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkHandleRepresentation.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkHandleRepresentation.h"
#include "vtkCoordinate.h"
#include "vtkInteractorObserver.h"
#include "vtkObjectFactory.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"

vtkCxxRevisionMacro(vtkHandleRepresentation, "1.7");

//----------------------------------------------------------------------
vtkHandleRepresentation::vtkHandleRepresentation()
{
  // Positions are maintained via a vtkCoordinate
  this->DisplayPosition = vtkCoordinate::New();
  this->DisplayPosition->SetCoordinateSystemToDisplay();

  this->WorldPosition = vtkCoordinate::New();
  this->WorldPosition->SetCoordinateSystemToWorld();

  this->InteractionState = vtkHandleRepresentation::Outside;
  this->Tolerance = 15;
  this->ActiveRepresentation = 0;
  this->Constrained = 0;

  this->DisplayPositionTime.Modified();
  this->WorldPositionTime.Modified();
}

//----------------------------------------------------------------------
vtkHandleRepresentation::~vtkHandleRepresentation()
{
  this->DisplayPosition->Delete();
  this->WorldPosition->Delete();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::SetDisplayPosition(double pos[3])
{
  this->DisplayPosition->SetValue(pos);
  if ( this->Renderer )
    {
    double *p = this->DisplayPosition->GetComputedWorldValue(this->Renderer);
    this->WorldPosition->SetValue(p[0], p[1], p[2]);
    }
  this->DisplayPositionTime.Modified();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::GetDisplayPosition(double pos[3])
{
  // The world position maintains the position
  if ( this->Renderer && (this->WorldPositionTime > this->DisplayPositionTime) )
    {
    int *p = this->WorldPosition->GetComputedDisplayValue(this->Renderer);
    this->DisplayPosition->SetValue(p[0],p[1],0.0);
    }
  this->DisplayPosition->GetValue(pos);
}

double* vtkHandleRepresentation::GetDisplayPosition()
{
  return this->DisplayPosition->GetValue();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::SetWorldPosition(double pos[3])
{
  this->WorldPosition->SetValue(pos);
  this->WorldPositionTime.Modified();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::GetWorldPosition(double pos[3])
{
  this->WorldPosition->GetValue(pos);
}

double* vtkHandleRepresentation::GetWorldPosition()
{
  return this->WorldPosition->GetValue();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::SetRenderer(vtkRenderer *ren)
{
  this->DisplayPosition->SetViewport(ren);
  this->WorldPosition->SetViewport(ren);
  this->Superclass::SetRenderer(ren);
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::ShallowCopy(vtkProp *prop)
{
  vtkHandleRepresentation *rep = vtkHandleRepresentation::SafeDownCast(prop);
  if ( rep )
    {
    this->SetTolerance(rep->GetTolerance());
    this->SetActiveRepresentation(rep->GetActiveRepresentation());
    this->SetConstrained(rep->GetConstrained());
    }
  this->Superclass::ShallowCopy(prop);
}

//----------------------------------------------------------------------
unsigned long vtkHandleRepresentation::GetMTime()
{
  unsigned long mTime=this->Superclass::GetMTime();
  unsigned long wMTime=this->WorldPosition->GetMTime();
  mTime = ( wMTime > mTime ? wMTime : mTime );
  unsigned long dMTime=this->DisplayPosition->GetMTime();
  mTime = ( dMTime > mTime ? dMTime : mTime );

  return mTime;
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
  //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
  this->Superclass::PrintSelf(os,indent);

  double p[3];
  this->GetDisplayPosition(p);
  os << indent << "Display Position: (" << p[0] << ", "
               << p[1] << ", " << p[2] << ")\n";

  this->GetWorldPosition(p);
  os << indent << "World Position: (" << p[0] << ", "
               << p[1] << ", " << p[2] << ")\n";

  os << indent << "Constrained: "
     << (this->Constrained ? "On" : "Off") << "\n";

  os << indent << "Tolerance: " << this->Tolerance << "\n";

  os << indent << "Active Representation: "
     << (this->ActiveRepresentation ? "On" : "Off") << "\n";
}
<commit_msg>STYLE:Marked method<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkHandleRepresentation.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkHandleRepresentation.h"
#include "vtkCoordinate.h"
#include "vtkInteractorObserver.h"
#include "vtkObjectFactory.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"

vtkCxxRevisionMacro(vtkHandleRepresentation, "1.8");

//----------------------------------------------------------------------
vtkHandleRepresentation::vtkHandleRepresentation()
{
  // Positions are maintained via a vtkCoordinate
  this->DisplayPosition = vtkCoordinate::New();
  this->DisplayPosition->SetCoordinateSystemToDisplay();

  this->WorldPosition = vtkCoordinate::New();
  this->WorldPosition->SetCoordinateSystemToWorld();

  this->InteractionState = vtkHandleRepresentation::Outside;
  this->Tolerance = 15;
  this->ActiveRepresentation = 0;
  this->Constrained = 0;

  this->DisplayPositionTime.Modified();
  this->WorldPositionTime.Modified();
}

//----------------------------------------------------------------------
vtkHandleRepresentation::~vtkHandleRepresentation()
{
  this->DisplayPosition->Delete();
  this->WorldPosition->Delete();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::SetDisplayPosition(double pos[3])
{
  this->DisplayPosition->SetValue(pos);
  if ( this->Renderer )
    {
    double *p = this->DisplayPosition->GetComputedWorldValue(this->Renderer);
    this->WorldPosition->SetValue(p[0], p[1], p[2]);
    }
  this->DisplayPositionTime.Modified();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::GetDisplayPosition(double pos[3])
{
  // The world position maintains the position
  if ( this->Renderer && (this->WorldPositionTime > this->DisplayPositionTime) )
    {
    int *p = this->WorldPosition->GetComputedDisplayValue(this->Renderer);
    this->DisplayPosition->SetValue(p[0],p[1],0.0);
    }
  this->DisplayPosition->GetValue(pos);
}

//----------------------------------------------------------------------
double* vtkHandleRepresentation::GetDisplayPosition()
{
  return this->DisplayPosition->GetValue();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::SetWorldPosition(double pos[3])
{
  this->WorldPosition->SetValue(pos);
  this->WorldPositionTime.Modified();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::GetWorldPosition(double pos[3])
{
  this->WorldPosition->GetValue(pos);
}

double* vtkHandleRepresentation::GetWorldPosition()
{
  return this->WorldPosition->GetValue();
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::SetRenderer(vtkRenderer *ren)
{
  this->DisplayPosition->SetViewport(ren);
  this->WorldPosition->SetViewport(ren);
  this->Superclass::SetRenderer(ren);
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::ShallowCopy(vtkProp *prop)
{
  vtkHandleRepresentation *rep = vtkHandleRepresentation::SafeDownCast(prop);
  if ( rep )
    {
    this->SetTolerance(rep->GetTolerance());
    this->SetActiveRepresentation(rep->GetActiveRepresentation());
    this->SetConstrained(rep->GetConstrained());
    }
  this->Superclass::ShallowCopy(prop);
}

//----------------------------------------------------------------------
unsigned long vtkHandleRepresentation::GetMTime()
{
  unsigned long mTime=this->Superclass::GetMTime();
  unsigned long wMTime=this->WorldPosition->GetMTime();
  mTime = ( wMTime > mTime ? wMTime : mTime );
  unsigned long dMTime=this->DisplayPosition->GetMTime();
  mTime = ( dMTime > mTime ? dMTime : mTime );

  return mTime;
}

//----------------------------------------------------------------------
void vtkHandleRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
  //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
  this->Superclass::PrintSelf(os,indent);

  double p[3];
  this->GetDisplayPosition(p);
  os << indent << "Display Position: (" << p[0] << ", "
               << p[1] << ", " << p[2] << ")\n";

  this->GetWorldPosition(p);
  os << indent << "World Position: (" << p[0] << ", "
               << p[1] << ", " << p[2] << ")\n";

  os << indent << "Constrained: "
     << (this->Constrained ? "On" : "Off") << "\n";

  os << indent << "Tolerance: " << this->Tolerance << "\n";

  os << indent << "Active Representation: "
     << (this->ActiveRepresentation ? "On" : "Off") << "\n";
}
<|endoftext|>


<commit_before>#include "Camera.h"
#include "Utility.h"
#include <GL\glew.h>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtc\quaternion.hpp>
#include <glm\gtx\transform.hpp>
#include <glm\gtx\quaternion.hpp>

Camera::Camera( glm::vec2 windowSize, ProjectionType type, glm::vec2 zLimits) :
	windowSize( windowSize ), projectionType( type ), projectionZLimit( zLimits ),
	position({ 0.0f, 5.0f, 0.0f }), forward({ 0.0f, 0.0f, -1.0f }), up({ 0.0f, 1.0f, 0.0f }), axis(glm::cross(forward, up))
{
	setupView();
	refreshProjection();
	refreshViewProjection();
}

Camera::~Camera(void)
{
}

// VIEW
void Camera::setupView()
{
	view = glm::lookAt(position, position + forward, -glm::cross(forward,axis));
	refreshViewProjection();
}

void Camera::applyOffset(glm::vec3 offset)
{
	position += offset;
	setupView();
}

void Camera::setMoveForward(bool movement) {
	moveForward = movement;
}

void Camera::setMoveBackward(bool movement) {
	moveBackward = movement;
}

void Camera::setMoveLeft(bool movement) {
	moveLeft = movement;
}

void Camera::setMoveRight(bool movement) {
	moveRight = movement;
}

void Camera::rotate(int idx, int idy)
{
	float dx = -100.f * idx / windowSize.x;
	float dy = -100.f * idy / windowSize.y;

	auto pitch = glm::angleAxis(dy, axis);
	auto heading = glm::angleAxis(dx, up);

	glm::quat temp = glm::cross(pitch, heading);
	temp = glm::normalize(temp);
	//update the direction from the quaternion
	forward = glm::rotate(temp, forward);
	axis = glm::rotate(heading, axis);
	// if up changes, camera becomes too free
	//up = glm::rotate(pitch, up);

	setupView();
}

void Camera::update(float dt)
{
	int forwardMovement = (moveForward ? 1 : 0) + (moveBackward ? -1 : 0);
	if (forwardMovement != 0) {
		applyOffset( forward * (forwardMovement * dt * 10.0f) );
	}
	int sideMovement = (moveLeft ? -1 : 0) + (moveRight ? 1 : 0);
	if (sideMovement != 0) {
		applyOffset( axis * (sideMovement * dt * 10.0f) );
	}
}

const glm::mat4 & Camera::getView() const
{
	return view;
}

// PROJECTION

void Camera::refreshProjection()
{
	if (projectionType == PERSPECTIVE) {
		setupPerspectiveProjection( 45.0f, windowSize.x/windowSize.y, projectionZLimit.x, projectionZLimit.y);
	}
	else {
		// TODO: projection start and size are dependant on the world and cameras relative eye offset
		// Ortho size could and should be open to outside interpretations, for now it is fixed
		setupOtrhographicProjection({ 0.0f,0.0f }, { windowSize.x,windowSize.y }, projectionZLimit.x, projectionZLimit.y);
	}
}

void Camera::setupOtrhographicProjection(glm::vec2 projectionStart, glm::vec2 projectionSize, float zNear, float zFar)
{
	projectionType = ProjectionType::OTRHOGRAPHIC;
	this->projectionStart = projectionStart;
	this->projectionSize = projectionSize;
	projection = glm::ortho(
		projectionStart.x, projectionStart.x + projectionSize.x,
		projectionStart.y, projectionStart.y + projectionSize.y,
		zNear, zFar);
	refreshViewProjection();
}

void Camera::setupPerspectiveProjection(float fovy, float aspectRatio, float zNear, float zFar)
{
	projectionType = ProjectionType::PERSPECTIVE;
	projection = glm::perspective(fovy, aspectRatio, zNear, zFar);
	refreshViewProjection();
}

const glm::mat4 & Camera::getProjection() const
{
	return projection;
}

// VIEW PROJECTION
void Camera::refreshViewProjection()
{
	viewProjection = projection * view;
}

const glm::mat4& Camera::getViewProjection() const
{
	return viewProjection;
}

void Camera::updateCamera()
{
	// OLD:
	/*glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glTranslatef(0, 0, -distance);

	glRotatef(angles.x, 1.0, 0.0, 0.0);
	glRotatef(angles.y, 0.0, 1.0, 0.0);

	glTranslatef(-center.x, -center.y, -center.z);*/
	/*glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(FOVy, aspectRatio, NCP, FCP); */
	frustum.setupGLProjection();
	frustum.CalculateFrustum();
}

// VIEWPORT
void Camera::windowDidResize(float width, float height)
{
	// TODO: viewport could stretch to fit, or it could be static
	windowSize.x = width;
	windowSize.y = height;
	setupViewport(0,0,width,height);
	refreshProjection();
}

void Camera::setupViewport(float x, float y, float width, float height)
{
	viewportPos.x = x;
	viewportPos.y = y;
	viewportSize.x = width;
	viewportSize.y = height;
}

void Camera::loadViewport()
{
	glViewport(viewportPos.x, viewportPos.y, viewportSize.x, viewportSize.y);
}

const Frustum & Camera::getFrustum() const
{
	return frustum;
}
<commit_msg>Speed up camera movement.<commit_after>#include "Camera.h"
#include "Utility.h"
#include <GL\glew.h>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtc\quaternion.hpp>
#include <glm\gtx\transform.hpp>
#include <glm\gtx\quaternion.hpp>

Camera::Camera( glm::vec2 windowSize, ProjectionType type, glm::vec2 zLimits) :
	windowSize( windowSize ), projectionType( type ), projectionZLimit( zLimits ),
	position({ 0.0f, 5.0f, 0.0f }), forward({ 0.0f, 0.0f, -1.0f }), up({ 0.0f, 1.0f, 0.0f }), axis(glm::cross(forward, up))
{
	setupView();
	refreshProjection();
	refreshViewProjection();
}

Camera::~Camera(void)
{
}

// VIEW
void Camera::setupView()
{
	view = glm::lookAt(position, position + forward, -glm::cross(forward,axis));
	refreshViewProjection();
}

void Camera::applyOffset(glm::vec3 offset)
{
	position += offset;
	setupView();
}

void Camera::setMoveForward(bool movement) {
	moveForward = movement;
}

void Camera::setMoveBackward(bool movement) {
	moveBackward = movement;
}

void Camera::setMoveLeft(bool movement) {
	moveLeft = movement;
}

void Camera::setMoveRight(bool movement) {
	moveRight = movement;
}

void Camera::rotate(int idx, int idy)
{
	float dx = -100.f * idx / windowSize.x;
	float dy = -100.f * idy / windowSize.y;

	auto pitch = glm::angleAxis(dy, axis);
	auto heading = glm::angleAxis(dx, up);

	glm::quat temp = glm::cross(pitch, heading);
	temp = glm::normalize(temp);
	//update the direction from the quaternion
	forward = glm::rotate(temp, forward);
	axis = glm::rotate(heading, axis);
	// if up changes, camera becomes too free
	//up = glm::rotate(pitch, up);

	setupView();
}

void Camera::update(float dt)
{
	float speed = 30.0f;
	int forwardMovement = (moveForward ? 1 : 0) + (moveBackward ? -1 : 0);
	if (forwardMovement != 0) {
		applyOffset( forward * (forwardMovement * dt * speed) );
	}
	int sideMovement = (moveLeft ? -1 : 0) + (moveRight ? 1 : 0);
	if (sideMovement != 0) {
		applyOffset( axis * (sideMovement * dt * speed) );
	}
}

const glm::mat4 & Camera::getView() const
{
	return view;
}

// PROJECTION

void Camera::refreshProjection()
{
	if (projectionType == PERSPECTIVE) {
		setupPerspectiveProjection( 45.0f, windowSize.x/windowSize.y, projectionZLimit.x, projectionZLimit.y);
	}
	else {
		// TODO: projection start and size are dependant on the world and cameras relative eye offset
		// Ortho size could and should be open to outside interpretations, for now it is fixed
		setupOtrhographicProjection({ 0.0f,0.0f }, { windowSize.x,windowSize.y }, projectionZLimit.x, projectionZLimit.y);
	}
}

void Camera::setupOtrhographicProjection(glm::vec2 projectionStart, glm::vec2 projectionSize, float zNear, float zFar)
{
	projectionType = ProjectionType::OTRHOGRAPHIC;
	this->projectionStart = projectionStart;
	this->projectionSize = projectionSize;
	projection = glm::ortho(
		projectionStart.x, projectionStart.x + projectionSize.x,
		projectionStart.y, projectionStart.y + projectionSize.y,
		zNear, zFar);
	refreshViewProjection();
}

void Camera::setupPerspectiveProjection(float fovy, float aspectRatio, float zNear, float zFar)
{
	projectionType = ProjectionType::PERSPECTIVE;
	projection = glm::perspective(fovy, aspectRatio, zNear, zFar);
	refreshViewProjection();
}

const glm::mat4 & Camera::getProjection() const
{
	return projection;
}

// VIEW PROJECTION
void Camera::refreshViewProjection()
{
	viewProjection = projection * view;
}

const glm::mat4& Camera::getViewProjection() const
{
	return viewProjection;
}

void Camera::updateCamera()
{
	// OLD:
	/*glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glTranslatef(0, 0, -distance);

	glRotatef(angles.x, 1.0, 0.0, 0.0);
	glRotatef(angles.y, 0.0, 1.0, 0.0);

	glTranslatef(-center.x, -center.y, -center.z);*/
	/*glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(FOVy, aspectRatio, NCP, FCP); */
	frustum.setupGLProjection();
	frustum.CalculateFrustum();
}

// VIEWPORT
void Camera::windowDidResize(float width, float height)
{
	// TODO: viewport could stretch to fit, or it could be static
	windowSize.x = width;
	windowSize.y = height;
	setupViewport(0,0,width,height);
	refreshProjection();
}

void Camera::setupViewport(float x, float y, float width, float height)
{
	viewportPos.x = x;
	viewportPos.y = y;
	viewportSize.x = width;
	viewportSize.y = height;
}

void Camera::loadViewport()
{
	glViewport(viewportPos.x, viewportPos.y, viewportSize.x, viewportSize.y);
}

const Frustum & Camera::getFrustum() const
{
	return frustum;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2014 Couchbase, 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 "config.h"
#include "ep_engine.h"
#include "connmap.h"
#include "dcp-backfill-manager.h"
#include "dcp-backfill.h"
#include "dcp-producer.h"

static const size_t sleepTime = 1;

class BackfillManagerTask : public GlobalTask {
public:
    BackfillManagerTask(EventuallyPersistentEngine* e, connection_t c,
                        const Priority &p, double sleeptime = 0,
                        bool shutdown = false)
        : GlobalTask(e, p, sleeptime, shutdown), conn(c) {}

    bool run();

    std::string getDescription();

private:
    connection_t conn;
};

bool BackfillManagerTask::run() {
    DcpProducer* producer = static_cast<DcpProducer*>(conn.get());
    if (producer->doDisconnect()) {
        return false;
    }

    backfill_status_t status = producer->getBackfillManager()->backfill();
    if (status == backfill_finished) {
        return false;
    } else if (status == backfill_snooze) {
        snooze(sleepTime);
    }

    if (engine->getEpStats().isShutdown) {
        return false;
    }

    return true;
}

std::string BackfillManagerTask::getDescription() {
    std::stringstream ss;
    ss << "Backfilling items for " << conn->getName();
    return ss.str();
}

BackfillManager::BackfillManager(EventuallyPersistentEngine* e, connection_t c)
    : engine(e), conn(c), managerTask(NULL) {

    Configuration& config = e->getConfiguration();

    scanBuffer.bytesRead = 0;
    scanBuffer.itemsRead = 0;
    scanBuffer.maxBytes = config.getDcpScanByteLimit();
    scanBuffer.maxItems = config.getDcpScanItemLimit();

    buffer.bytesRead = 0;
    buffer.maxBytes = config.getDcpBackfillByteLimit();
    buffer.nextReadSize = 0;
    buffer.full = false;
}

BackfillManager::~BackfillManager() {
    LockHolder lh(lock);
    if (managerTask) {
        managerTask->cancel();
    }

    while (!activeBackfills.empty()) {
        DCPBackfill* backfill = activeBackfills.front();
        activeBackfills.pop();
        backfill->cancel();
        delete backfill;
    }

    while (!snoozingBackfills.empty()) {
        DCPBackfill* backfill = (snoozingBackfills.front()).second;
        snoozingBackfills.pop_front();
        backfill->cancel();
        delete backfill;
    }
}

void BackfillManager::schedule(stream_t stream, uint64_t start, uint64_t end) {
    LockHolder lh(lock);
    activeBackfills.push(new DCPBackfill(engine, stream, start, end));

    if (managerTask) {
        managerTask->snooze(0);
        return;
    }

    managerTask = new BackfillManagerTask(engine, conn,
                                          Priority::BackfillTaskPriority);
    ExecutorPool::get()->schedule(managerTask, NONIO_TASK_IDX);
}

bool BackfillManager::bytesRead(uint32_t bytes) {
    LockHolder lh(lock);
    if (scanBuffer.itemsRead >= scanBuffer.maxItems) {
        return false;
    }

    // Always allow an item to be backfilled if the scan buffer is empty,
    // otherwise check to see if there is room for the item.
    if (scanBuffer.bytesRead + bytes <= scanBuffer.maxBytes ||
        scanBuffer.bytesRead == 0) {
        scanBuffer.bytesRead += bytes;
    }

    if (buffer.bytesRead == 0 || buffer.bytesRead + bytes <= buffer.maxBytes) {
        buffer.bytesRead += bytes;
    } else {
        scanBuffer.bytesRead -= bytes;
        buffer.full = true;
        buffer.nextReadSize = bytes;
        return false;
    }

    scanBuffer.itemsRead++;

    return true;
}

void BackfillManager::bytesSent(uint32_t bytes) {
    LockHolder lh(lock);
    cb_assert(buffer.bytesRead >= bytes);
    buffer.bytesRead -= bytes;

    if (buffer.full) {
        uint32_t bufferSize = buffer.bytesRead;
        bool canFitNext = buffer.maxBytes - bufferSize >= buffer.nextReadSize;
        bool enoughCleared = bufferSize < (buffer.maxBytes * 3 / 4);
        if (canFitNext && enoughCleared) {
            buffer.nextReadSize = 0;
            buffer.full = false;
            if (managerTask) {
                managerTask->snooze(0);
            }
        }
    }
}

backfill_status_t BackfillManager::backfill() {
    LockHolder lh(lock);
    if (buffer.full) {
        return backfill_snooze;
    }

    if (activeBackfills.empty() && snoozingBackfills.empty()) {
        managerTask.reset();
        return backfill_finished;
    }

    if (engine->getEpStore()->isMemoryUsageTooHigh()) {
        LOG(EXTENSION_LOG_WARNING, "DCP backfilling task for connection %s "
            "temporarily suspended because the current memory usage is too "
            "high", conn->getName().c_str());
        return backfill_snooze;
    }

    while (!snoozingBackfills.empty()) {
        std::pair<rel_time_t, DCPBackfill*> snoozer = snoozingBackfills.front();
        // If snoozing task is found to be sleeping for greater than
        // allowed snoozetime, push into active queue
        if (snoozer.first + sleepTime <= ep_current_time()) {
            DCPBackfill* bfill = snoozer.second;
            activeBackfills.push(bfill);
            snoozingBackfills.pop_front();
        } else {
            break;
        }
    }

    if (activeBackfills.empty()) {
        return backfill_snooze;
    }

    DCPBackfill* backfill = activeBackfills.front();

    lh.unlock();
    backfill_status_t status = backfill->run();
    lh.lock();

    if (status == backfill_success && buffer.full) {
        // Snooze while the buffer is full
        return backfill_snooze;
    }

    scanBuffer.bytesRead = 0;
    scanBuffer.itemsRead = 0;

    activeBackfills.pop();
    if (status == backfill_success) {
        activeBackfills.push(backfill);
    } else if (status == backfill_finished) {
        lh.unlock();
        delete backfill;
    } else if (status == backfill_snooze) {
        uint16_t vbid = backfill->getVBucketId();
        RCPtr<VBucket> vb = engine->getVBucket(vbid);
        if (vb) {
            snoozingBackfills.push_back(
                                std::make_pair(ep_current_time(), backfill));
            shared_ptr<Callback<uint64_t> >
                                cb(new BackfillCallback(backfill->getEndSeqno(),
                                                        vbid, conn));
            vb->addPersistenceNotification(cb);
        } else {
            lh.unlock();
            LOG(EXTENSION_LOG_WARNING, "Deleting the backfill, as vbucket %d "
                    "seems to have been deleted!", vbid);
            backfill->cancel();
            delete backfill;
        }
    } else {
        abort();
    }

    return backfill_success;
}

void BackfillManager::wakeUpTask() {
    LockHolder lh(lock);
    if (managerTask) {
        managerTask->snooze(0);
    }
}

void BackfillManager::wakeUpSnoozingBackfills(uint16_t vbid) {
    LockHolder lh(lock);
    std::list<std::pair<rel_time_t, DCPBackfill*> >::iterator it;
    for (it = snoozingBackfills.begin(); it != snoozingBackfills.end(); ++it) {
        DCPBackfill *bfill = (*it).second;
        if (vbid == bfill->getVBucketId()) {
            activeBackfills.push(bfill);
            snoozingBackfills.erase(it);
            managerTask->snooze(0);
            return;
        }
    }
}

bool BackfillManager::addIfLessThanMax(AtomicValue<uint32_t>& val,
                                       uint32_t incr, uint32_t max) {
    do {
        uint32_t oldVal = val.load();
        uint32_t newVal = oldVal + incr;

        if (newVal > max) {
            return false;
        }

        if (val.compare_exchange_strong(oldVal, newVal)) {
            return true;
        }
    } while (true);
}
<commit_msg>MB-13070: Check for a dead backfill task when scheduling backfill<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2014 Couchbase, 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 "config.h"
#include "ep_engine.h"
#include "connmap.h"
#include "dcp-backfill-manager.h"
#include "dcp-backfill.h"
#include "dcp-producer.h"

static const size_t sleepTime = 1;

class BackfillManagerTask : public GlobalTask {
public:
    BackfillManagerTask(EventuallyPersistentEngine* e, connection_t c,
                        const Priority &p, double sleeptime = 0,
                        bool shutdown = false)
        : GlobalTask(e, p, sleeptime, shutdown), conn(c) {}

    bool run();

    std::string getDescription();

private:
    connection_t conn;
};

bool BackfillManagerTask::run() {
    DcpProducer* producer = static_cast<DcpProducer*>(conn.get());
    if (producer->doDisconnect()) {
        return false;
    }

    backfill_status_t status = producer->getBackfillManager()->backfill();
    if (status == backfill_finished) {
        return false;
    } else if (status == backfill_snooze) {
        snooze(sleepTime);
    }

    if (engine->getEpStats().isShutdown) {
        return false;
    }

    return true;
}

std::string BackfillManagerTask::getDescription() {
    std::stringstream ss;
    ss << "Backfilling items for " << conn->getName();
    return ss.str();
}

BackfillManager::BackfillManager(EventuallyPersistentEngine* e, connection_t c)
    : engine(e), conn(c), managerTask(NULL) {

    Configuration& config = e->getConfiguration();

    scanBuffer.bytesRead = 0;
    scanBuffer.itemsRead = 0;
    scanBuffer.maxBytes = config.getDcpScanByteLimit();
    scanBuffer.maxItems = config.getDcpScanItemLimit();

    buffer.bytesRead = 0;
    buffer.maxBytes = config.getDcpBackfillByteLimit();
    buffer.nextReadSize = 0;
    buffer.full = false;
}

BackfillManager::~BackfillManager() {
    LockHolder lh(lock);
    if (managerTask) {
        managerTask->cancel();
    }

    while (!activeBackfills.empty()) {
        DCPBackfill* backfill = activeBackfills.front();
        activeBackfills.pop();
        backfill->cancel();
        delete backfill;
    }

    while (!snoozingBackfills.empty()) {
        DCPBackfill* backfill = (snoozingBackfills.front()).second;
        snoozingBackfills.pop_front();
        backfill->cancel();
        delete backfill;
    }
}

void BackfillManager::schedule(stream_t stream, uint64_t start, uint64_t end) {
    LockHolder lh(lock);
    activeBackfills.push(new DCPBackfill(engine, stream, start, end));

    if (managerTask && !managerTask->isdead()) {
        managerTask->snooze(0);
        return;
    }

    managerTask.reset(new BackfillManagerTask(engine, conn,
                                              Priority::BackfillTaskPriority));
    ExecutorPool::get()->schedule(managerTask, NONIO_TASK_IDX);
}

bool BackfillManager::bytesRead(uint32_t bytes) {
    LockHolder lh(lock);
    if (scanBuffer.itemsRead >= scanBuffer.maxItems) {
        return false;
    }

    // Always allow an item to be backfilled if the scan buffer is empty,
    // otherwise check to see if there is room for the item.
    if (scanBuffer.bytesRead + bytes <= scanBuffer.maxBytes ||
        scanBuffer.bytesRead == 0) {
        scanBuffer.bytesRead += bytes;
    }

    if (buffer.bytesRead == 0 || buffer.bytesRead + bytes <= buffer.maxBytes) {
        buffer.bytesRead += bytes;
    } else {
        scanBuffer.bytesRead -= bytes;
        buffer.full = true;
        buffer.nextReadSize = bytes;
        return false;
    }

    scanBuffer.itemsRead++;

    return true;
}

void BackfillManager::bytesSent(uint32_t bytes) {
    LockHolder lh(lock);
    cb_assert(buffer.bytesRead >= bytes);
    buffer.bytesRead -= bytes;

    if (buffer.full) {
        uint32_t bufferSize = buffer.bytesRead;
        bool canFitNext = buffer.maxBytes - bufferSize >= buffer.nextReadSize;
        bool enoughCleared = bufferSize < (buffer.maxBytes * 3 / 4);
        if (canFitNext && enoughCleared) {
            buffer.nextReadSize = 0;
            buffer.full = false;
            if (managerTask) {
                managerTask->snooze(0);
            }
        }
    }
}

backfill_status_t BackfillManager::backfill() {
    LockHolder lh(lock);
    if (buffer.full) {
        return backfill_snooze;
    }

    if (activeBackfills.empty() && snoozingBackfills.empty()) {
        managerTask.reset();
        return backfill_finished;
    }

    if (engine->getEpStore()->isMemoryUsageTooHigh()) {
        LOG(EXTENSION_LOG_WARNING, "DCP backfilling task for connection %s "
            "temporarily suspended because the current memory usage is too "
            "high", conn->getName().c_str());
        return backfill_snooze;
    }

    while (!snoozingBackfills.empty()) {
        std::pair<rel_time_t, DCPBackfill*> snoozer = snoozingBackfills.front();
        // If snoozing task is found to be sleeping for greater than
        // allowed snoozetime, push into active queue
        if (snoozer.first + sleepTime <= ep_current_time()) {
            DCPBackfill* bfill = snoozer.second;
            activeBackfills.push(bfill);
            snoozingBackfills.pop_front();
        } else {
            break;
        }
    }

    if (activeBackfills.empty()) {
        return backfill_snooze;
    }

    DCPBackfill* backfill = activeBackfills.front();

    lh.unlock();
    backfill_status_t status = backfill->run();
    lh.lock();

    if (status == backfill_success && buffer.full) {
        // Snooze while the buffer is full
        return backfill_snooze;
    }

    scanBuffer.bytesRead = 0;
    scanBuffer.itemsRead = 0;

    activeBackfills.pop();
    if (status == backfill_success) {
        activeBackfills.push(backfill);
    } else if (status == backfill_finished) {
        lh.unlock();
        delete backfill;
    } else if (status == backfill_snooze) {
        uint16_t vbid = backfill->getVBucketId();
        RCPtr<VBucket> vb = engine->getVBucket(vbid);
        if (vb) {
            snoozingBackfills.push_back(
                                std::make_pair(ep_current_time(), backfill));
            shared_ptr<Callback<uint64_t> >
                                cb(new BackfillCallback(backfill->getEndSeqno(),
                                                        vbid, conn));
            vb->addPersistenceNotification(cb);
        } else {
            lh.unlock();
            LOG(EXTENSION_LOG_WARNING, "Deleting the backfill, as vbucket %d "
                    "seems to have been deleted!", vbid);
            backfill->cancel();
            delete backfill;
        }
    } else {
        abort();
    }

    return backfill_success;
}

void BackfillManager::wakeUpTask() {
    LockHolder lh(lock);
    if (managerTask) {
        managerTask->snooze(0);
    }
}

void BackfillManager::wakeUpSnoozingBackfills(uint16_t vbid) {
    LockHolder lh(lock);
    std::list<std::pair<rel_time_t, DCPBackfill*> >::iterator it;
    for (it = snoozingBackfills.begin(); it != snoozingBackfills.end(); ++it) {
        DCPBackfill *bfill = (*it).second;
        if (vbid == bfill->getVBucketId()) {
            activeBackfills.push(bfill);
            snoozingBackfills.erase(it);
            managerTask->snooze(0);
            return;
        }
    }
}

bool BackfillManager::addIfLessThanMax(AtomicValue<uint32_t>& val,
                                       uint32_t incr, uint32_t max) {
    do {
        uint32_t oldVal = val.load();
        uint32_t newVal = oldVal + incr;

        if (newVal > max) {
            return false;
        }

        if (val.compare_exchange_strong(oldVal, newVal)) {
            return true;
        }
    } while (true);
}
<|endoftext|>


<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <unistd.h>
#include <fnord/io/file.h>
#include <fnord/io/fileutil.h>
#include <fnord/io/mmappedfile.h>
#include <fnord/logging.h>
#include <fnord/io/fileutil.h>
#include <fnord/util/binarymessagereader.h>
#include <fnord/util/binarymessagewriter.h>
#include <dproc/LocalScheduler.h>

using namespace fnord;

namespace dproc {

LocalScheduler::LocalScheduler(
    const String& tempdir /* = "/tmp" */,
    size_t max_threads /* = 8 */,
    size_t max_requests /* = 32 */) :
    tempdir_(tempdir),
    tpool_(max_threads),
    req_tpool_(max_requests) {}

void LocalScheduler::start() {
  req_tpool_.start();
  tpool_.start();
}

void LocalScheduler::stop() {
  req_tpool_.stop();
  tpool_.stop();
}

RefPtr<TaskResultFuture> LocalScheduler::run(
    RefPtr<Application> app,
    const TaskSpec& task) {
  RefPtr<TaskResultFuture> result(new TaskResultFuture());

  try {
    auto instance = mkRef(
        new LocalTaskRef(
            app,
            task.task_name(),
            Buffer(task.params().data(), task.params().size())));

    req_tpool_.run([this, app, result, instance] () {
      try {
        LocalTaskPipeline pipeline;
        pipeline.tasks.push_back(instance);
        runPipeline(app.get(), &pipeline, result);

        if (instance->failed) {
          RAISE(kRuntimeError, "task failed");
        }

        result->returnResult(instance->task);
      } catch (const StandardException& e) {
        fnord::logError("dproc.scheduler", e, "task failed");
        result->returnError(e);
      }
    });
  } catch (const StandardException& e) {
    fnord::logError("dproc.scheduler", e, "task failed");
    result->returnError(e);
  }

  return result;
}

void LocalScheduler::runPipeline(
    Application* app,
    LocalTaskPipeline* pipeline,
    RefPtr<TaskResultFuture> result) {
  fnord::logDebug(
      "fnord.dproc",
      "Starting local pipeline id=$0 tasks=$1",
      (void*) pipeline,
      pipeline->tasks.size());

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  result->updateStatus([&pipeline] (TaskStatus* status) {
    status->num_subtasks_total = pipeline->tasks.size();
  });

  while (pipeline->tasks.size() > 0) {
    bool waiting = true;
    size_t num_waiting = 0;
    size_t num_running = 0;
    size_t num_completed = 0;

    for (auto& taskref : pipeline->tasks) {

      if (taskref->finished) {
        ++num_completed;
        continue;
      }

      if (taskref->running) {
        ++num_running;
        continue;
      }

      if (!taskref->expanded) {
        taskref->expanded = true;

        auto rdd = dynamic_cast<dproc::RDD*>(taskref->task.get());
        if (rdd != nullptr) {
          auto cache_key = rdd->cacheKeySHA1();
          if (!cache_key.isEmpty()) {
            taskref->cache_filename = FileUtil::joinPaths(
                tempdir_,
                StringUtil::format("$0.rdd", cache_key.get()));
          }

          if (!taskref->cache_filename.empty() &&
              FileUtil::exists(taskref->cache_filename)) {
            fnord::logDebug(
                "fnord.dproc",
                "Read RDD from cache: $0, key=$1",
                taskref->debug_name,
                cache_key.get());

            taskref->readCache();

            result->updateStatus([&pipeline] (TaskStatus* status) {
              ++status->num_subtasks_completed;
            });

            taskref->finished = true;
            waiting = false;
            break;
          }
        }

        auto parent_task = taskref;
        size_t numdeps = 0;
        for (const auto& dep : taskref->task->dependencies()) {
          RefPtr<LocalTaskRef> depref(new LocalTaskRef(app, dep.task_name, dep.params));
          parent_task->dependencies.emplace_back(depref);
          pipeline->tasks.emplace_back(depref);
          ++numdeps;
        }

        if (numdeps > 0) {
          result->updateStatus([numdeps] (TaskStatus* status) {
            status->num_subtasks_total += numdeps;
          });
        }

        waiting = false;
        break;
      }

      bool deps_finished = true;
      for (const auto& dep : taskref->dependencies) {
        if (dep->failed) {
          taskref->failed = true;
          taskref->finished = true;
          waiting = false;
        }

        if (!dep->finished) {
          deps_finished = false;
        }
      }

      if (!taskref->finished) {
        if (!deps_finished) {
          ++num_waiting;
          continue;
        }

        fnord::logDebug(
            "fnord.dproc",
            "Computing RDD: $0",
            taskref->debug_name);

        taskref->running = true;
        tpool_.run(std::bind(
            &LocalScheduler::runTask,
            this,
            pipeline,
            taskref,
            result));

        waiting = false;
      }
    }

    fnord::logDebug(
        "fnord.dproc",
        "Running local pipeline id=$0: $1",
        (void*) pipeline,
        result->status().toString());

    if (waiting) {
      pipeline->wakeup.wait(lk);
    }

    while (pipeline->tasks.size() > 0 && pipeline->tasks.back()->finished) {
      pipeline->tasks.pop_back();
    }
  }

  fnord::logDebug(
      "fnord.dproc",
      "Completed local pipeline id=$0",
      (void*) pipeline);
}

void LocalScheduler::runTask(
    LocalTaskPipeline* pipeline,
    RefPtr<LocalTaskRef> task,
    RefPtr<TaskResultFuture> result) {
  bool from_cache = false;

  auto rdd = dynamic_cast<dproc::RDD*>(task->task.get());
  if (rdd != nullptr &&
      !task->cache_filename.empty() &&
      FileUtil::exists(task->cache_filename)) {
    fnord::logDebug(
        "fnord.dproc",
        "Read RDD from cache: $0, key=$1",
        task->debug_name,
        rdd->cacheKeySHA1().get());

    task->readCache();

    from_cache = true;
  }

  if (!from_cache) {
    try {
      task->task->compute(task.get());

      if (rdd != nullptr && !task->cache_filename.empty()) {
        auto cache_file = task->cache_filename;
        auto cache = rdd->encode();

        auto f = File::openFile(
            cache_file + "~",
            File::O_CREATEOROPEN | File::O_WRITE | File::O_TRUNCATE);

        f.write(cache->data(), cache->size());

        FileUtil::mv(cache_file + "~", cache_file);
      }
    } catch (const std::exception& e) {
      task->failed = true;
      fnord::logError("fnord.dproc", e, "error");
    }
  }

  result->updateStatus([&pipeline] (TaskStatus* status) {
    ++status->num_subtasks_completed;
  });

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  task->finished = true;
  lk.unlock();
  pipeline->wakeup.notify_all();
}

LocalScheduler::LocalTaskRef::LocalTaskRef(
    RefPtr<Application> app,
    const String& task_name,
    const Buffer& params) :
    task(app->getTaskInstance(task_name, params)),
    debug_name(StringUtil::format("$0#$1", app->name(), task_name)),
    running(false),
    expanded(false),
    finished(false),
    failed(false) {}

void LocalScheduler::LocalTaskRef::readCache() {
  auto rdd = dynamic_cast<dproc::RDD*>(task.get());
  if (rdd == nullptr) {
    RAISE(kRuntimeError, "can't cache actions");
  }

  rdd->decode(
      new io::MmappedFile(
          File::openFile(
              cache_filename,
              File::O_READ)));
}

RefPtr<dproc::RDD> LocalScheduler::LocalTaskRef::getDependency(size_t index) {
  if (index >= dependencies.size()) {
    RAISEF(kIndexError, "invalid dependecy index: $0", index);
  }

  const auto& dep = dependencies[index];
  return dynamic_cast<dproc::RDD*>(dep->task.get());
}

size_t LocalScheduler::LocalTaskRef::numDependencies() const {
  return dependencies.size();
}

} // namespace dproc
<commit_msg>dproc log namespace<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <unistd.h>
#include <fnord/io/file.h>
#include <fnord/io/fileutil.h>
#include <fnord/io/mmappedfile.h>
#include <fnord/logging.h>
#include <fnord/io/fileutil.h>
#include <fnord/util/binarymessagereader.h>
#include <fnord/util/binarymessagewriter.h>
#include <dproc/LocalScheduler.h>

using namespace fnord;

namespace dproc {

LocalScheduler::LocalScheduler(
    const String& tempdir /* = "/tmp" */,
    size_t max_threads /* = 8 */,
    size_t max_requests /* = 32 */) :
    tempdir_(tempdir),
    tpool_(max_threads),
    req_tpool_(max_requests) {}

void LocalScheduler::start() {
  req_tpool_.start();
  tpool_.start();
}

void LocalScheduler::stop() {
  req_tpool_.stop();
  tpool_.stop();
}

RefPtr<TaskResultFuture> LocalScheduler::run(
    RefPtr<Application> app,
    const TaskSpec& task) {
  RefPtr<TaskResultFuture> result(new TaskResultFuture());

  try {
    auto instance = mkRef(
        new LocalTaskRef(
            app,
            task.task_name(),
            Buffer(task.params().data(), task.params().size())));

    req_tpool_.run([this, app, result, instance] () {
      try {
        LocalTaskPipeline pipeline;
        pipeline.tasks.push_back(instance);
        runPipeline(app.get(), &pipeline, result);

        if (instance->failed) {
          RAISE(kRuntimeError, "task failed");
        }

        result->returnResult(instance->task);
      } catch (const StandardException& e) {
        fnord::logError("dproc.scheduler", e, "task failed");
        result->returnError(e);
      }
    });
  } catch (const StandardException& e) {
    fnord::logError("dproc.scheduler", e, "task failed");
    result->returnError(e);
  }

  return result;
}

void LocalScheduler::runPipeline(
    Application* app,
    LocalTaskPipeline* pipeline,
    RefPtr<TaskResultFuture> result) {
  fnord::logDebug(
      "dproc",
      "Starting local pipeline id=$0 tasks=$1",
      (void*) pipeline,
      pipeline->tasks.size());

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  result->updateStatus([&pipeline] (TaskStatus* status) {
    status->num_subtasks_total = pipeline->tasks.size();
  });

  while (pipeline->tasks.size() > 0) {
    bool waiting = true;
    size_t num_waiting = 0;
    size_t num_running = 0;
    size_t num_completed = 0;

    for (auto& taskref : pipeline->tasks) {

      if (taskref->finished) {
        ++num_completed;
        continue;
      }

      if (taskref->running) {
        ++num_running;
        continue;
      }

      if (!taskref->expanded) {
        taskref->expanded = true;

        auto rdd = dynamic_cast<dproc::RDD*>(taskref->task.get());
        if (rdd != nullptr) {
          auto cache_key = rdd->cacheKeySHA1();
          if (!cache_key.isEmpty()) {
            taskref->cache_filename = FileUtil::joinPaths(
                tempdir_,
                StringUtil::format("$0.rdd", cache_key.get()));
          }

          if (!taskref->cache_filename.empty() &&
              FileUtil::exists(taskref->cache_filename)) {
            fnord::logDebug(
                "dproc",
                "Read RDD from cache: $0, key=$1",
                taskref->debug_name,
                cache_key.get());

            taskref->readCache();

            result->updateStatus([&pipeline] (TaskStatus* status) {
              ++status->num_subtasks_completed;
            });

            taskref->finished = true;
            waiting = false;
            break;
          }
        }

        auto parent_task = taskref;
        size_t numdeps = 0;
        for (const auto& dep : taskref->task->dependencies()) {
          RefPtr<LocalTaskRef> depref(new LocalTaskRef(app, dep.task_name, dep.params));
          parent_task->dependencies.emplace_back(depref);
          pipeline->tasks.emplace_back(depref);
          ++numdeps;
        }

        if (numdeps > 0) {
          result->updateStatus([numdeps] (TaskStatus* status) {
            status->num_subtasks_total += numdeps;
          });
        }

        waiting = false;
        break;
      }

      bool deps_finished = true;
      for (const auto& dep : taskref->dependencies) {
        if (dep->failed) {
          taskref->failed = true;
          taskref->finished = true;
          waiting = false;
        }

        if (!dep->finished) {
          deps_finished = false;
        }
      }

      if (!taskref->finished) {
        if (!deps_finished) {
          ++num_waiting;
          continue;
        }

        fnord::logDebug(
            "dproc",
            "Computing RDD: $0",
            taskref->debug_name);

        taskref->running = true;
        tpool_.run(std::bind(
            &LocalScheduler::runTask,
            this,
            pipeline,
            taskref,
            result));

        waiting = false;
      }
    }

    fnord::logDebug(
        "dproc",
        "Running local pipeline id=$0: $1",
        (void*) pipeline,
        result->status().toString());

    if (waiting) {
      pipeline->wakeup.wait(lk);
    }

    while (pipeline->tasks.size() > 0 && pipeline->tasks.back()->finished) {
      pipeline->tasks.pop_back();
    }
  }

  fnord::logDebug(
      "dproc",
      "Completed local pipeline id=$0",
      (void*) pipeline);
}

void LocalScheduler::runTask(
    LocalTaskPipeline* pipeline,
    RefPtr<LocalTaskRef> task,
    RefPtr<TaskResultFuture> result) {
  bool from_cache = false;

  auto rdd = dynamic_cast<dproc::RDD*>(task->task.get());
  if (rdd != nullptr &&
      !task->cache_filename.empty() &&
      FileUtil::exists(task->cache_filename)) {
    fnord::logDebug(
        "dproc",
        "Read RDD from cache: $0, key=$1",
        task->debug_name,
        rdd->cacheKeySHA1().get());

    task->readCache();

    from_cache = true;
  }

  if (!from_cache) {
    try {
      task->task->compute(task.get());

      if (rdd != nullptr && !task->cache_filename.empty()) {
        auto cache_file = task->cache_filename;
        auto cache = rdd->encode();

        auto f = File::openFile(
            cache_file + "~",
            File::O_CREATEOROPEN | File::O_WRITE | File::O_TRUNCATE);

        f.write(cache->data(), cache->size());

        FileUtil::mv(cache_file + "~", cache_file);
      }
    } catch (const std::exception& e) {
      task->failed = true;
      fnord::logError("dproc", e, "error");
    }
  }

  result->updateStatus([&pipeline] (TaskStatus* status) {
    ++status->num_subtasks_completed;
  });

  std::unique_lock<std::mutex> lk(pipeline->mutex);
  task->finished = true;
  lk.unlock();
  pipeline->wakeup.notify_all();
}

LocalScheduler::LocalTaskRef::LocalTaskRef(
    RefPtr<Application> app,
    const String& task_name,
    const Buffer& params) :
    task(app->getTaskInstance(task_name, params)),
    debug_name(StringUtil::format("$0#$1", app->name(), task_name)),
    running(false),
    expanded(false),
    finished(false),
    failed(false) {}

void LocalScheduler::LocalTaskRef::readCache() {
  auto rdd = dynamic_cast<dproc::RDD*>(task.get());
  if (rdd == nullptr) {
    RAISE(kRuntimeError, "can't cache actions");
  }

  rdd->decode(
      new io::MmappedFile(
          File::openFile(
              cache_filename,
              File::O_READ)));
}

RefPtr<dproc::RDD> LocalScheduler::LocalTaskRef::getDependency(size_t index) {
  if (index >= dependencies.size()) {
    RAISEF(kIndexError, "invalid dependecy index: $0", index);
  }

  const auto& dep = dependencies[index];
  return dynamic_cast<dproc::RDD*>(dep->task.get());
}

size_t LocalScheduler::LocalTaskRef::numDependencies() const {
  return dependencies.size();
}

} // namespace dproc
<|endoftext|>


<commit_before>#include "QtWebSockets/QWebSocketServer"
#include "QtWebSockets/QWebSocket"
#include <QtCore/QDebug>
#include "WebSocketServer.h"
#include "Player.h"

WebSocketServer::WebSocketServer(quint16 port, QObject *parent) :
        QObject(parent),
  m_pWebSocketServer(Q_NULLPTR),
  m_clients()
{
  m_pWebSocketServer = new QWebSocketServer(QStringLiteral("Chat Server"),
                                            QWebSocketServer::NonSecureMode,
                                            this);
  if (m_pWebSocketServer->listen(QHostAddress::Any, port))
  {
      qDebug() << "WebSocket server listening on port " << port;
      connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
              this, &WebSocketServer::onNewConnection);
      connect(Player::instance(), &Player::statusChanged,
              this, &WebSocketServer::broadcastStatus);
      connect(Player::instance(), &Player::playlistChanged,
              this, &WebSocketServer::broadcastPlaylist);
  }
}

WebSocketServer::~WebSocketServer()
{
    m_pWebSocketServer->close();
    qDeleteAll(m_clients.begin(), m_clients.end());
}

void WebSocketServer::onNewConnection()
{
    QWebSocket *socket = m_pWebSocketServer->nextPendingConnection();

    connect(socket, &QWebSocket::disconnected, this, &WebSocketServer::socketDisconnected);

    JsonApi *api = new JsonApi(socket);
    connect(socket, &QWebSocket::textMessageReceived, api, &JsonApi::processMessage);

    m_clients[socket] = api;
}

void WebSocketServer::broadcastStatus(EMSPlayerStatus newStatus)
{
    foreach( JsonApi *api, m_clients.values() )
    {
        if (api)
        {
            api->sendStatus(newStatus);
        }
    }
}

void WebSocketServer::broadcastPlaylist(EMSPlaylist newPlaylist)
{
    foreach( JsonApi *api, m_clients.values() )
    {
        if (api)
        {
            api->sendPlaylist(newPlaylist);
        }
    }
}

void WebSocketServer::sendAuthRequestToLocalUI(const EMSClient client)
{
    QMapIterator<QWebSocket*, JsonApi*> client_it(m_clients);
    qDebug() << "WebSocketServer: nb clients = " << m_clients.size();

    // Search the websocket for the local UI,
    while (client_it.hasNext()) {
        client_it.next();
        if (client_it.key()->peerAddress() == QHostAddress::LocalHost) {
            // and send the authentication request message
            client_it.value()->sendAuthRequest(client);
            return;
        }
    }
}

void WebSocketServer::processMessage(QString message)
{
   QWebSocket *client = qobject_cast<QWebSocket *>(sender());
   m_clients[client]->processMessage(message);
}

void WebSocketServer::socketDisconnected()
{
    QWebSocket *client = qobject_cast<QWebSocket *>(sender());
    if (client)
    {
        delete m_clients[client];
        m_clients.remove(client);
    }
}
<commit_msg>Accept client: add log for debug<commit_after>#include "QtWebSockets/QWebSocketServer"
#include "QtWebSockets/QWebSocket"
#include <QtCore/QDebug>
#include "WebSocketServer.h"
#include "Player.h"

WebSocketServer::WebSocketServer(quint16 port, QObject *parent) :
        QObject(parent),
  m_pWebSocketServer(Q_NULLPTR),
  m_clients()
{
  m_pWebSocketServer = new QWebSocketServer(QStringLiteral("Chat Server"),
                                            QWebSocketServer::NonSecureMode,
                                            this);
  if (m_pWebSocketServer->listen(QHostAddress::Any, port))
  {
      qDebug() << "WebSocket server listening on port " << port;
      connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
              this, &WebSocketServer::onNewConnection);
      connect(Player::instance(), &Player::statusChanged,
              this, &WebSocketServer::broadcastStatus);
      connect(Player::instance(), &Player::playlistChanged,
              this, &WebSocketServer::broadcastPlaylist);
  }
}

WebSocketServer::~WebSocketServer()
{
    m_pWebSocketServer->close();
    qDeleteAll(m_clients.begin(), m_clients.end());
}

void WebSocketServer::onNewConnection()
{
    QWebSocket *socket = m_pWebSocketServer->nextPendingConnection();

    connect(socket, &QWebSocket::disconnected, this, &WebSocketServer::socketDisconnected);

    JsonApi *api = new JsonApi(socket);
    connect(socket, &QWebSocket::textMessageReceived, api, &JsonApi::processMessage);

    m_clients[socket] = api;
}

void WebSocketServer::broadcastStatus(EMSPlayerStatus newStatus)
{
    foreach( JsonApi *api, m_clients.values() )
    {
        if (api)
        {
            api->sendStatus(newStatus);
        }
    }
}

void WebSocketServer::broadcastPlaylist(EMSPlaylist newPlaylist)
{
    foreach( JsonApi *api, m_clients.values() )
    {
        if (api)
        {
            api->sendPlaylist(newPlaylist);
        }
    }
}

void WebSocketServer::sendAuthRequestToLocalUI(const EMSClient client)
{
    QMapIterator<QWebSocket*, JsonApi*> client_it(m_clients);
    qDebug() << "WebSocketServer: sent the 'authentication' request for " << client.uuid;
    qDebug() << "WebSocketServer: nb connected clients = " << m_clients.size();

    // Search the websocket for the local UI,
    while (client_it.hasNext()) {
        client_it.next();
        if (client_it.key()->peerAddress() == QHostAddress::LocalHost) {
            // and send the authentication request message
            client_it.value()->sendAuthRequest(client);
            return;
        }
    }
}

void WebSocketServer::processMessage(QString message)
{
   QWebSocket *client = qobject_cast<QWebSocket *>(sender());
   m_clients[client]->processMessage(message);
}

void WebSocketServer::socketDisconnected()
{
    QWebSocket *client = qobject_cast<QWebSocket *>(sender());
    if (client)
    {
        delete m_clients[client];
        m_clients.remove(client);
    }
}
<|endoftext|>