<commit_before>//
//
//
#ifndef POPEN_HPP
#define POPEN_HPP

#include <sys/types.h>

#include <cstdio>
#include <csignal>
#include <regex>
#include <string>

#include "asio.hpp"

#include "bash-queue.hpp"

namespace led_d
{

  class popen_t// : public std::enable_shared_from_this<popen_t>
  {
  public:
    // Achtung: it throws
    popen_t (const std::string &command,
             asio::io_context &context, bash_queue_t &queue);
    popen_t () = delete;
    popen_t (const popen_t&) = delete;
    ~popen_t ();

    // 'fileno (FILE*)' call
    // descriptor_t& descriptor () {return m_descriptor;}

    // Try to read smth
    // Note: ignore if 'info' is empty
    // bool read (std::string &info);

    // man -S 2 kill
    bool kill (int signal);

    static bool split (const std::string &src,
                       std::string &prefix, std::string &suffix,
                       const std::string &pattern);

    static bool split (const std::string &src,
                       std::string &prefix, std::string &suffix);

  private:
    using descriptor_t = asio::posix::stream_descriptor;

    static bool split (const std::string &src,
                       std::string &prefix, std::string &suffix,
                       const std::regex &regex);

    void filter (std::string &info);

    void handle_read (const asio::error_code &error, std::size_t len);

    FILE *m_file_ptr;
    descriptor_t m_descriptor;
    bash_queue_t &m_queue;

    pid_t m_pid;

    static constexpr auto asio_buf_size = 128;
    std::array<char, asio_buf_size> m_asio_buf;

    static const std::regex m_regex;
  };

} // led_d

// list of all tracks
// mpc -f "%file%" playlist

#endif
<commit_msg>pi: Debug<commit_after>//
//
//
#ifndef POPEN_HPP
#define POPEN_HPP

#include <sys/types.h>

#include <cstdio>
#include <csignal>
#include <regex>
#include <string>

#include "asio.hpp"

#include "bash-queue.hpp"

namespace led_d
{

  class popen_t// : public std::enable_shared_from_this<popen_t>
  {
  public:
    // Achtung: it throws
    popen_t (const std::string &command,
             asio::io_context &context, bash_queue_t &queue);
    popen_t () = delete;
    popen_t (const popen_t&) = delete;
    ~popen_t ();

    // 'fileno (FILE*)' call
    // descriptor_t& descriptor () {return m_descriptor;}

    // Try to read smth
    // Note: ignore if 'info' is empty
    // bool read (std::string &info);

    // man -S 2 kill
    bool kill (int signal);

    static bool split (const std::string &src,
                       std::string &prefix, std::string &suffix,
                       const std::string &pattern);

    static bool split (const std::string &src,
                       std::string &prefix, std::string &suffix);

    static bool split (const std::string &src,
                       std::string &prefix, std::string &suffix,
                       const std::regex &regex);

  private:
    using descriptor_t = asio::posix::stream_descriptor;

    void filter (std::string &info);

    void handle_read (const asio::error_code &error, std::size_t len);

    FILE *m_file_ptr;
    descriptor_t m_descriptor;
    bash_queue_t &m_queue;

    pid_t m_pid;

    static constexpr auto asio_buf_size = 128;
    std::array<char, asio_buf_size> m_asio_buf;

    static const std::regex m_regex;
  };

} // led_d

// list of all tracks
// mpc -f "%file%" playlist

#endif
<|endoftext|>


<commit_before>#include "pch.h"
#include "AssemblyUILayer.h"
#include "GameManager.h"
#include "StageManager.h"
#include "DataManager.h"
#include "ResourceManager.h"
#include "InputManager.h"
#include "AssemblyLineLayer.h"
#include "EquipmentStatusLayer.h"
#include "AssemblyDisplayLayer.h"
#include "SkillLineLayer.h"
#include "ButtonLayer.h"
#include "IconLayer.h"
#include "SoundManager.h"

AssemblyUILayer::AssemblyUILayer()
{
	m_viewChangeRect.setRect(1235 * RESOLUTION, 310 * RESOLUTION, 25 * RESOLUTION, 100 * RESOLUTION);
}

AssemblyUILayer::~AssemblyUILayer()
{
}

bool AssemblyUILayer::init()
{
	if (!cocos2d::Layer::init())
	{
		return false;
	}
	m_IsStarted = false;

	m_AssemblyLineLayer = AssemblyLineLayer::create();
	m_StatusLayer = EquipmentStatusLayer::create();
	m_DisplayLayer = AssemblyDisplayLayer::create();
	m_SkillLineLayer = SkillLineLayer::create();
	m_ReadyText = cocos2d::Label::createWithSystemFont("", "Calibri", 30 * RESOLUTION);

	m_AssemblyBackground = GET_RESOURCE_MANAGER()->createSprite(ST_ASSEMBLY_BACKGROUND);
	m_AssemblyFrame = GET_RESOURCE_MANAGER()->createSprite(ST_ASSEMBLY_FRAME);
	m_ViewChangeArrow = GET_RESOURCE_MANAGER()->createSprite(ST_ASSEMBLY_ARROW);
	m_EquipmentRect.setRect(140 * RESOLUTION, 40 * RESOLUTION, 390 * RESOLUTION, 580 * RESOLUTION);
	m_SkillRect.setRect(535 * RESOLUTION, 295 * RESOLUTION, 320 * RESOLUTION, 325 * RESOLUTION);

	setUIProperties(m_AssemblyBackground, cocos2d::Point::ZERO, cocos2d::Point::ZERO, RESOLUTION, true, 0);
	setUIProperties(m_AssemblyFrame, cocos2d::Point::ZERO, cocos2d::Point::ZERO, RESOLUTION, true, 0);
	setUIProperties(m_ViewChangeArrow, cocos2d::Point(0.5, 0.5), cocos2d::Point(1055, 360), 1.0f, true, 1);

	m_AssemblyLineLayer->setPosition(cocos2d::Point(0, 0));
	m_StatusLayer->setPosition(cocos2d::Point(545, 0));
	m_DisplayLayer->setPosition(cocos2d::Point(830, 0));
	m_SkillLineLayer->setPosition(cocos2d::Point(1280, 0));
	m_ReadyText->setPosition(cocos2d::Point(1350, 150));
	m_ReadyText->setAnchorPoint(cocos2d::Point(0, 0));

	assemblyLayerButtonInit();

	m_CurrentAssembly = ASSEMBLY_VIEW;
	this->addChild(m_AssemblyBackground);
	m_AssemblyBackground->addChild(m_AssemblyLineLayer);
	m_AssemblyBackground->addChild(m_SkillLineLayer);
	this->addChild(m_AssemblyFrame);
	m_AssemblyFrame->addChild(m_DisplayLayer);
	m_AssemblyFrame->addChild(m_ViewChangeArrow);
	m_AssemblyFrame->addChild(m_StatusLayer);
	m_AssemblyFrame->addChild(m_ReadyText);
	return true;
}

void AssemblyUILayer::update(float dTime)
{
	MouseInfo mouseInput = GET_INPUT_MANAGER()->getMouseInfo();
	if (m_CurrentAssembly == ASSEMBLY_VIEW)
	{
		GET_INPUT_MANAGER()->resetMouseWheel();
		m_StatusLayer->update(dTime);
		m_DisplayLayer->update(dTime);

		if (m_EquipmentRect.containsPoint(mouseInput.m_MouseMove))
		{
			m_AssemblyLineLayer->updateEquipments(dTime);
			m_AssemblyLineLayer->containerScroll(mouseInput.m_ScollValue, mouseInput.m_MouseMove);
			GET_INPUT_MANAGER()->resetMouseWheel();

			if (mouseInput.m_MouseState == MS_LEFT_UP)
			{
				//sound
				GET_SOUND_MANAGER()->createSound(SoundManager::EQUIPCLICK, false);
//
// 				m_AssemblyLineLayer->updateClickItem(mouseInput.m_MouseMove);
// 				m_AssemblyLineLayer->setClickedItem(mouseInput.m_MouseMove);
				m_AssemblyLineLayer->updateClickItem(mouseInput.m_MouseMove);
				m_AssemblyLineLayer->setConfirmSet(mouseInput.m_MouseMove);
				m_StatusLayer->setConfirmSet(m_AssemblyLineLayer->getConfirmSet());
				m_StatusLayer->clickedSomeEquipment();
 				//m_StatusLayer->setCurClickedItem(m_AssemblyLineLayer->getClickedItem());
				m_DisplayLayer->setConfirmSet(m_AssemblyLineLayer->getConfirmSet());
				m_DisplayLayer->assembleRobot();
				m_DisplayLayer->moveScanBar();
 				GET_INPUT_MANAGER()->resetMouseState();
			}
		}
		else
		{
			m_AssemblyLineLayer->hideLabelLayer();
			if (mouseInput.m_ScollValue < 0)
			{
				viewChange(SKILL_VIEW);
			}
			else if (mouseInput.m_ScollValue > 0)
			{
				GET_INPUT_MANAGER()->resetMouseWheel();
			}

			//meaningless double click error exception
			if (mouseInput.m_DoubleClick)
			{
				GET_INPUT_MANAGER()->resetMouseDoubleClick();
			}
		}

		//view change arrow
		if (m_viewChangeRect.containsPoint(mouseInput.m_MouseEnd[LEFT_CLICK_POINT]))
		{
			viewChange(SKILL_VIEW);
		}
	}
	else if (m_CurrentAssembly == SKILL_VIEW)
	{
		GET_INPUT_MANAGER()->resetMouseWheel();
		m_DisplayLayer->update(dTime);
		if (m_SkillRect.containsPoint(mouseInput.m_MouseMove))
		{
			//sound
			GET_SOUND_MANAGER()->createSound(SoundManager::EQUIPCLICK, false);

			m_SkillLineLayer->updateSkills(dTime);
			m_SkillLineLayer->containerScroll(mouseInput.m_ScollValue, mouseInput.m_MouseMove);
			GET_INPUT_MANAGER()->resetMouseWheel();
			if (mouseInput.m_MouseState == MS_LEFT_UP)
			{
				//sound
				GET_SOUND_MANAGER()->createSound(SoundManager::EQUIPDOUBLECLICK, false);
				m_SkillLineLayer->updateClickSkill(mouseInput.m_MouseMove);
				m_SkillLineLayer->setSkillSet(mouseInput.m_MouseMove);
				m_DisplayLayer->moveScanBar();
				GET_INPUT_MANAGER()->resetMouseState();
			}
		}
		else
		{
			m_SkillLineLayer->hideLabelLayer();
			if (mouseInput.m_ScollValue > 0)
			{
				viewChange(ASSEMBLY_VIEW);
			}
			else if (mouseInput.m_ScollValue < 0)
			{
				GET_INPUT_MANAGER()->resetMouseWheel();
			}
			//meaningless double click error exception
			if (mouseInput.m_DoubleClick)
			{
				GET_INPUT_MANAGER()->resetMouseDoubleClick();
			}
		}

		//view change arrow
		if (m_viewChangeRect.containsPoint(mouseInput.m_MouseEnd[LEFT_CLICK_POINT]))
		{
			viewChange(ASSEMBLY_VIEW);
		}
		m_ButtonConfirm->update(dTime);
		m_ButtonCancel->update(dTime);
	}
}

void AssemblyUILayer::viewChange(AssemblyLayerType moveViewTo)
{
	if (m_AssemblyBackground->getNumberOfRunningActions() == 0)
	{
		cocos2d::ActionInterval* moveAction0;
		cocos2d::ActionInterval* moveAction1;
		if (moveViewTo == SKILL_VIEW)
		{
			moveAction0 = cocos2d::MoveTo::create(1.0f, cocos2d::Point(-830 * RESOLUTION, 0));
			moveAction1 = cocos2d::MoveTo::create(1.2f, cocos2d::Point(-830 * RESOLUTION, 0));
			m_viewChangeRect.setRect(20 * RESOLUTION, 310 * RESOLUTION, 25 * RESOLUTION, 100 * RESOLUTION);
			m_ViewChangeArrow->setRotation(180);
			m_ButtonConfirm->setButtonRect(cocos2d::Point(-830 * RESOLUTION, 0));
			m_ButtonCancel->setButtonRect(cocos2d::Point(-830 * RESOLUTION, 0));
			m_AssemblyLineLayer->setVisible(false);
			m_StatusLayer->setVisible(false);
			m_SkillLineLayer->setVisible(true);
			m_EquipmentRect.setRect(0, 0, 0, 0);
			m_SkillRect.setRect(535 * RESOLUTION, 295 * RESOLUTION, 320 * RESOLUTION, 325 * RESOLUTION);
			m_CurrentAssembly = SKILL_VIEW;
			std::stringstream sumString;
			if (checkAssemblyComplete(m_AssemblyLineLayer->getConfirmSet()))
			{
				sumString << "Robot is ready! \nLet's Go!";
			}
			else
			{
				auto confirmSet = m_AssemblyLineLayer->getConfirmSet();
				sumString << "Robot is not ready: \n";
				if (confirmSet.m_Head == HL_START)
				{
					sumString << "HEAD";
				}
				if (confirmSet.m_Engine == EL_START)
				{
					sumString << ", ENGINE";
				}
				if (confirmSet.m_Armor == AL_START)
				{
					sumString << ", ARMOR";
				}
				if (confirmSet.m_Melee == ML_START)
				{
					sumString << ", MELEE";
				}
				if (confirmSet.m_Range == RL_START)
				{
					sumString << ", RANGE";
				}
				if (confirmSet.m_Steam == SCL_START)
				{
					sumString << ", STEAM CONTAINER";
				}
				if (confirmSet.m_Head == LL_START)
				{
					sumString << ", LEG";
				}
			}
			std::string readyText = sumString.str();
			m_ReadyText->setString(readyText);
		}
		else
		{
			moveAction0 = cocos2d::MoveTo::create(1.0f, cocos2d::Point(0, 0));
			moveAction1 = cocos2d::MoveTo::create(1.2f, cocos2d::Point(0, 0));
			m_viewChangeRect.setRect(1235 * RESOLUTION, 310 * RESOLUTION, 25 * RESOLUTION, 100 * RESOLUTION);
			m_ViewChangeArrow->setRotation(0);
			m_ButtonConfirm->setButtonRect(cocos2d::Point(0 * RESOLUTION, 0));
			m_ButtonCancel->setButtonRect(cocos2d::Point(0 * RESOLUTION, 0));
			m_AssemblyLineLayer->setVisible(true);
			m_StatusLayer->setVisible(true);
			m_SkillLineLayer->setVisible(false);
			m_EquipmentRect.setRect(140 * RESOLUTION, 40 * RESOLUTION, 390 * RESOLUTION, 580 * RESOLUTION);
			m_SkillRect.setRect(0, 0, 0, 0);
			m_CurrentAssembly = ASSEMBLY_VIEW;
		}
		cocos2d::Action* action0 = cocos2d::EaseExponentialOut::create(moveAction0);
		cocos2d::Action* action1 = cocos2d::EaseExponentialOut::create(moveAction1);
		m_AssemblyFrame->runAction(action0);
		m_AssemblyBackground->runAction(action1);
	}
	GET_INPUT_MANAGER()->resetMousePoints();
	GET_INPUT_MANAGER()->resetMouseWheel();
}

void AssemblyUILayer::assemblyLayerButtonInit()
{
	m_ButtonConfirm = ButtonLayer::create();
	m_ButtonCancel = ButtonLayer::create();

	m_ButtonConfirm->setButtonProperties(BUTTON_ASSEMBLY_CONFIRM, cocos2d::Point(0 * RESOLUTION, 0), cocos2d::Point(1700, 55), "Confirm", 35);
	m_ButtonCancel->setButtonProperties(BUTTON_ASSEMBLY_CONFIRM, cocos2d::Point(0 * RESOLUTION, 0), cocos2d::Point(1940, 55), "Cancel", 35);

	m_ButtonConfirm->setButtonFunc(std::bind(&AssemblyUILayer::confirmAssembly, this));
	m_ButtonCancel->setButtonFunc(std::bind(&AssemblyUILayer::toTitleScene, this));

	m_AssemblyFrame->addChild(m_ButtonConfirm);
	m_AssemblyFrame->addChild(m_ButtonCancel);
}

void AssemblyUILayer::moveContainer(bool moveLeft, float worldCoordinateX, cocos2d::Node* container, cocos2d::Rect containerRect)
{
	if (moveLeft) //scroll down
	{
		if (worldCoordinateX >= containerRect.getMinX())
		{
			container->setPosition(cocos2d::Point(convertToNodeSpace(cocos2d::Point(containerRect.getMinX(), containerRect.getMinY()))));
		}
		else
		{
			container->setPosition(cocos2d::Point(container->getPosition().x + 15, container->getPosition().y));
		}
		GET_INPUT_MANAGER()->resetMouseWheel();
	}
	else // scroll up
	{
		if (worldCoordinateX + container->getContentSize().width * RESOLUTION <= containerRect.getMaxX())
		{
			container->setPosition(cocos2d::Point(convertToNodeSpace(cocos2d::Point(containerRect.getMaxX() - container->getContentSize().width * RESOLUTION, containerRect.getMinY()))));
		}
		else
		{
			container->setPosition(cocos2d::Point(container->getPosition().x - 15, container->getPosition().y));
		}
		GET_INPUT_MANAGER()->resetMouseWheel();
	}
}

void AssemblyUILayer::confirmAssembly()
{
	if (checkAssemblyComplete(m_AssemblyLineLayer->getConfirmSet()))
	{
		if (!m_IsStarted)
		{
			m_IsStarted = true;
			GET_DATA_MANAGER()->setEquipmentItem(m_AssemblyLineLayer->getConfirmSet());
			GET_DATA_MANAGER()->setSkillSet(m_SkillLineLayer->getSkillSet());
			GET_DATA_MANAGER()->saveGameData();
			GET_DATA_MANAGER()->initWorldData();
			GET_INPUT_MANAGER()->resetMouseInfo();
			GET_GAME_MANAGER()->changeScene(GAME_SCENE);
			GET_STAGE_MANAGER()->start();
		}
	}
	else
	{
		//̿ϼ ޽ !
	}
}

void AssemblyUILayer::toTitleScene()
{
	//߿ Լ ٲٱ
	exit(0);
}

bool AssemblyUILayer::checkAssemblyComplete(ConfirmSet confirmSet)
{
	if (confirmSet.m_Head == HL_START || confirmSet.m_Engine == EL_START ||
		confirmSet.m_Armor == AL_START || confirmSet.m_Melee == ML_START ||
		confirmSet.m_Range == RL_START || confirmSet.m_Steam == SCL_START || confirmSet.m_Leg == LL_START)
	{
		return false;
	}

// 	if (m_DisplayLayer->getPowerOver())
// 	{
// 		return false;
// 	}

	return true;
}

void AssemblyUILayer::onExit()
{
	m_IsStarted = false;
}

<commit_msg>Assembly bug fix<commit_after>#include "pch.h"
#include "AssemblyUILayer.h"
#include "GameManager.h"
#include "StageManager.h"
#include "DataManager.h"
#include "ResourceManager.h"
#include "InputManager.h"
#include "AssemblyLineLayer.h"
#include "EquipmentStatusLayer.h"
#include "AssemblyDisplayLayer.h"
#include "SkillLineLayer.h"
#include "ButtonLayer.h"
#include "IconLayer.h"
#include "SoundManager.h"

AssemblyUILayer::AssemblyUILayer()
{
	m_viewChangeRect.setRect(1235 * RESOLUTION, 310 * RESOLUTION, 25 * RESOLUTION, 100 * RESOLUTION);
}

AssemblyUILayer::~AssemblyUILayer()
{
}

bool AssemblyUILayer::init()
{
	if (!cocos2d::Layer::init())
	{
		return false;
	}
	m_IsStarted = false;

	m_AssemblyLineLayer = AssemblyLineLayer::create();
	m_StatusLayer = EquipmentStatusLayer::create();
	m_DisplayLayer = AssemblyDisplayLayer::create();
	m_SkillLineLayer = SkillLineLayer::create();
	m_ReadyText = cocos2d::Label::createWithSystemFont("", "Calibri", 30 * RESOLUTION);

	m_AssemblyBackground = GET_RESOURCE_MANAGER()->createSprite(ST_ASSEMBLY_BACKGROUND);
	m_AssemblyFrame = GET_RESOURCE_MANAGER()->createSprite(ST_ASSEMBLY_FRAME);
	m_ViewChangeArrow = GET_RESOURCE_MANAGER()->createSprite(ST_ASSEMBLY_ARROW);
	m_EquipmentRect.setRect(140 * RESOLUTION, 40 * RESOLUTION, 390 * RESOLUTION, 580 * RESOLUTION);
	m_SkillRect.setRect(535 * RESOLUTION, 295 * RESOLUTION, 320 * RESOLUTION, 325 * RESOLUTION);

	setUIProperties(m_AssemblyBackground, cocos2d::Point::ZERO, cocos2d::Point::ZERO, RESOLUTION, true, 0);
	setUIProperties(m_AssemblyFrame, cocos2d::Point::ZERO, cocos2d::Point::ZERO, RESOLUTION, true, 0);
	setUIProperties(m_ViewChangeArrow, cocos2d::Point(0.5, 0.5), cocos2d::Point(1055, 360), 1.0f, true, 1);

	m_AssemblyLineLayer->setPosition(cocos2d::Point(0, 0));
	m_StatusLayer->setPosition(cocos2d::Point(545, 0));
	m_DisplayLayer->setPosition(cocos2d::Point(830, 0));
	m_SkillLineLayer->setPosition(cocos2d::Point(1280, 0));
	m_ReadyText->setPosition(cocos2d::Point(1350, 150));
	m_ReadyText->setAnchorPoint(cocos2d::Point(0, 0));

	assemblyLayerButtonInit();

	m_CurrentAssembly = ASSEMBLY_VIEW;
	this->addChild(m_AssemblyBackground);
	m_AssemblyBackground->addChild(m_AssemblyLineLayer);
	m_AssemblyBackground->addChild(m_SkillLineLayer);
	this->addChild(m_AssemblyFrame);
	m_AssemblyFrame->addChild(m_DisplayLayer);
	m_AssemblyFrame->addChild(m_ViewChangeArrow);
	m_AssemblyFrame->addChild(m_StatusLayer);
	m_AssemblyFrame->addChild(m_ReadyText);
	return true;
}

void AssemblyUILayer::update(float dTime)
{
	MouseInfo mouseInput = GET_INPUT_MANAGER()->getMouseInfo();
	if (m_CurrentAssembly == ASSEMBLY_VIEW)
	{
		GET_INPUT_MANAGER()->resetMouseWheel();
		m_StatusLayer->update(dTime);
		m_DisplayLayer->update(dTime);

		if (m_EquipmentRect.containsPoint(mouseInput.m_MouseMove))
		{
			m_AssemblyLineLayer->updateEquipments(dTime);
			m_AssemblyLineLayer->containerScroll(mouseInput.m_ScollValue, mouseInput.m_MouseMove);
			GET_INPUT_MANAGER()->resetMouseWheel();

			if (mouseInput.m_MouseState == MS_LEFT_UP)
			{
				//sound
				GET_SOUND_MANAGER()->createSound(SoundManager::EQUIPCLICK, false);
//
// 				m_AssemblyLineLayer->updateClickItem(mouseInput.m_MouseMove);
// 				m_AssemblyLineLayer->setClickedItem(mouseInput.m_MouseMove);
				m_AssemblyLineLayer->updateClickItem(mouseInput.m_MouseMove);
				m_AssemblyLineLayer->setConfirmSet(mouseInput.m_MouseMove);
				m_StatusLayer->setConfirmSet(m_AssemblyLineLayer->getConfirmSet());
				m_StatusLayer->clickedSomeEquipment();
 				//m_StatusLayer->setCurClickedItem(m_AssemblyLineLayer->getClickedItem());
				m_DisplayLayer->setConfirmSet(m_AssemblyLineLayer->getConfirmSet());
				m_DisplayLayer->assembleRobot();
				m_DisplayLayer->moveScanBar();
 				GET_INPUT_MANAGER()->resetMouseState();
			}
		}
		else
		{
			m_AssemblyLineLayer->hideLabelLayer();
			if (mouseInput.m_ScollValue < 0)
			{
				viewChange(SKILL_VIEW);
			}
			else if (mouseInput.m_ScollValue > 0)
			{
				GET_INPUT_MANAGER()->resetMouseWheel();
			}

			//meaningless double click error exception
			if (mouseInput.m_DoubleClick)
			{
				GET_INPUT_MANAGER()->resetMouseDoubleClick();
			}
		}

		//view change arrow
		if (m_viewChangeRect.containsPoint(mouseInput.m_MouseEnd[LEFT_CLICK_POINT]))
		{
			viewChange(SKILL_VIEW);
		}
	}
	else if (m_CurrentAssembly == SKILL_VIEW)
	{
		GET_INPUT_MANAGER()->resetMouseWheel();
		m_DisplayLayer->update(dTime);
		if (m_SkillRect.containsPoint(mouseInput.m_MouseMove))
		{
			//sound
			GET_SOUND_MANAGER()->createSound(SoundManager::EQUIPCLICK, false);

			m_SkillLineLayer->updateSkills(dTime);
			m_SkillLineLayer->containerScroll(mouseInput.m_ScollValue, mouseInput.m_MouseMove);
			GET_INPUT_MANAGER()->resetMouseWheel();
			if (mouseInput.m_MouseState == MS_LEFT_UP)
			{
				//sound
				GET_SOUND_MANAGER()->createSound(SoundManager::EQUIPDOUBLECLICK, false);
				m_SkillLineLayer->updateClickSkill(mouseInput.m_MouseMove);
				m_SkillLineLayer->setSkillSet(mouseInput.m_MouseMove);
				m_DisplayLayer->moveScanBar();
				GET_INPUT_MANAGER()->resetMouseState();
			}
		}
		else
		{
			m_SkillLineLayer->hideLabelLayer();
			if (mouseInput.m_ScollValue > 0)
			{
				viewChange(ASSEMBLY_VIEW);
			}
			else if (mouseInput.m_ScollValue < 0)
			{
				GET_INPUT_MANAGER()->resetMouseWheel();
			}
			//meaningless double click error exception
			if (mouseInput.m_DoubleClick)
			{
				GET_INPUT_MANAGER()->resetMouseDoubleClick();
			}
		}

		//view change arrow
		if (m_viewChangeRect.containsPoint(mouseInput.m_MouseEnd[LEFT_CLICK_POINT]))
		{
			viewChange(ASSEMBLY_VIEW);
		}
		m_ButtonConfirm->update(dTime);
		m_ButtonCancel->update(dTime);
	}
}

void AssemblyUILayer::viewChange(AssemblyLayerType moveViewTo)
{
	if (m_AssemblyBackground->getNumberOfRunningActions() == 0)
	{
		cocos2d::ActionInterval* moveAction0;
		cocos2d::ActionInterval* moveAction1;
		if (moveViewTo == SKILL_VIEW)
		{
			moveAction0 = cocos2d::MoveTo::create(1.0f, cocos2d::Point(-830 * RESOLUTION, 0));
			moveAction1 = cocos2d::MoveTo::create(1.2f, cocos2d::Point(-830 * RESOLUTION, 0));
			m_viewChangeRect.setRect(20 * RESOLUTION, 310 * RESOLUTION, 25 * RESOLUTION, 100 * RESOLUTION);
			m_ViewChangeArrow->setRotation(180);
			m_ButtonConfirm->setButtonRect(cocos2d::Point(-830 * RESOLUTION, 0));
			m_ButtonCancel->setButtonRect(cocos2d::Point(-830 * RESOLUTION, 0));
			m_AssemblyLineLayer->setVisible(false);
			m_StatusLayer->setVisible(false);
			m_SkillLineLayer->setVisible(true);
			m_EquipmentRect.setRect(0, 0, 0, 0);
			m_SkillRect.setRect(535 * RESOLUTION, 295 * RESOLUTION, 320 * RESOLUTION, 325 * RESOLUTION);
			m_CurrentAssembly = SKILL_VIEW;
			std::stringstream sumString;
			if (checkAssemblyComplete(m_AssemblyLineLayer->getConfirmSet()))
			{
				sumString << "Robot is ready! \nLet's Go!";
			}
			else
			{
				auto confirmSet = m_AssemblyLineLayer->getConfirmSet();
				sumString << "Robot is not ready: \n";
				if (confirmSet.m_Head == HL_START)
				{
					sumString << "HEAD";
				}
				if (confirmSet.m_Engine == EL_START)
				{
					sumString << ", ENGINE";
				}
				if (confirmSet.m_Armor == AL_START)
				{
					sumString << ", ARMOR";
				}
				if (confirmSet.m_Melee == ML_START)
				{
					sumString << ", MELEE";
				}
				if (confirmSet.m_Range == RL_START)
				{
					sumString << ", RANGE";
				}
				if (confirmSet.m_Steam == SCL_START)
				{
					sumString << ", STEAM CONTAINER";
				}
				if (confirmSet.m_Leg == LL_START)
				{
					sumString << ", LEG";
				}
			}
			std::string readyText = sumString.str();
			m_ReadyText->setString(readyText);
		}
		else
		{
			moveAction0 = cocos2d::MoveTo::create(1.0f, cocos2d::Point(0, 0));
			moveAction1 = cocos2d::MoveTo::create(1.2f, cocos2d::Point(0, 0));
			m_viewChangeRect.setRect(1235 * RESOLUTION, 310 * RESOLUTION, 25 * RESOLUTION, 100 * RESOLUTION);
			m_ViewChangeArrow->setRotation(0);
			m_ButtonConfirm->setButtonRect(cocos2d::Point(0 * RESOLUTION, 0));
			m_ButtonCancel->setButtonRect(cocos2d::Point(0 * RESOLUTION, 0));
			m_AssemblyLineLayer->setVisible(true);
			m_StatusLayer->setVisible(true);
			m_SkillLineLayer->setVisible(false);
			m_EquipmentRect.setRect(140 * RESOLUTION, 40 * RESOLUTION, 390 * RESOLUTION, 580 * RESOLUTION);
			m_SkillRect.setRect(0, 0, 0, 0);
			m_CurrentAssembly = ASSEMBLY_VIEW;
		}
		cocos2d::Action* action0 = cocos2d::EaseExponentialOut::create(moveAction0);
		cocos2d::Action* action1 = cocos2d::EaseExponentialOut::create(moveAction1);
		m_AssemblyFrame->runAction(action0);
		m_AssemblyBackground->runAction(action1);
	}
	GET_INPUT_MANAGER()->resetMousePoints();
	GET_INPUT_MANAGER()->resetMouseWheel();
}

void AssemblyUILayer::assemblyLayerButtonInit()
{
	m_ButtonConfirm = ButtonLayer::create();
	m_ButtonCancel = ButtonLayer::create();

	m_ButtonConfirm->setButtonProperties(BUTTON_ASSEMBLY_CONFIRM, cocos2d::Point(0 * RESOLUTION, 0), cocos2d::Point(1700, 55), "Confirm", 35);
	m_ButtonCancel->setButtonProperties(BUTTON_ASSEMBLY_CONFIRM, cocos2d::Point(0 * RESOLUTION, 0), cocos2d::Point(1940, 55), "Cancel", 35);

	m_ButtonConfirm->setButtonFunc(std::bind(&AssemblyUILayer::confirmAssembly, this));
	m_ButtonCancel->setButtonFunc(std::bind(&AssemblyUILayer::toTitleScene, this));

	m_AssemblyFrame->addChild(m_ButtonConfirm);
	m_AssemblyFrame->addChild(m_ButtonCancel);
}

void AssemblyUILayer::moveContainer(bool moveLeft, float worldCoordinateX, cocos2d::Node* container, cocos2d::Rect containerRect)
{
	if (moveLeft) //scroll down
	{
		if (worldCoordinateX >= containerRect.getMinX())
		{
			container->setPosition(cocos2d::Point(convertToNodeSpace(cocos2d::Point(containerRect.getMinX(), containerRect.getMinY()))));
		}
		else
		{
			container->setPosition(cocos2d::Point(container->getPosition().x + 15, container->getPosition().y));
		}
		GET_INPUT_MANAGER()->resetMouseWheel();
	}
	else // scroll up
	{
		if (worldCoordinateX + container->getContentSize().width * RESOLUTION <= containerRect.getMaxX())
		{
			container->setPosition(cocos2d::Point(convertToNodeSpace(cocos2d::Point(containerRect.getMaxX() - container->getContentSize().width * RESOLUTION, containerRect.getMinY()))));
		}
		else
		{
			container->setPosition(cocos2d::Point(container->getPosition().x - 15, container->getPosition().y));
		}
		GET_INPUT_MANAGER()->resetMouseWheel();
	}
}

void AssemblyUILayer::confirmAssembly()
{
	if (checkAssemblyComplete(m_AssemblyLineLayer->getConfirmSet()))
	{
		if (!m_IsStarted)
		{
			m_IsStarted = true;
			GET_DATA_MANAGER()->setEquipmentItem(m_AssemblyLineLayer->getConfirmSet());
			GET_DATA_MANAGER()->setSkillSet(m_SkillLineLayer->getSkillSet());
			GET_DATA_MANAGER()->saveGameData();
			GET_DATA_MANAGER()->initWorldData();
			GET_INPUT_MANAGER()->resetMouseInfo();
			GET_GAME_MANAGER()->changeScene(GAME_SCENE);
			GET_STAGE_MANAGER()->start();
		}
	}
	else
	{
		//̿ϼ ޽ !
	}
}

void AssemblyUILayer::toTitleScene()
{
	//߿ Լ ٲٱ
	exit(0);
}

bool AssemblyUILayer::checkAssemblyComplete(ConfirmSet confirmSet)
{
	if (confirmSet.m_Head == HL_START || confirmSet.m_Engine == EL_START ||
		confirmSet.m_Armor == AL_START || confirmSet.m_Melee == ML_START ||
		confirmSet.m_Range == RL_START || confirmSet.m_Steam == SCL_START || confirmSet.m_Leg == LL_START)
	{
		return false;
	}

// 	if (m_DisplayLayer->getPowerOver())
// 	{
// 		return false;
// 	}

	return true;
}

void AssemblyUILayer::onExit()
{
	m_IsStarted = false;
}

<|endoftext|>


<commit_before>#include "recharge_shields.h"
#include "../SCBW/scbwdata.h"
#include "../SCBW/enumerations.h"
#include "../SCBW/api.h"

//-------- Helper function declarations. Do NOT modify! --------//
namespace {
bool orderToMoveToTarget(CUnit *unit, const CUnit *target);
void orderToHoldPosition(CUnit *unit);
void insertFirstOrder(CUnit *unit, u8 orderId);

//Returns:  0 - Unit has not reached destination
//          1 - Unit cannot move
//          2 - Unit has reached destination
int getUnitMovementState(const CUnit *unit);
} //unnamed namespace

//-------- Actual hook functions --------//

//This function is called every frame when a unit recharges shields.
void rechargeShieldsProc(CUnit *target, CUnit *battery) {
  //Default StarCraft behavior
  using scbw::isCheatEnabled;
  using CheatFlags::TheGathering;

  s32 shieldGain = 1280, energySpent = 640;
  const s32 maxShields = Unit::MaxShieldPoints[target->id] << 8;

   if (maxShields - target->shields < shieldGain) {
    shieldGain = maxShields - target->shields;
    energySpent = shieldGain / 2;
  }
  if (energySpent > battery->energy) {
    energySpent = battery->energy;
    shieldGain = energySpent * 2;
  }

  s32 shields = target->shields + shieldGain;
  if (shields > maxShields)
    shields = maxShields;
  target->shields = shields;

  if (!isCheatEnabled(TheGathering))
    battery->energy -= energySpent;
}

namespace hooks {

/// Decides whether the @p target can recharge shields from the @p battery.
bool unitCanRechargeShieldsHook(const CUnit *target, const CUnit *battery) {
  //Default StarCraft behavior
  using Unit::ShieldsEnabled;
  using Unit::GroupFlags;
  using Unit::MaxShieldPoints;

  //Check target conditions
  if (target->playerId != battery->playerId   //Is not owned by the player
      || !(ShieldsEnabled[target->id])  //Does not have shields
      || !(target->status & (UnitStatus::Completed | UnitStatus::IsBuilding)) //Is incomplete?
      || target->status & UnitStatus::GroundedBuilding)                       //Is a building
    return false;

  //Check target race
  const GroupFlag &ugf = GroupFlags[target->id];
  if (!ugf.isProtoss || (ugf.isTerran || ugf.isZerg)) //Is not a protoss unit
    return false;

  //Check target shield amount
  if (target->shields >= (MaxShieldPoints[target->id] << 8)) //Already has max shields
    return false;

  //Check battery conditions
  if (!(battery->status & UnitStatus::Completed)  //Is being warped in
      || !battery->energy                         //Does not have energy
      || battery->isFrozen())                     //Is frozen
    return false; //Cannot recharge from this battery

  if (target->pAI) { //Separate check for AI-controlled units
    if (target->mainOrderId == OrderId::RechargeShields1 || target->mainOrderId == OrderId::Pickup4)
      return false;
    if (target->orderQueueHead && target->orderQueueHead->orderId == OrderId::RechargeShields1)
      return false;
  }

  return true;
}

/// Determines when to stop the shield recharge process
bool canStopRechargeShieldsHook(const CUnit *target, const CUnit *battery) {
  //Default StarCraft behavior
  return target->shields >= (Unit::MaxShieldPoints[target->id] << 8)  //Shields are fully recharged
         || battery->energy == 0; //Shield Battery is drained
}

//The order process run by a unit when recharging shields
void orderRechargeShieldsHook(CUnit *unit) {
  //Default StarCraft behavior

  CUnit *battery = unit->orderTarget.unit;

  //Skip if the Shield Battery does not exist, has no energy, or is disabled
  if (!battery || battery->energy == 0 || battery->isFrozen()) {
    unit->orderToIdle();
    return;
  }

  switch (unit->mainOrderState) {
    //State 0: Order the unit to move towards the Shield Battery
    case 0:
      if (orderToMoveToTarget(unit, battery))
        unit->mainOrderState = 1;
      break;

    //State 1: Make the unit move until it is close enough and then stop.
    case 1:
      switch (getUnitMovementState(unit)) {
        case 0: //Unit has not reached target yet
          if (unit->getDistanceToTarget(battery) > 128)
            return;
        case 1: //Unit cannot move
          orderToHoldPosition(unit);
          unit->mainOrderState = 2;
          break;

        default:
          unit->orderToIdle();
          return;
      }

    //State 2: Prepare to recharge shields
    case 2:
      battery->setSecondaryOrder(OrderId::ShieldBattery);
      unit->sprite->createOverlay(ImageId::RechargeShields_Small + scbw::getUnitOverlayAdjustment(unit));
      insertFirstOrder(unit, OrderId::Harvest5);  //Stop workers harvesting
      unit->mainOrderState = 3;

    //State 3: Recharge unit shields
    case 3:
      if (!battery->orderTarget.unit)
        battery->orderTarget.unit = unit;

      rechargeShieldsProc(unit, battery);

      //Stop recharge condition: Unit is at full shields or Shield Battery has no energy
      if (unit->shields >= Unit::MaxShieldPoints[unit->id] * 256
          || battery->energy == 0)
      {
        if (battery->orderTarget.unit == unit)
          battery->orderTarget.unit = NULL;
        unit->orderToIdle();
      }
      break;
  }
}

} //hooks

//-------- Helper function definitions. Do NOT modify! --------//

namespace {

const u32 Helper_OrderToMoveToTarget = 0x004EB980;
bool orderToMoveToTarget(CUnit *unit, const CUnit *target) {
  static u32 result;

  __asm {
    PUSHAD
    MOV EAX, target
    MOV ECX, unit
    CALL Helper_OrderToMoveToTarget
    MOV result, EAX
    POPAD
  }

  return result != 0;
}

//Identical to function @ 0x00401DC0;
int getUnitMovementState(const CUnit *unit) {
  if (unit->moveTarget.pt != unit->sprite->position)
    return 0;
  else if (!(unit->status & UnitStatus::Unmovable))
    return 1;
  else
    return 2;
}

const u32 Helper_OrderToHoldPosition = 0x004EB5B0;
void orderToHoldPosition(CUnit *unit) {
  __asm {
    PUSHAD
    MOV ESI, unit
    CALL Helper_OrderToHoldPosition
    POPAD
  }
}

const u32 Helper_InsertFirstOrder = 0x004749D0;
void insertFirstOrder(CUnit *unit, u8 orderId) {
  __asm {
    PUSHAD
    MOV AL, orderId
    MOV ECX, unit
    CALL Helper_InsertFirstOrder
    POPAD
  }
}

} //unnamed namespace<commit_msg>SCT: Merge again (removed unused code)<commit_after>#include "recharge_shields.h"
#include "../SCBW/scbwdata.h"
#include "../SCBW/enumerations.h"
#include "../SCBW/api.h"

//-------- Helper function declarations. Do NOT modify! --------//
namespace {
bool orderToMoveToTarget(CUnit *unit, const CUnit *target);
void orderToHoldPosition(CUnit *unit);
void insertFirstOrder(CUnit *unit, u8 orderId);

//Returns:  0 - Unit has not reached destination
//          1 - Unit cannot move
//          2 - Unit has reached destination
int getUnitMovementState(const CUnit *unit);
} //unnamed namespace

//-------- Actual hook functions --------//

//This function is called every frame when a unit recharges shields.
void rechargeShieldsProc(CUnit *target, CUnit *battery) {
  //Default StarCraft behavior
  using scbw::isCheatEnabled;
  using CheatFlags::TheGathering;

  s32 shieldGain = 1280, energySpent = 640;
  const s32 maxShields = Unit::MaxShieldPoints[target->id] << 8;

   if (maxShields - target->shields < shieldGain) {
    shieldGain = maxShields - target->shields;
    energySpent = shieldGain / 2;
  }
  if (energySpent > battery->energy) {
    energySpent = battery->energy;
    shieldGain = energySpent * 2;
  }

  s32 shields = target->shields + shieldGain;
  if (shields > maxShields)
    shields = maxShields;
  target->shields = shields;

  if (!isCheatEnabled(TheGathering))
    battery->energy -= energySpent;
}

namespace hooks {

/// Decides whether the @p target can recharge shields from the @p battery.
bool unitCanRechargeShieldsHook(const CUnit *target, const CUnit *battery) {
  //Default StarCraft behavior
  using Unit::ShieldsEnabled;
  using Unit::GroupFlags;
  using Unit::MaxShieldPoints;

  //Check target conditions
  if (target->playerId != battery->playerId   //Is not owned by the player
      || !(ShieldsEnabled[target->id])  //Does not have shields
      || !(target->status & (UnitStatus::Completed | UnitStatus::IsBuilding)) //Is incomplete?
      || target->status & UnitStatus::GroundedBuilding)                       //Is a building
    return false;

  //Check target race
  const GroupFlag &ugf = GroupFlags[target->id];
  if (!ugf.isProtoss || (ugf.isTerran || ugf.isZerg)) //Is not a protoss unit
    return false;

  //Check target shield amount
  if (target->shields >= (MaxShieldPoints[target->id] << 8)) //Already has max shields
    return false;

  //Check battery conditions
  if (!(battery->status & UnitStatus::Completed)  //Is being warped in
      || !battery->energy                         //Does not have energy
      || battery->isFrozen())                     //Is frozen
    return false; //Cannot recharge from this battery

  if (target->pAI) { //Separate check for AI-controlled units
    if (target->mainOrderId == OrderId::RechargeShields1 || target->mainOrderId == OrderId::Pickup4)
      return false;
    if (target->orderQueueHead && target->orderQueueHead->orderId == OrderId::RechargeShields1)
      return false;
  }

  return true;
}

//The order process run by a unit when recharging shields
void orderRechargeShieldsHook(CUnit *unit) {
  //Default StarCraft behavior

  CUnit *battery = unit->orderTarget.unit;

  //Skip if the Shield Battery does not exist, has no energy, or is disabled
  if (!battery || battery->energy == 0 || battery->isFrozen()) {
    unit->orderToIdle();
    return;
  }

  switch (unit->mainOrderState) {
    //State 0: Order the unit to move towards the Shield Battery
    case 0:
      if (orderToMoveToTarget(unit, battery))
        unit->mainOrderState = 1;
      break;

    //State 1: Make the unit move until it is close enough and then stop.
    case 1:
      switch (getUnitMovementState(unit)) {
        case 0: //Unit has not reached target yet
          if (unit->getDistanceToTarget(battery) > 128)
            return;
        case 1: //Unit cannot move
          orderToHoldPosition(unit);
          unit->mainOrderState = 2;
          break;

        default:
          unit->orderToIdle();
          return;
      }

    //State 2: Prepare to recharge shields
    case 2:
      battery->setSecondaryOrder(OrderId::ShieldBattery);
      unit->sprite->createOverlay(ImageId::RechargeShields_Small + scbw::getUnitOverlayAdjustment(unit));
      insertFirstOrder(unit, OrderId::Harvest5);  //Stop workers harvesting
      unit->mainOrderState = 3;

    //State 3: Recharge unit shields
    case 3:
      if (!battery->orderTarget.unit)
        battery->orderTarget.unit = unit;

      rechargeShieldsProc(unit, battery);

      //Stop recharge condition: Unit is at full shields or Shield Battery has no energy
      if (unit->shields >= Unit::MaxShieldPoints[unit->id] * 256
          || battery->energy == 0)
      {
        if (battery->orderTarget.unit == unit)
          battery->orderTarget.unit = NULL;
        unit->orderToIdle();
      }
      break;
  }
}

} //hooks

//-------- Helper function definitions. Do NOT modify! --------//

namespace {

const u32 Helper_OrderToMoveToTarget = 0x004EB980;
bool orderToMoveToTarget(CUnit *unit, const CUnit *target) {
  static u32 result;

  __asm {
    PUSHAD
    MOV EAX, target
    MOV ECX, unit
    CALL Helper_OrderToMoveToTarget
    MOV result, EAX
    POPAD
  }

  return result != 0;
}

//Identical to function @ 0x00401DC0;
int getUnitMovementState(const CUnit *unit) {
  if (unit->moveTarget.pt != unit->sprite->position)
    return 0;
  else if (!(unit->status & UnitStatus::Unmovable))
    return 1;
  else
    return 2;
}

const u32 Helper_OrderToHoldPosition = 0x004EB5B0;
void orderToHoldPosition(CUnit *unit) {
  __asm {
    PUSHAD
    MOV ESI, unit
    CALL Helper_OrderToHoldPosition
    POPAD
  }
}

const u32 Helper_InsertFirstOrder = 0x004749D0;
void insertFirstOrder(CUnit *unit, u8 orderId) {
  __asm {
    PUSHAD
    MOV AL, orderId
    MOV ECX, unit
    CALL Helper_InsertFirstOrder
    POPAD
  }
}

} //unnamed namespace<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////
//
//  Analysis package
//
// -------------------------------------------------------
//
//  AUTHOR: Miguel Ramos Pernas
//  e-mail: miguel.ramos.pernas@cern.ch
//
//  Last update: 09/11/2016
//
// -------------------------------------------------------
//
//  Description:
//
//  Here are defined different tools to manage TTree
//  objects.
//
// ------------------------------------------------------
/////////////////////////////////////////////////////////

#include "TreeManagement.h"
#include "Utils.h"

#include "TBranch.h"
#include "TDirectory.h"
#include "TLeaf.h"
#include "TObjArray.h"

#include <iostream>
#include <map>
#include <utility>

//_______________________________________________________________________________
// Appends to the given vector all the names of the branches in a tree
void Analysis::GetBranchNames( std::vector<std::string> &vector,
			       TTree *inputTree,
			       const std::string &expr ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::vector<std::string> brVector( brList -> GetEntries() );
  for ( int ibr = 0; ibr < brList -> GetEntries(); ibr++ )
    brVector[ ibr ] = brList -> At( ibr ) -> GetName();
  if ( expr.size() )
    General::StringVectorFilter( vector, brVector, expr );
  else
    vector.insert( vector.end(), brVector.begin(), brVector.end() );
}

//_______________________________________________________________________________
// Appends to the given vector all the titles of the branches in a tree
void Analysis::GetBranchTitles( std::vector<std::string> &vector,
				TTree *inputTree,
				const std::string &expr ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::vector<std::string> brVector( brList -> GetEntries() );
  for ( int ibr = 0; ibr < brList -> GetEntries(); ibr++ )
    brVector[ ibr ] = brList -> At( ibr ) -> GetTitle();
  if ( expr.size() )
    General::StringVectorFilter( vector, brVector, expr );
  else
    vector.insert( vector.end(), brVector.begin(), brVector.end() );
}

//_______________________________________________________________________________
// Gets the number of variables in a tree whose name contains a given keyword
size_t Analysis::GetNvarsWithExpr( TTree *inputTree, const std::string &expr ) {
  std::vector<std::string> vector;
  Analysis::GetBranchNames( vector, inputTree, expr );
  return vector.size();
}

//_______________________________________________________________________________
// Returns the number of variables of a given type
size_t Analysis::GetNvarsWithType( TTree *inputTree, const char &type ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::string title;
  size_t      counter( 0 );
  for ( int ibr = 0; ibr < brList -> GetEntries(); ibr++ ) {
    title = brList -> At( ibr ) -> GetTitle();
    if ( title.back() == type )
      counter++;
  }
  return counter;
}

//_______________________________________________________________________________
// Returns the number of variables of a certain type in a given vector and tree
size_t Analysis::GetNvarsWithTypeIn( TTree *inputTree,
				     const char &type,
				     const std::vector<std::string> &vector ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::string title;
  size_t      counter( 0 );
  for ( auto it = vector.begin(); it != vector.end(); it++ ) {
    title = brList -> FindObject( it -> c_str() ) -> GetTitle();
    if ( title.back() == type )
      counter++;
  }
  return counter;
}

//_______________________________________________________________________________
// Gets the type of a variable in a tree
char Analysis::GetVarType( TTree *inputTree, const std::string &var ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::string type = brList -> FindObject( var.c_str() ) -> GetTitle();
  type.replace( 0, var.length(), "" );
  return type[ 1 ];
}

//_______________________________________________________________________________
// Makes and saves a new tree with a given set of names changed by anothers. The
// output tree is going to be saved in the current directory, so an output file
// must be opened first.
void Analysis::MakeTreeChangingNames( TTree *inputTree,
				      const std::vector<std::string> &ivars,
				      const std::vector<std::string> &ovars ) {

  // Sends a warning message if the number of input variables is different to
  // the number of output variables
  if ( ivars.size() != ovars.size() ) {
    std::cout << " -- Number of input and output variables doesn't match --" << std::endl;
    exit( 0 );
  }

  std::cout << " Changing variables in tree: < "   << inputTree  -> GetName() << " >" << std::endl;
  std::cout << " Output tree will be saved in: < " << gDirectory -> GetName() << " >" << std::endl;

  // Deactivates the branches of the input variables
  for ( auto it = ivars.begin(); it != ivars.end(); it++ )
    inputTree -> SetBranchStatus( it -> c_str(), false );

  // Clones the input tree
  TTree *outputTree = inputTree -> CloneTree();

  // Writes the output tree to avoid link errors
  outputTree -> Write();

  // Reactivates the branches of the input variables
  for ( auto it = ivars.begin(); it != ivars.end(); it++ )
    inputTree -> SetBranchStatus( it -> c_str(), true );

  // Generates a set of vectors to almacenate the data
  std::vector< std::pair<float , TLeaf*> >
    fvector( Analysis::GetNvarsWithTypeIn( inputTree, 'F', ivars ) );
  std::vector< std::pair<double, TLeaf*> >
    dvector( Analysis::GetNvarsWithTypeIn( inputTree, 'D', ivars ) );
  std::vector< std::pair<int   , TLeaf*> >
    ivector( Analysis::GetNvarsWithTypeIn( inputTree, 'I', ivars ) );
  std::vector< std::pair<bool  , TLeaf*> >
    bvector( Analysis::GetNvarsWithTypeIn( inputTree, 'O', ivars ) );

  std::cout << " Variables to change:" << std::endl;
  std::cout << " - Float:  \t" << fvector.size() << std::endl;
  std::cout << " - Double: \t" << dvector.size() << std::endl;
  std::cout << " - Integer:\t" << ivector.size() << std::endl;
  std::cout << " - Boolean:\t" << bvector.size() << std::endl;

  // Loops over all the variables generating the corresponding branches
  std::vector<TBranch*> brList( ovars.size() );
  std::string           title;
  TLeaf                *leaf;
  size_t                pos;
  for ( size_t i = 0; i != ivars.size(); i++ ) {
    leaf  = inputTree -> GetLeaf( ivars[ i ].c_str() );
    title = inputTree -> GetBranch( ivars[ i ].c_str() ) -> GetTitle();
    if ( ( pos = title.find( "/F" ) ) != std::string::npos ) {
      fvector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &fvector[ i ].first,
					  title.c_str() );
    }
    else if ( ( pos = title.find( "/D" ) ) != std::string::npos ) {
      dvector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &dvector[ i ].first,
					  title.c_str() );
    }
    else if ( ( pos = title.find( "/I" ) ) != std::string::npos ) {
      ivector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &ivector[ i ].first,
					  title.c_str() );
    }
    else if ( ( pos = title.find( "/B" ) ) != std::string::npos ) {
      bvector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &bvector[ i ].first,
					  title.c_str() );
    }
  }

  // Iterates through the input tree to fill the branches
  std::vector< std::pair<float , TLeaf*> >::iterator fit;
  std::vector< std::pair<double, TLeaf*> >::iterator dit;
  std::vector< std::pair<int   , TLeaf*> >::iterator iit;
  std::vector< std::pair<bool  , TLeaf*> >::iterator bit;
  std::vector< TBranch* >::iterator brit;
  for ( Long64_t ievt = 0; ievt < inputTree -> GetEntries(); ievt++ ) {

    inputTree -> GetEntry( ievt );

    for ( fit = fvector.begin(); fit != fvector.end(); fit++ )
      fit -> first = fit -> second -> GetValue();
    for ( dit = dvector.begin(); dit != dvector.end(); dit++ )
      dit -> first = dit -> second -> GetValue();
    for ( iit = ivector.begin(); iit != ivector.end(); iit++ )
      iit -> first = iit -> second -> GetValue();
    for ( bit = bvector.begin(); bit != bvector.end(); bit++ )
      bit -> first = bit -> second -> GetValue();

    for ( brit = brList.begin(); brit != brList.end(); brit++ )
      (*brit) -> Fill();

    if ( ievt % 100000 == 0 )
      outputTree -> AutoSave();
  }

  // Writes the output tree in the current directory
  outputTree -> AutoSave();
  std::cout << " Output tree < " << outputTree -> GetName() << " > saved" << std::endl;
}

//_______________________________________________________________________________
// Creates and saves a clone of the input tree where all the input variables of
// the given type, specified by 'F' ( float ) or 'D' ( double ), are changed to
// the other one
TTree* Analysis::MakeTreeConvertingVars( TTree *inputTree, const char &itype ) {

  TObjArray *brList = inputTree -> GetListOfBranches();

  std::map<std::string, std::pair<float, double> > vars;
  std::string brname, brtitle, vtype, tail;
  size_t nvars = 0;

  // Checks the type of conversion that is going to be made
  if ( itype == 'F' ) {
    std::cout << "Converting variables from float to double in tree < " <<
      inputTree -> GetName() << " >" << std::endl;
    tail = "/F";
    vtype = "float";
  }
  else {
    std::cout << "Converting variables from double to float in tree < " <<
      inputTree -> GetName() << " >" << std::endl;
    tail = "/D";
    vtype = "double";
  }

  // Searches for the variables of the input type
  for ( size_t ibr = 0; ibr < (size_t) brList -> GetEntries(); ibr++ ) {
    brname  = brList -> At( ibr ) -> GetName();
    brtitle = brList -> At( ibr ) -> GetTitle();
    if ( brtitle.find( tail ) != std::string::npos ) {
      inputTree -> SetBranchStatus( brname.c_str(), false );
      vars[ brname ] = std::make_pair( 0, 0 );
      nvars++;
    }
  }
  std::cout << "Found " << nvars << " " << vtype << " variables" << std::endl;

  std::cout << "Cloning input tree" << std::endl;
  TTree *outputTree = inputTree -> CloneTree( 0 );

  if ( !nvars )
    std::cout << "WARNING: Number of " << vtype <<
      " variables is zero. It will be saved a clone of the input tree." << std::endl;

  inputTree -> SetBranchStatus( "*", true );

  // Depending on the input type the address from the TTree is changed
  if ( itype == 'F' )
    for ( auto it = vars.begin(); it != vars.end(); it++ ) {
      brname  = it -> first;
      brtitle = brname + "/D";
      inputTree  ->
	SetBranchAddress( brname.c_str(), &( it -> second ).first );
      outputTree ->
	Branch( brname.c_str(), &( it -> second ).second, brtitle.c_str() );
    }
  else
    for ( auto it = vars.begin(); it != vars.end(); it++ ) {
      brname  = it -> first;
      brtitle = brname + "/F";
      inputTree  ->
	SetBranchAddress( brname.c_str(), &( it -> second ).second );
      outputTree ->
	Branch( brname.c_str(), &( it -> second ).first, brtitle.c_str() );
    }

  std::cout << "Constructing the double variables" << std::endl;
  std::pair<float, double> *pair;

  // Performs the loop over the input tree to fill the output variables depending on the input
  // variable type
  if ( itype == 'F' )
    for ( size_t ievt = 0; ievt < ( size_t ) inputTree -> GetEntries(); ievt++ ) {
      inputTree -> GetEntry( ievt );
      for ( auto it = vars.begin(); it != vars.end(); it++ ) {
	pair = &( it -> second );
	pair -> second = pair -> first;
      }
      outputTree -> Fill();
      if ( ievt % 100000 == 0 )
	outputTree -> AutoSave();
    }
  else
    for ( size_t ievt = 0; ievt < ( size_t ) inputTree -> GetEntries(); ievt++ ) {
      inputTree -> GetEntry( ievt );
      for ( auto it = vars.begin(); it != vars.end(); it++ ) {
	pair = &( it -> second );
	pair -> first = pair -> second;
      }
      outputTree -> Fill();
      if ( ievt % 100000 == 0 )
	outputTree -> AutoSave();
    }

  outputTree -> AutoSave();
  std::cout << "Saved output tree < " << outputTree -> GetName() << " > in directory < "
	    << gDirectory -> GetName() << " >" << std::endl;

  return outputTree;
}
<commit_msg>Changed the position of < ++ > in the < for > loops of TreeManagement.cpp.<commit_after>//////////////////////////////////////////////////////////
//
//  Analysis package
//
// -------------------------------------------------------
//
//  AUTHOR: Miguel Ramos Pernas
//  e-mail: miguel.ramos.pernas@cern.ch
//
//  Last update: 10/11/2016
//
// -------------------------------------------------------
//
//  Description:
//
//  Here are defined different tools to manage TTree
//  objects.
//
// ------------------------------------------------------
/////////////////////////////////////////////////////////

#include "TreeManagement.h"
#include "Utils.h"

#include "TBranch.h"
#include "TDirectory.h"
#include "TLeaf.h"
#include "TObjArray.h"

#include <iostream>
#include <map>
#include <utility>

//_______________________________________________________________________________
// Appends to the given vector all the names of the branches in a tree
void Analysis::GetBranchNames( std::vector<std::string> &vector,
			       TTree *inputTree,
			       const std::string &expr ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::vector<std::string> brVector( brList -> GetEntries() );
  for ( int ibr = 0; ibr < brList -> GetEntries(); ++ibr )
    brVector[ ibr ] = brList -> At( ibr ) -> GetName();
  if ( expr.size() )
    General::StringVectorFilter( vector, brVector, expr );
  else
    vector.insert( vector.end(), brVector.begin(), brVector.end() );
}

//_______________________________________________________________________________
// Appends to the given vector all the titles of the branches in a tree
void Analysis::GetBranchTitles( std::vector<std::string> &vector,
				TTree *inputTree,
				const std::string &expr ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::vector<std::string> brVector( brList -> GetEntries() );
  for ( int ibr = 0; ibr < brList -> GetEntries(); ++ibr )
    brVector[ ibr ] = brList -> At( ibr ) -> GetTitle();
  if ( expr.size() )
    General::StringVectorFilter( vector, brVector, expr );
  else
    vector.insert( vector.end(), brVector.begin(), brVector.end() );
}

//_______________________________________________________________________________
// Gets the number of variables in a tree whose name contains a given keyword
size_t Analysis::GetNvarsWithExpr( TTree *inputTree, const std::string &expr ) {
  std::vector<std::string> vector;
  Analysis::GetBranchNames( vector, inputTree, expr );
  return vector.size();
}

//_______________________________________________________________________________
// Returns the number of variables of a given type
size_t Analysis::GetNvarsWithType( TTree *inputTree, const char &type ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::string title;
  size_t      counter( 0 );
  for ( int ibr = 0; ibr < brList -> GetEntries(); ++ibr ) {
    title = brList -> At( ibr ) -> GetTitle();
    if ( title.back() == type )
      ++counter;
  }
  return counter;
}

//_______________________________________________________________________________
// Returns the number of variables of a certain type in a given vector and tree
size_t Analysis::GetNvarsWithTypeIn( TTree *inputTree,
				     const char &type,
				     const std::vector<std::string> &vector ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::string title;
  size_t      counter( 0 );
  for ( auto it = vector.begin(); it != vector.end(); ++it ) {
    title = brList -> FindObject( it -> c_str() ) -> GetTitle();
    if ( title.back() == type )
      ++counter;
  }
  return counter;
}

//_______________________________________________________________________________
// Gets the type of a variable in a tree
char Analysis::GetVarType( TTree *inputTree, const std::string &var ) {
  TObjArray *brList = inputTree -> GetListOfBranches();
  std::string type = brList -> FindObject( var.c_str() ) -> GetTitle();
  type.replace( 0, var.length(), "" );
  return type[ 1 ];
}

//_______________________________________________________________________________
// Makes and saves a new tree with a given set of names changed by anothers. The
// output tree is going to be saved in the current directory, so an output file
// must be opened first.
void Analysis::MakeTreeChangingNames( TTree *inputTree,
				      const std::vector<std::string> &ivars,
				      const std::vector<std::string> &ovars ) {

  // Sends a warning message if the number of input variables is different to
  // the number of output variables
  if ( ivars.size() != ovars.size() ) {
    std::cout << " -- Number of input and output variables doesn't match --" << std::endl;
    exit( 0 );
  }

  std::cout << " Changing variables in tree: < "   << inputTree  -> GetName() << " >" << std::endl;
  std::cout << " Output tree will be saved in: < " << gDirectory -> GetName() << " >" << std::endl;

  // Deactivates the branches of the input variables
  for ( auto it = ivars.begin(); it != ivars.end(); ++it )
    inputTree -> SetBranchStatus( it -> c_str(), false );

  // Clones the input tree
  TTree *outputTree = inputTree -> CloneTree();

  // Writes the output tree to avoid link errors
  outputTree -> Write();

  // Reactivates the branches of the input variables
  for ( auto it = ivars.begin(); it != ivars.end(); ++it )
    inputTree -> SetBranchStatus( it -> c_str(), true );

  // Generates a set of vectors to almacenate the data
  std::vector< std::pair<float , TLeaf*> >
    fvector( Analysis::GetNvarsWithTypeIn( inputTree, 'F', ivars ) );
  std::vector< std::pair<double, TLeaf*> >
    dvector( Analysis::GetNvarsWithTypeIn( inputTree, 'D', ivars ) );
  std::vector< std::pair<int   , TLeaf*> >
    ivector( Analysis::GetNvarsWithTypeIn( inputTree, 'I', ivars ) );
  std::vector< std::pair<bool  , TLeaf*> >
    bvector( Analysis::GetNvarsWithTypeIn( inputTree, 'O', ivars ) );

  std::cout << " Variables to change:" << std::endl;
  std::cout << " - Float:  \t" << fvector.size() << std::endl;
  std::cout << " - Double: \t" << dvector.size() << std::endl;
  std::cout << " - Integer:\t" << ivector.size() << std::endl;
  std::cout << " - Boolean:\t" << bvector.size() << std::endl;

  // Loops over all the variables generating the corresponding branches
  std::vector<TBranch*> brList( ovars.size() );
  std::string           title;
  TLeaf                *leaf;
  size_t                pos;
  for ( size_t i = 0; i != ivars.size(); ++i ) {
    leaf  = inputTree -> GetLeaf( ivars[ i ].c_str() );
    title = inputTree -> GetBranch( ivars[ i ].c_str() ) -> GetTitle();
    if ( ( pos = title.find( "/F" ) ) != std::string::npos ) {
      fvector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &fvector[ i ].first,
					  title.c_str() );
    }
    else if ( ( pos = title.find( "/D" ) ) != std::string::npos ) {
      dvector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &dvector[ i ].first,
					  title.c_str() );
    }
    else if ( ( pos = title.find( "/I" ) ) != std::string::npos ) {
      ivector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &ivector[ i ].first,
					  title.c_str() );
    }
    else if ( ( pos = title.find( "/B" ) ) != std::string::npos ) {
      bvector[ i ].second = leaf;
      title.replace( 0, pos, ovars[ i ] );
      brList[ i ] = outputTree -> Branch( ovars[ i ].c_str(),
					  &bvector[ i ].first,
					  title.c_str() );
    }
  }

  // Iterates through the input tree to fill the branches
  std::vector< std::pair<float , TLeaf*> >::iterator fit;
  std::vector< std::pair<double, TLeaf*> >::iterator dit;
  std::vector< std::pair<int   , TLeaf*> >::iterator iit;
  std::vector< std::pair<bool  , TLeaf*> >::iterator bit;
  std::vector< TBranch* >::iterator brit;
  for ( Long64_t ievt = 0; ievt < inputTree -> GetEntries(); ++ievt ) {

    inputTree -> GetEntry( ievt );

    for ( fit = fvector.begin(); fit != fvector.end(); ++fit )
      fit -> first = fit -> second -> GetValue();
    for ( dit = dvector.begin(); dit != dvector.end(); ++dit )
      dit -> first = dit -> second -> GetValue();
    for ( iit = ivector.begin(); iit != ivector.end(); ++iit )
      iit -> first = iit -> second -> GetValue();
    for ( bit = bvector.begin(); bit != bvector.end(); ++bit )
      bit -> first = bit -> second -> GetValue();

    for ( brit = brList.begin(); brit != brList.end(); ++brit )
      (*brit) -> Fill();

    if ( ievt % 100000 == 0 )
      outputTree -> AutoSave();
  }

  // Writes the output tree in the current directory
  outputTree -> AutoSave();
  std::cout << " Output tree < " << outputTree -> GetName() << " > saved" << std::endl;
}

//_______________________________________________________________________________
// Creates and saves a clone of the input tree where all the input variables of
// the given type, specified by 'F' ( float ) or 'D' ( double ), are changed to
// the other one
TTree* Analysis::MakeTreeConvertingVars( TTree *inputTree, const char &itype ) {

  TObjArray *brList = inputTree -> GetListOfBranches();

  std::map<std::string, std::pair<float, double> > vars;
  std::string brname, brtitle, vtype, tail;
  size_t nvars = 0;

  // Checks the type of conversion that is going to be made
  if ( itype == 'F' ) {
    std::cout << "Converting variables from float to double in tree < " <<
      inputTree -> GetName() << " >" << std::endl;
    tail = "/F";
    vtype = "float";
  }
  else {
    std::cout << "Converting variables from double to float in tree < " <<
      inputTree -> GetName() << " >" << std::endl;
    tail = "/D";
    vtype = "double";
  }

  // Searches for the variables of the input type
  for ( size_t ibr = 0; ibr < (size_t) brList -> GetEntries(); ++ibr ) {
    brname  = brList -> At( ibr ) -> GetName();
    brtitle = brList -> At( ibr ) -> GetTitle();
    if ( brtitle.find( tail ) != std::string::npos ) {
      inputTree -> SetBranchStatus( brname.c_str(), false );
      vars[ brname ] = std::make_pair( 0, 0 );
      ++nvars;
    }
  }
  std::cout << "Found " << nvars << " " << vtype << " variables" << std::endl;

  std::cout << "Cloning input tree" << std::endl;
  TTree *outputTree = inputTree -> CloneTree( 0 );

  if ( !nvars )
    std::cout << "WARNING: Number of " << vtype <<
      " variables is zero. It will be saved a clone of the input tree." << std::endl;

  inputTree -> SetBranchStatus( "*", true );

  // Depending on the input type the address from the TTree is changed
  if ( itype == 'F' )
    for ( auto it = vars.begin(); it != vars.end(); ++it ) {
      brname  = it -> first;
      brtitle = brname + "/D";
      inputTree  ->
	SetBranchAddress( brname.c_str(), &( it -> second ).first );
      outputTree ->
	Branch( brname.c_str(), &( it -> second ).second, brtitle.c_str() );
    }
  else
    for ( auto it = vars.begin(); it != vars.end(); ++it ) {
      brname  = it -> first;
      brtitle = brname + "/F";
      inputTree  ->
	SetBranchAddress( brname.c_str(), &( it -> second ).second );
      outputTree ->
	Branch( brname.c_str(), &( it -> second ).first, brtitle.c_str() );
    }

  std::cout << "Constructing the double variables" << std::endl;
  std::pair<float, double> *pair;

  // Performs the loop over the input tree to fill the output variables depending on the input
  // variable type
  if ( itype == 'F' )
    for ( size_t ievt = 0; ievt < ( size_t ) inputTree -> GetEntries(); ++ievt ) {
      inputTree -> GetEntry( ievt );
      for ( auto it = vars.begin(); it != vars.end(); ++it ) {
	pair = &( it -> second );
	pair -> second = pair -> first;
      }
      outputTree -> Fill();
      if ( ievt % 100000 == 0 )
	outputTree -> AutoSave();
    }
  else
    for ( size_t ievt = 0; ievt < ( size_t ) inputTree -> GetEntries(); ++ievt ) {
      inputTree -> GetEntry( ievt );
      for ( auto it = vars.begin(); it != vars.end(); ++it ) {
	pair = &( it -> second );
	pair -> first = pair -> second;
      }
      outputTree -> Fill();
      if ( ievt % 100000 == 0 )
	outputTree -> AutoSave();
    }

  outputTree -> AutoSave();
  std::cout << "Saved output tree < " << outputTree -> GetName() << " > in directory < "
	    << gDirectory -> GetName() << " >" << std::endl;

  return outputTree;
}
<|endoftext|>


<commit_before><commit_msg>Simplify the if statement<commit_after><|endoftext|>


<commit_before>/*
 * Medical Image Registration ToolKit (MIRTK)
 *
 * Copyright 2013-2015 Imperial College London
 * Copyright 2013-2015 Andreas Schuh
 *
 * 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 "mirtk/Common.h"
#include "mirtk/Options.h"

#include "mirtk/PointSetIO.h"

#include "vtkSmartPointer.h"
#include "vtkPolyData.h"
#include "vtkCellData.h"
#include "vtkCell.h"
#include "vtkTriangle.h"
#include "vtkFloatArray.h"

using namespace mirtk;

// =============================================================================
// Help
// =============================================================================

// -----------------------------------------------------------------------------
/// Print help screen
void PrintHelp(const char *name)
{
  cout << endl;
  cout << "Usage: " << name << " <original> <deformed> <output> [options]" << endl;
  cout << endl;
  cout << "Description:" << endl;
  cout << "  Computes the distortion of a surface mesh under deformation and stores" << endl;
  cout << "  the results in the output dataset. If no output dataset is given, the" << endl;
  cout << "  mean and standard deviation are reported only." << endl;
  cout << endl;
  cout << "Arguments:" << endl;
  cout << "  original   File name of original dataset." << endl;
  cout << "  deformed   File name of deformed dataset." << endl;
  cout << "  output     File name of output dataset." << endl;
  cout << endl;
  cout << "Options:" << endl;
  cout << "  -areal       Compute areal distortion of cells: log_2(area(deformed)/area(original)). (default)" << endl;
  cout << "  -abs-areal   Compute absolute value of :option:`-areal` distortion." << endl;
  PrintStandardOptions(cout);
  cout << endl;
}

// =============================================================================
// Main
// =============================================================================

// -----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
  // Positional arguments
  REQUIRES_POSARGS(2);

  const char *original_name = POSARG(1);
  const char *deformed_name = POSARG(2);
  const char *output_name   = NULL;

  if (NUM_POSARGS == 3) output_name = POSARG(3);
  else if (NUM_POSARGS > 3) {
    cerr << "Too many positional arguments given (see -help for usage)" << endl;
    exit(1);
  }

  // Optional arguments
  bool areal     = false;
  bool areal_abs = false;

  for (ALL_OPTIONS) {
    if      (OPTION("-areal"))     areal     = true;
    else if (OPTION("-abs-areal")) areal_abs = true;
    else HANDLE_STANDARD_OR_UNKNOWN_OPTION();
  }

  if (!areal && !areal_abs) areal = true;

  // Read input files
  if (verbose > 1) cout << "Reading original surface from " << original_name << endl;
  vtkSmartPointer<vtkPolyData> original = ReadPolyData(original_name);
  if (verbose > 1) cout << "Reading deformed surface from " << deformed_name << endl;
  vtkSmartPointer<vtkPolyData> deformed = ReadPolyData(deformed_name);

  // Check input
  vtkIdType npoints = original->GetNumberOfPoints();
  if (npoints == 0) {
    cerr << "Original surface has no points!" << endl;
    exit(1);
  }
  if (deformed->GetNumberOfPoints() != original->GetNumberOfPoints()) {
    cerr << "Surface meshes have differing number of points!" << endl;
    exit(1);
  }
  vtkIdType ncells = original->GetNumberOfCells();
  if (ncells == 0) {
    cerr << "Original surface has no cells!" << endl;
    exit(1);
  }
  if (deformed->GetNumberOfCells() != original->GetNumberOfCells()) {
    cerr << "Surface meshes have differing number of cells!" << endl;
    exit(1);
  }

  // Compute areal distortion
  if (areal || areal_abs) {
    vtkSmartPointer<vtkFloatArray> areal_distortion;
    vtkSmartPointer<vtkFloatArray> abs_areal_distortion;

    if (areal && output_name) {
      areal_distortion = vtkSmartPointer<vtkFloatArray>::New();
      areal_distortion->SetNumberOfComponents(1);
      areal_distortion->SetNumberOfTuples(ncells);
      areal_distortion->SetName("areal_distortion");
      deformed->GetCellData()->AddArray(areal_distortion);
    }
    if (areal_abs && output_name) {
      abs_areal_distortion = vtkSmartPointer<vtkFloatArray>::New();
      abs_areal_distortion->SetNumberOfComponents(1);
      abs_areal_distortion->SetNumberOfTuples(ncells);
      abs_areal_distortion->SetName("abs_areal_distortion");
      deformed->GetCellData()->AddArray(abs_areal_distortion);
    }

    const double log2 = log(2);
    double distortion;
    double areal_distortion_sum     = .0, areal_distortion_sum2     = .0;
    double abs_areal_distortion_sum = .0, abs_areal_distortion_sum2 = .0;

    for (vtkIdType i = 0; i < ncells; ++i) {
      vtkCell * const original_cell = original->GetCell(i);
      vtkCell * const deformed_cell = deformed->GetCell(i);
      if (deformed_cell->GetCellType() != original_cell->GetCellType()) {
        cerr << "Cell " << (i+1) << " has differing type in the two meshes!" << endl;
        exit(1);
      }
      if (deformed_cell->GetNumberOfPoints() != original_cell->GetNumberOfPoints()) {
        cerr << "Cell " << (i+1) << " has different number of points in the two meshes!" << endl;
        exit(1);
      }
      switch (original_cell->GetCellType()) {
        case VTK_TRIANGLE: {
            vtkTriangle * const original_triangle = dynamic_cast<vtkTriangle *>(original_cell);
            vtkTriangle * const deformed_triangle = dynamic_cast<vtkTriangle *>(deformed_cell);
            distortion = log(deformed_triangle->ComputeArea() / original_triangle->ComputeArea()) / log2;
            if (areal) {
              areal_distortion_sum  += distortion;
              areal_distortion_sum2 += distortion * distortion;
              if (areal_distortion) areal_distortion    ->SetTuple1(i, distortion);
            }
            if (areal_abs) {
              distortion = abs(distortion);
              abs_areal_distortion_sum  += distortion;
              abs_areal_distortion_sum2 += distortion * distortion;
              if (abs_areal_distortion) abs_areal_distortion->SetTuple1(i, distortion);
            }
          } break;
        default:
          cerr << "Unsupported cell type: " << original_cell->GetCellType() << endl;
          exit(1);
      }
    }

    if (!output_name || verbose) {
      if (areal) {
        double mean = areal_distortion_sum / ncells;
        cout << "Areal distortion: mean = " << mean << ", sigma = "
             << sqrt(areal_distortion_sum2 / ncells - mean * mean) << endl;
      }
      if (areal_abs) {
        double mean = abs_areal_distortion_sum / ncells;
        cout << "Absolute areal distortion: mean = " << mean << ", sigma = "
             << sqrt(abs_areal_distortion_sum2 / ncells - mean * mean) << endl;
      }
    }
  }

  // Write output dataset
  if (output_name) WritePolyData(output_name, deformed);

  return 0;
}
<commit_msg>fix: Build of evaluate-distortion command with VTK 6.0 [Applications]<commit_after>/*
 * Medical Image Registration ToolKit (MIRTK)
 *
 * Copyright 2013-2015 Imperial College London
 * Copyright 2013-2015 Andreas Schuh
 *
 * 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 "mirtk/Common.h"
#include "mirtk/Options.h"

#include "mirtk/PointSetIO.h"

// included mirtk/vtkMath.h with fix for VTK 6.0 isinf ambiguity
// needed because vtkTriangle.h otherwise includes vtkMath.h
#include "mirtk/vtkMath.h"

#include "vtkSmartPointer.h"
#include "vtkPolyData.h"
#include "vtkCellData.h"
#include "vtkCell.h"
#include "vtkTriangle.h"
#include "vtkFloatArray.h"

using namespace mirtk;

// =============================================================================
// Help
// =============================================================================

// -----------------------------------------------------------------------------
/// Print help screen
void PrintHelp(const char *name)
{
  cout << endl;
  cout << "Usage: " << name << " <original> <deformed> <output> [options]" << endl;
  cout << endl;
  cout << "Description:" << endl;
  cout << "  Computes the distortion of a surface mesh under deformation and stores" << endl;
  cout << "  the results in the output dataset. If no output dataset is given, the" << endl;
  cout << "  mean and standard deviation are reported only." << endl;
  cout << endl;
  cout << "Arguments:" << endl;
  cout << "  original   File name of original dataset." << endl;
  cout << "  deformed   File name of deformed dataset." << endl;
  cout << "  output     File name of output dataset." << endl;
  cout << endl;
  cout << "Options:" << endl;
  cout << "  -areal       Compute areal distortion of cells: log_2(area(deformed)/area(original)). (default)" << endl;
  cout << "  -abs-areal   Compute absolute value of :option:`-areal` distortion." << endl;
  PrintStandardOptions(cout);
  cout << endl;
}

// =============================================================================
// Main
// =============================================================================

// -----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
  // Positional arguments
  REQUIRES_POSARGS(2);

  const char *original_name = POSARG(1);
  const char *deformed_name = POSARG(2);
  const char *output_name   = NULL;

  if (NUM_POSARGS == 3) output_name = POSARG(3);
  else if (NUM_POSARGS > 3) {
    cerr << "Too many positional arguments given (see -help for usage)" << endl;
    exit(1);
  }

  // Optional arguments
  bool areal     = false;
  bool areal_abs = false;

  for (ALL_OPTIONS) {
    if      (OPTION("-areal"))     areal     = true;
    else if (OPTION("-abs-areal")) areal_abs = true;
    else HANDLE_STANDARD_OR_UNKNOWN_OPTION();
  }

  if (!areal && !areal_abs) areal = true;

  // Read input files
  if (verbose > 1) cout << "Reading original surface from " << original_name << endl;
  vtkSmartPointer<vtkPolyData> original = ReadPolyData(original_name);
  if (verbose > 1) cout << "Reading deformed surface from " << deformed_name << endl;
  vtkSmartPointer<vtkPolyData> deformed = ReadPolyData(deformed_name);

  // Check input
  vtkIdType npoints = original->GetNumberOfPoints();
  if (npoints == 0) {
    cerr << "Original surface has no points!" << endl;
    exit(1);
  }
  if (deformed->GetNumberOfPoints() != original->GetNumberOfPoints()) {
    cerr << "Surface meshes have differing number of points!" << endl;
    exit(1);
  }
  vtkIdType ncells = original->GetNumberOfCells();
  if (ncells == 0) {
    cerr << "Original surface has no cells!" << endl;
    exit(1);
  }
  if (deformed->GetNumberOfCells() != original->GetNumberOfCells()) {
    cerr << "Surface meshes have differing number of cells!" << endl;
    exit(1);
  }

  // Compute areal distortion
  if (areal || areal_abs) {
    vtkSmartPointer<vtkFloatArray> areal_distortion;
    vtkSmartPointer<vtkFloatArray> abs_areal_distortion;

    if (areal && output_name) {
      areal_distortion = vtkSmartPointer<vtkFloatArray>::New();
      areal_distortion->SetNumberOfComponents(1);
      areal_distortion->SetNumberOfTuples(ncells);
      areal_distortion->SetName("areal_distortion");
      deformed->GetCellData()->AddArray(areal_distortion);
    }
    if (areal_abs && output_name) {
      abs_areal_distortion = vtkSmartPointer<vtkFloatArray>::New();
      abs_areal_distortion->SetNumberOfComponents(1);
      abs_areal_distortion->SetNumberOfTuples(ncells);
      abs_areal_distortion->SetName("abs_areal_distortion");
      deformed->GetCellData()->AddArray(abs_areal_distortion);
    }

    const double log2 = log(2);
    double distortion;
    double areal_distortion_sum     = .0, areal_distortion_sum2     = .0;
    double abs_areal_distortion_sum = .0, abs_areal_distortion_sum2 = .0;

    for (vtkIdType i = 0; i < ncells; ++i) {
      vtkCell * const original_cell = original->GetCell(i);
      vtkCell * const deformed_cell = deformed->GetCell(i);
      if (deformed_cell->GetCellType() != original_cell->GetCellType()) {
        cerr << "Cell " << (i+1) << " has differing type in the two meshes!" << endl;
        exit(1);
      }
      if (deformed_cell->GetNumberOfPoints() != original_cell->GetNumberOfPoints()) {
        cerr << "Cell " << (i+1) << " has different number of points in the two meshes!" << endl;
        exit(1);
      }
      switch (original_cell->GetCellType()) {
        case VTK_TRIANGLE: {
            vtkTriangle * const original_triangle = dynamic_cast<vtkTriangle *>(original_cell);
            vtkTriangle * const deformed_triangle = dynamic_cast<vtkTriangle *>(deformed_cell);
            distortion = log(deformed_triangle->ComputeArea() / original_triangle->ComputeArea()) / log2;
            if (areal) {
              areal_distortion_sum  += distortion;
              areal_distortion_sum2 += distortion * distortion;
              if (areal_distortion) areal_distortion    ->SetTuple1(i, distortion);
            }
            if (areal_abs) {
              distortion = abs(distortion);
              abs_areal_distortion_sum  += distortion;
              abs_areal_distortion_sum2 += distortion * distortion;
              if (abs_areal_distortion) abs_areal_distortion->SetTuple1(i, distortion);
            }
          } break;
        default:
          cerr << "Unsupported cell type: " << original_cell->GetCellType() << endl;
          exit(1);
      }
    }

    if (!output_name || verbose) {
      if (areal) {
        double mean = areal_distortion_sum / ncells;
        cout << "Areal distortion: mean = " << mean << ", sigma = "
             << sqrt(areal_distortion_sum2 / ncells - mean * mean) << endl;
      }
      if (areal_abs) {
        double mean = abs_areal_distortion_sum / ncells;
        cout << "Absolute areal distortion: mean = " << mean << ", sigma = "
             << sqrt(abs_areal_distortion_sum2 / ncells - mean * mean) << endl;
      }
    }
  }

  // Write output dataset
  if (output_name) WritePolyData(output_name, deformed);

  return 0;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RL78/G13 グループ SAU/UART 制御 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "G13/system.hpp"
#include "G13/sau.hpp"
#include "G13/intr.hpp"
#include "common/fifo.hpp"

/// F_CLK はボーレートパラメーター計算で必要、設定が無いとエラーにします。
#ifndef F_CLK
#  error "uart_io.hpp requires F_CLK to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  UART 制御クラス・テンプレート
		@param[in]	SAUtx	シリアル・アレイ・ユニット送信・クラス（偶数チャネル）
		@param[in]	SAUrx	シリアル・アレイ・ユニット受信・クラス（奇数チャネル）
		@param[in]	send_size	送信バッファサイズ
		@param[in]	recv_size	受信バッファサイズ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
	class uart_io {

		static SAUtx tx_;	///< 送信リソース
		static SAUrx rx_;	///< 受信リソース

		static utils::fifo<send_size> send_;
		static utils::fifo<recv_size> recv_;

		static volatile bool	send_stall_;

		uint8_t	intr_level_ = 0;
		bool	crlf_ = true;

		// ※必要なら、実装する
		void sleep_() { asm("nop"); }

	public:
		// 送信完了割り込み設定
		static inline void send_intrrupt_mask_(bool f)
		{
			if(tx_.get_unit_no() == 0) {
				if(tx_.get_chanel_no() == 0) {  // UART0
					intr::MK0H.STMK0 = f;
				} else {  // UART1
					intr::MK1L.STMK1 = f;
				}
			} else {
				if(tx_.get_chanel_no() == 0) {  // UART2
					intr::MK0H.STMK2 = f;
				} else {  // UART3
					intr::MK1H.STMK3 = f;
				}
			}
		}

		// 受信割り込みマスク設定
		static inline void recv_interrupt_mask_(bool f)
		{
			if(rx_.get_unit_no() == 0) {
				if(rx_.get_chanel_no() == 1) {  // UART0
					intr::MK0H.SRMK0 = f;
				} else {  // UART1
					intr::MK1L.SRMK1 = f;
				}
			} else {
				if(rx_.get_chanel_no() == 1) {  // UART2
					intr::MK0H.SRMK2 = f;
				} else {  //UART3
					intr::MK1H.SRMK3 = f;
				}
			}
		}

		static __attribute__ ((interrupt)) void send_task()
		{
			if(send_.length()) {
				tx_.SDR_L = send_.get();
			} else {
				send_intrrupt_mask_(true);
				send_stall_ = true;
			}
		}

		static __attribute__ ((interrupt)) void recv_task()
		{
			recv_.put(rx_.SDR_L());
		}

		static __attribute__ ((interrupt)) void error_task()
		{
		}

		void send_restart_() {
			if(send_stall_ && send_.length() > 0) {
				while(tx_.SSR.TSF() != 0) sleep_();
				char ch = send_.get();
				send_stall_ = false;
				tx_.SDR_L = ch;
				send_intrrupt_mask_(false);
			}
		}

		void putch_(char ch)
		{
			if(intr_level_) {
				/// ７／８ を超えてた場合は、バッファが空になるまで待つ。
				if(send_.length() >= (send_.size() * 7 / 8)) {
					send_restart_();
					while(send_.length() != 0) sleep_();
				}
				send_.put(ch);
				send_restart_();
			} else {
				while(tx_.SSR.TSF() != 0) sleep_();
				tx_.SDR_L = ch;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ボーレートを設定して、UART を有効にする
			@param[in]	baud	ボーレート
			@param[in]	level	割り込みレベル（１～２）、０の場合はポーリング
			@return エラーなら「false」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t baud, bool level = 0) {
			intr_level_ = level;

			// ボーレートから分周比の算出
			auto div = static_cast<uint32_t>(F_CLK) / baud;
			uint8_t master = 0;
			while(div > 256) {
				div /= 2;
				++master;
				if(master >= 16) {
					/// ボーレート設定範囲外
					return false;
				}
			}
			--div;
			div &= 0xfe;
			if(div <= 2) {
				/// ボーレート設定範囲外
				return false;
			}

			// 対応するユニットを有効にする
			if(tx_.get_unit_no() == 0) {
				PER0.SAU0EN = 1;
			} else {
				PER0.SAU1EN = 1;
			}

			// チャネル０、１で共有の為、どちらか片方のみの設定
			tx_.SPS = SAUtx::SPS.PRS0.b(master);
			// rx_.SPS = SAUrx::SPS.PRS0.b(master);

			tx_.SMR = 0x20 | SAUtx::SMR.MD.b(1) | SAUtx::SMR.MD0.b(1);
			rx_.SMR = 0x20 | SAUrx::SMR.STS.b(1) | SAUrx::SMR.MD.b(1);

			// 8 date, 1 stop, no-parity LSB-first
			// 送信設定
			tx_.SCR = 0x0004 | SAUtx::SCR.TXE.b(1) | SAUtx::SCR.SLC.b(1) | SAUtx::SCR.DLS.b(3) |
					  SAUtx::SCR.DIR.b(1);
			// 受信設定
			rx_.SCR = 0x0004 | SAUrx::SCR.RXE.b(1) | SAUrx::SCR.SLC.b(1) | SAUrx::SCR.DLS.b(3) |
					  SAUrx::SCR.DIR.b(1);

			// ボーレート・ジェネレーター設定
			tx_.SDR = div << 8;
			rx_.SDR = div << 8;

			tx_.SOL = 0;	// TxD
			tx_.SO  = 1;	// シリアル出力設定
			tx_.SOE = 1;	// シリアル出力許可(Txd)

			// 対応するポートの設定
			if(tx_.get_unit_no() == 0) {
				if(tx_.get_chanel_no() == 0) {  // UART0
					PM1.B1 = 1;	// P1-1 input  (RxD0)
					PM1.B2 = 0;	// P1-2 output (TxD0)
					P1.B2  = 1;	// ポートレジスター TxD 切り替え
				} else {  // UART1
					PM1.B4 = 1;	// P1-1 input  (RxD0)
					PM1.B3 = 0;	// P1-2 output (TxD0)
					P1.B3  = 1;	// ポートレジスター TxD 切り替え
				}
			} else {
				if(tx_.get_chanel_no() == 0) {  // UART2
					PM0.B3  = 1;  // P1-3 input  (RxD2)
					PM0.B2  = 0;  // P1-2 output (TxD2)
					PMC0.B2 = 0;  // ポートモードコントロール
					P0.B2   = 1;  // ポートレジスター TxD 切り替え
				} else {  // UART3（128ピンデバイスでサポート）
					PM14.B3 = 1;  // P14-3 input (RxD3)
					PM14.B4 = 0;  // P14-4 output (TxD3)
					P14.B4  = 1;  // ポートレジスター TxD 切り替え
				}
			}

			send_stall_ = true;

			tx_.SS = 1;	/// TxD enable
			rx_.SS = 1;	/// RxD enable

			// マスクをクリアして、割り込み許可
			if(intr_level_ > 0) {
				recv_interrupt_mask_(0);
			}

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	CRLF 自動送出
			@param[in]	f	「false」なら無効
		 */
		//-----------------------------------------------------------------//
		void auto_crlf(bool f = true) { crlf_ = f; }

		//-----------------------------------------------------------------//
		/*!
			@brief	送信バッファのサイズを返す
			@return　バッファのサイズ
		 */
		//-----------------------------------------------------------------//
		uint16_t send_length() const {
			if(intr_level_) {
				return send_.length();
			} else {
				return tx_.SSR.TSF();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	受信バッファのサイズを返す @n
					※ポーリング時、データが無い：０、データがある：１
			@return　バッファのサイズ
		 */
		//-----------------------------------------------------------------//
		uint16_t recv_length() const {
			if(intr_level_) {
				return recv_.length();
			} else {
				return rx_.SSR.BFF();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	文字出力
			@param[in]	ch	文字コード
		 */
		//-----------------------------------------------------------------//
		void putch(char ch) {
			if(crlf_ && ch == '\n') {
				putch_('\r');
			}
			putch_(ch);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	文字入力
			@return 文字コード
		 */
		//-----------------------------------------------------------------//
		char getch() {
			if(intr_level_) {
				while(recv_.length() == 0) sleep_();
				return recv_.get();
			} else {
				while(rx_.SSR.BFF() == 0) sleep_();
				return rx_.SDR_L();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	文字列出力
			@param[in]	s	出力ストリング
		 */
		//-----------------------------------------------------------------//
		void puts(const char* s) {
			char ch;
			while((ch = *s) != 0) {
				putch(ch);
				++s;
			}
		}
	};

	// send_、recv_, send_stall_ の実体を定義
	template<class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
		utils::fifo<send_size> uart_io<SAUtx, SAUrx, send_size, recv_size>::send_;

	template<class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
		utils::fifo<recv_size> uart_io<SAUtx, SAUrx, send_size, recv_size>::recv_;

	template<class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
		volatile bool uart_io<SAUtx, SAUrx, send_size, recv_size>::send_stall_ = true;
}
<commit_msg>fix baud-rate selector<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RL78/G13 グループ SAU/UART 制御 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "G13/system.hpp"
#include "G13/sau.hpp"
#include "G13/intr.hpp"
#include "common/fifo.hpp"

/// F_CLK はボーレートパラメーター計算で必要、設定が無いとエラーにします。
#ifndef F_CLK
#  error "uart_io.hpp requires F_CLK to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  UART 制御クラス・テンプレート
		@param[in]	SAUtx	シリアル・アレイ・ユニット送信・クラス（偶数チャネル）
		@param[in]	SAUrx	シリアル・アレイ・ユニット受信・クラス（奇数チャネル）
		@param[in]	send_size	送信バッファサイズ
		@param[in]	recv_size	受信バッファサイズ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
	class uart_io {

		static SAUtx tx_;	///< 送信リソース
		static SAUrx rx_;	///< 受信リソース

		static utils::fifo<send_size> send_;
		static utils::fifo<recv_size> recv_;

		static volatile bool	send_stall_;

		uint8_t	intr_level_ = 0;
		bool	crlf_ = true;

		// ※必要なら、実装する
		void sleep_() { asm("nop"); }

		void send_restart_() {
			if(send_stall_ && send_.length() > 0) {
				while(tx_.SSR.TSF() != 0) sleep_();
				char ch = send_.get();
				send_stall_ = false;
				tx_.SDR_L = ch;
				send_intrrupt_mask_(false);
			}
		}

		void putch_(char ch)
		{
			if(intr_level_) {
				/// ７／８ を超えてた場合は、バッファが空になるまで待つ。
				if(send_.length() >= (send_.size() * 7 / 8)) {
					send_restart_();
					while(send_.length() != 0) sleep_();
				}
				send_.put(ch);
				send_restart_();
			} else {
				while(tx_.SSR.TSF() != 0) sleep_();
				tx_.SDR_L = ch;
			}
		}

	public:
		// 送信完了割り込み設定
		static inline void send_intrrupt_mask_(bool f)
		{
			if(tx_.get_unit_no() == 0) {
				if(tx_.get_chanel_no() == 0) {  // UART0
					intr::MK0H.STMK0 = f;
				} else {  // UART1
					intr::MK1L.STMK1 = f;
				}
			} else {
				if(tx_.get_chanel_no() == 0) {  // UART2
					intr::MK0H.STMK2 = f;
				} else {  // UART3
					intr::MK1H.STMK3 = f;
				}
			}
		}

		// 受信割り込みマスク設定
		static inline void recv_interrupt_mask_(bool f)
		{
			if(rx_.get_unit_no() == 0) {
				if(rx_.get_chanel_no() == 1) {  // UART0
					intr::MK0H.SRMK0 = f;
				} else {  // UART1
					intr::MK1L.SRMK1 = f;
				}
			} else {
				if(rx_.get_chanel_no() == 1) {  // UART2
					intr::MK0H.SRMK2 = f;
				} else {  //UART3
					intr::MK1H.SRMK3 = f;
				}
			}
		}

		static __attribute__ ((interrupt)) void send_task()
		{
			if(send_.length()) {
				tx_.SDR_L = send_.get();
			} else {
				send_intrrupt_mask_(true);
				send_stall_ = true;
			}
		}

		static __attribute__ ((interrupt)) void recv_task()
		{
			recv_.put(rx_.SDR_L());
		}

		static __attribute__ ((interrupt)) void error_task()
		{
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ボーレートを設定して、UART を有効にする
			@param[in]	baud	ボーレート
			@param[in]	level	割り込みレベル（１～２）、０の場合はポーリング
			@return エラーなら「false」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t baud, bool level = 0) {
			intr_level_ = level;

			// ボーレートから分周比の算出
			auto div = static_cast<uint32_t>(F_CLK) / baud;
			uint8_t master = 0;
			while(div > 256) {
				div /= 2;
				++master;
				if(master >= 16) {
					/// ボーレート設定範囲外
					return false;
				}
			}
			--div;
			div &= 0xfe;
			if(div <= 2) {
				/// ボーレート設定範囲外
				return false;
			}

			// 対応するユニットを有効にする
			if(tx_.get_unit_no() == 0) {
				PER0.SAU0EN = 1;
			} else {
				PER0.SAU1EN = 1;
			}

			// チャネル０、１で共有の為、どちらか片方のみの設定
			bool cks = false;
			if(tx_.get_chanel_no() == 0) {
				tx_.SPS = SAUtx::SPS.PRS0.b(master);
			} else {
				tx_.SPS = SAUtx::SPS.PRS1.b(master);
				cks = true;
			}

			tx_.SMR = 0x0020 | SAUtx::SMR.CKS.b(cks) | SAUtx::SMR.MD.b(1) | SAUtx::SMR.MD0.b(1);
			rx_.SMR = 0x0020 | SAUtx::SMR.CKS.b(cks) | SAUrx::SMR.STS.b(1) | SAUrx::SMR.MD.b(1);

			// 8 date, 1 stop, no-parity LSB-first
			// 送信設定
			tx_.SCR = 0x0004 | SAUtx::SCR.TXE.b(1) | SAUtx::SCR.SLC.b(1) | SAUtx::SCR.DLS.b(3) |
					  SAUtx::SCR.DIR.b(1);
			// 受信設定
			rx_.SCR = 0x0004 | SAUrx::SCR.RXE.b(1) | SAUrx::SCR.SLC.b(1) | SAUrx::SCR.DLS.b(3) |
					  SAUrx::SCR.DIR.b(1);

			// ボーレート・ジェネレーター設定
			tx_.SDR = div << 8;
			rx_.SDR = div << 8;

			tx_.SOL = 0;	// TxD
			tx_.SO  = 1;	// シリアル出力設定
			tx_.SOE = 1;	// シリアル出力許可(Txd)

			// 対応するポートの設定
			if(tx_.get_unit_no() == 0) {
				if(tx_.get_chanel_no() == 0) {  // UART0
					PM1.B1 = 1;	// P1-1 input  (RxD0)
					PM1.B2 = 0;	// P1-2 output (TxD0)
					P1.B2  = 1;	// ポートレジスター TxD 切り替え
				} else {  // UART1
					PM1.B4 = 1;	// P1-1 input  (RxD0)
					PM1.B3 = 0;	// P1-2 output (TxD0)
					P1.B3  = 1;	// ポートレジスター TxD 切り替え
				}
			} else {
				if(tx_.get_chanel_no() == 0) {  // UART2
					PM0.B3  = 1;  // P1-3 input  (RxD2)
					PM0.B2  = 0;  // P1-2 output (TxD2)
					PMC0.B2 = 0;  // ポートモードコントロール
					P0.B2   = 1;  // ポートレジスター TxD 切り替え
				} else {  // UART3（128ピンデバイスでサポート）
					PM14.B3 = 1;  // P14-3 input (RxD3)
					PM14.B4 = 0;  // P14-4 output (TxD3)
					P14.B4  = 1;  // ポートレジスター TxD 切り替え
				}
			}

			send_stall_ = true;

			tx_.SS = 1;	/// TxD enable
			rx_.SS = 1;	/// RxD enable

			// マスクをクリアして、割り込み許可
			if(intr_level_ > 0) {
				recv_interrupt_mask_(0);
			}

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	CRLF 自動送出
			@param[in]	f	「false」なら無効
		 */
		//-----------------------------------------------------------------//
		void auto_crlf(bool f = true) { crlf_ = f; }

		//-----------------------------------------------------------------//
		/*!
			@brief	送信バッファのサイズを返す
			@return　バッファのサイズ
		 */
		//-----------------------------------------------------------------//
		uint16_t send_length() const {
			if(intr_level_) {
				return send_.length();
			} else {
				return tx_.SSR.TSF();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	受信バッファのサイズを返す @n
					※ポーリング時、データが無い：０、データがある：１
			@return　バッファのサイズ
		 */
		//-----------------------------------------------------------------//
		uint16_t recv_length() const {
			if(intr_level_) {
				return recv_.length();
			} else {
				return rx_.SSR.BFF();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	文字出力
			@param[in]	ch	文字コード
		 */
		//-----------------------------------------------------------------//
		void putch(char ch) {
			if(crlf_ && ch == '\n') {
				putch_('\r');
			}
			putch_(ch);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	文字入力
			@return 文字コード
		 */
		//-----------------------------------------------------------------//
		char getch() {
			if(intr_level_) {
				while(recv_.length() == 0) sleep_();
				return recv_.get();
			} else {
				while(rx_.SSR.BFF() == 0) sleep_();
				return rx_.SDR_L();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	文字列出力
			@param[in]	s	出力ストリング
		 */
		//-----------------------------------------------------------------//
		void puts(const char* s) {
			char ch;
			while((ch = *s) != 0) {
				putch(ch);
				++s;
			}
		}
	};

	// send_、recv_, send_stall_ の実体を定義
	template<class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
		utils::fifo<send_size> uart_io<SAUtx, SAUrx, send_size, recv_size>::send_;

	template<class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
		utils::fifo<recv_size> uart_io<SAUtx, SAUrx, send_size, recv_size>::recv_;

	template<class SAUtx, class SAUrx, uint16_t send_size, uint16_t recv_size>
		volatile bool uart_io<SAUtx, SAUrx, send_size, recv_size>::send_stall_ = true;
}
<|endoftext|>


<commit_before>#include <algorithm>

#include "benchmark.hpp"

static
void myprint(int* a, int n) {
  for (int i = 0; i < n; i++)
    std::cout << " " << a[i];
  std::cout << std::endl;
}

// copies the elements in the range, defined by
// [first, last), to another range beginning at
// d_first.
static
void pcopy(int* first, int* last, int* d_first) {
  const size_t cutoff = 10000;
  size_t nb = last-first;
  if (nb <= cutoff) {
    std::copy(first, last, d_first);
  } else {
    size_t m = nb/2;
    pcopy(first,   first+m, d_first);
    pcopy(first+m, last,    d_first+m);
  }
}

// merges contents of:
//   a[first_a1, ..., last_a1-1]   and
//   a[first_a2, ..., last_a2-1]
// assuming that these two subarrays are sorted
// leaving the result in
//   tmp[tmp_first, ...]
static
void merge_seq(const int* a, int* tmp,
               int first_a1, int last_a1,
               int first_a2, int last_a2,
               int tmp_first) {
  int i = first_a1;
  int j = first_a2;
  int z = tmp_first;

  // merge two halves until one is empty
  while (i < last_a1 and j < last_a2)
    tmp[z++] = (a[i] < a[j]) ? a[i++] : a[j++];

  // copy remaining items
  std::copy(a+i, a+last_a1, tmp+z);
  std::copy(a+j, a+last_a2, tmp+z);
}

// merges contents of:
//   a[first, ..., mid-1]   and
//   a[mid,  ..., last-1]
// assuming that these two subarrays are sorted
// leaving the result in
//   a[first, ...]
// using tmp[first, ...] as scratch space
static
void merge_seq(int* a, int* tmp,
               int first, int mid, int last) {
  merge_seq(a, tmp, first, mid, mid, last, first);

  // copy back to source array
  std::copy(tmp+first, tmp+last, a+first);
}

// returns the position of the first item in
// a[first, ..., last-1] which does not compare
// less than val
static
int lower_bound(const int* a, int first, int last, int val) {
  const int* p = std::lower_bound(a+first, a+last, val);
  return (int)(p-a);
}

// merges contents of:
//   a[first_a1, ..., last_a1-1]   and
//   a[first_a2, ..., last_a2-1]
// assuming that each of these two subarrays are sorted
// leaving the result in
//   tmp[tmp_first, ...]
static
void merge_par(const int* a, int* tmp,
               int first_a1, int last_a1,
               int first_a2, int last_a2,
               int tmp_first) {
  int n1 = last_a1 - first_a1;
  int n2 = last_a2 - first_a2;

  if (n1 < n2) {
    // to ensure that the first subarray being sorted is the larger or the two
    merge_par(a, tmp, first_a2, last_a2, first_a1, last_a1, tmp_first);

  } else if (n1 == 1) {

    if (n2 == 0) {
      // a1 singleton; a2 empty
      tmp[tmp_first] = a[first_a1];
    } else {
      // both singletons
      tmp[tmp_first+0] = std::min(a[first_a1], a[first_a2]);
      tmp[tmp_first+1] = std::max(a[first_a1], a[first_a2]);
    }

  } else {

    // select pivot positions
    int mid_a1 = (first_a1+last_a1)/2;
    int mid_a2 = lower_bound(a, first_a2, last_a2, a[mid_a1]);

    // number of items to be treated by the first parallel call
    int k = (mid_a1-first_a1) + (mid_a2-first_a2);

    merge_par(a, tmp, first_a1, mid_a1,   first_a2, mid_a2,   tmp_first);
    merge_par(a, tmp, mid_a1,   last_a1,  mid_a2,   last_a2,  tmp_first+k);

  }
}

// merges contents of:
//   a[first, ..., mid-1]   and
//   a[mid,  ..., last-1]
// assuming that each of these two subarrays are sorted
// leaving the result in
//   a[first, ...]
// using tmp[first, ...] as scratch space
static
void merge_par(int* a, int* tmp,
               int first, int mid, int last) {
  merge_par(a, tmp, first, mid, mid, last, first);

  // copy back to source array
  pcopy(tmp+first, tmp+last, a+first);
}

// same comment as above
static
void merge(int* a, int* tmp,
           int first, int mid, int last) {
  merge_par(a, tmp, first, mid, last);
}

// sorts contents of:
//    a[first, ..., last-1]
// leaving the result in
//    a[first, ...]
// using tmp[first, ...] as scratch space
static
void sort(int* a, int* tmp,
          int first, int last) {
  // base case, 1: empty sequence.
  if (first + 1 >= last)
    return;

  int mid = (first + last) / 2;

  // base case, 2: 1 or 2 elements in the sequence.
  if (last - first <= 2) {
    if (a[first] > a[mid])
      std::swap(a[first], a[mid]);
    return;
  }

  sort (a, tmp, first, mid);
  sort (a, tmp, mid, last);

  merge(a, tmp, first, mid, last);
}

// sorts the items in the range [first, last) in
// ascending order
static
void sort(int* first, int* last) {
  int n = (int)(last-first);
  int* tmp = (int*)malloc(sizeof(int)*n);
  sort(first, tmp, 0, n);
  free(tmp);
}

template <
  class Container,
  class Copy_fct,
  class Are_equal_fct,
  class Trusted_sort_fct,
  class Untrusted_sort_fct
>
bool check(const Container& input,
           const Copy_fct& copy_fct,
           const Are_equal_fct& are_equal_fct,
           const Trusted_sort_fct& trusted_sort_fct,
           const Untrusted_sort_fct& untrusted_sort_fct) {
  Container trusted_input;
  Container untrusted_input;
  copy_fct(input, trusted_input);
  copy_fct(input, untrusted_input);
  trusted_sort_fct(trusted_input);
  untrusted_sort_fct(untrusted_input);
  return are_equal_fct(trusted_input, untrusted_input);
}

// later: parallelize
static
bool are_equal(int* a, int* b, int n) {
  for (int i = 0; i < n; i++)
    if (a[i] != b[i])
      return false;
  return true;
}

int main(int argc, char** argv) {

  int a[] = { 9, 1, 3, 5, 7, 0,
              2, 4, 6, 8 };
  const int nb = sizeof(a) / sizeof(int);

#if 0
  int first = 1;
  int last = 9;
  int mid = 5;
  int tmp[nb];
  merge_seq(a, tmp, first, mid, last);
//  merge_par(a, tmp, first, mid, last);
  std::cout << "size of a: " << nb << std::endl;
  std::cout << "contents of a:";
  myprint(a+first, last-first);

#else

  sort(a, a+nb);
  myprint(a, nb);

#endif

  auto init = [&] {

  };
  auto run = [&] (bool sequential) {

  };
  auto output = [&] {

  };
  auto destroy = [&] {
    ;
  };

  pasl::sched::launch(argc, argv, init, run, output, destroy);

  return 0;
}<commit_msg>Delete mergesort.cpp<commit_after><|endoftext|>