<commit_before>#include "tfd_modules/tfdm_eval_interface.h"
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <sys/stat.h>
#include <ros/ros.h>
#include "planParser.h"
#include "domainParser.h"
#include <pluginlib/class_list_macros.h>

PLUGINLIB_DECLARE_CLASS(tfd_modules, tfdm_eval_interface,
        tfd_modules::TFDMEvalInterface, continual_planning_executive::PlannerInterface)

using namespace std;

namespace tfd_modules
{
    bool setupRunLazyEvalPartialCaching()
    {
        // set params for module, etc.
        ros::NodeHandle nh("/tfd_modules");
        nh.setParam("lazy_state_module_evaluation", 1);

        // record all other settings

        return true;
    }

    bool setupRunEagerEvalPartialCaching()
    {
        // set params for module, etc.
        ros::NodeHandle nh("/tfd_modules");
        nh.setParam("lazy_state_module_evaluation", 0);

        // record all settings

        return true;
    }

    TFDMEvalInterface::TFDMEvalInterface()
    {
        runs.insert(make_pair("lazy_eval_partial_caching", setupRunLazyEvalPartialCaching));
        runs.insert(make_pair("eager_eval_partial_caching", setupRunEagerEvalPartialCaching));
        defaultRun = "lazy_eval_partial_caching";
    }

    TFDMEvalInterface::~TFDMEvalInterface()
    {
    }

    void TFDMEvalInterface::initialize(const std::string & domainFile, const std::vector<std::string> & options)
    {
        TFDMInterface::initialize(domainFile, options);

        ROS_INFO("I am in %s", get_current_dir_name());//leak

        ros::NodeHandle nhConfig("/tfd_modules/eval");
        if(!nhConfig.getParam("eval_dir", evalOutputDir)) {
            ROS_FATAL("TFDMEvalInterface: /tfd_modules/eval/evalDir was not set!");
            evalOutputDir = "/tmp";
        }

        // add date
        time_t rawtime;
        struct tm* timeinfo;
        char buffer[1024];

        time(&rawtime);
        timeinfo = localtime(&rawtime);

        strftime(buffer, 1024, "/%Y-%m-%d_%H-%M-%S", timeinfo);

        evalOutputDir += buffer;
        ROS_INFO("evalOutputDir is %s", evalOutputDir.c_str());

        int ret = mkdir(evalOutputDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        if(ret != 0) {
            ROS_FATAL("Failed to create evalOutputDir: %s (%d)", evalOutputDir.c_str(), ret);
        }

        safeCopy(this->_domainFile, evalOutputDir + "/domain.pddl");

        callNumber = 0;
    }

    continual_planning_executive::PlannerInterface::PlannerResult TFDMEvalInterface::plan(
            const SymbolicState & init, const SymbolicState & goal, Plan & plan)
    {
        if(!writeProblem(init, goal))
            return PR_FAILURE_OTHER;

        if(!setupRuns()) {
            ROS_FATAL("Failed to setup runs.");
        }

        if(!recordProblemData(init)) {
            ROS_ERROR("Failed to record problem data");
        }

        PlannerResult defaultResult = PR_FAILURE_OTHER;

        for(map<string, setupRunFunction>::iterator it = runs.begin(); it != runs.end(); it++) {
            if(!setupRun(it->first)) {
                ROS_ERROR("Failed to setup run for %s", it->first.c_str());
                continue;
            }

            // call the run specific setup function
            if(! (it->second()) ) {
                ROS_ERROR("Failed run specific setup for %s", it->first.c_str());
                continue;
            }

            if(system("rosparam dump planner_params.yaml /tfd_modules") != 0) {
                ROS_ERROR("Failed to dump planner_params");
            }

            // perfrom the planner call
            std::string planNamePrefix = "plan";
            ROS_INFO("Performing planner call for: %s", it->first.c_str());
            PlannerResult result = callPlanner(this->_domainFile, _problemFileName, planNamePrefix);

            if(it->first == defaultRun) {   // actually use this one for plan + result
                std::string planName = planNamePrefix + ".best";

                defaultResult = result;

                // parse plan
                if(result == PR_SUCCESS_TIMEOUT || result == PR_SUCCESS) {
                    std::ifstream planFile(planName.c_str());
                    bool ok = PlanParser::parsePlan(planFile, plan);
                    planFile.close();
                    if(!ok) {
                        ROS_WARN_STREAM("No plan generated or failure in parsing!" << std::endl);
                        defaultResult = PR_FAILURE_OTHER;
                    }
                }
            }
        }

        return defaultResult;
    }

    continual_planning_executive::PlannerInterface::PlannerResult TFDMEvalInterface::callPlanner(const std::string & domain, const std::string & problem,
            const std::string & planNamePrefix)
    {
        const bool failOnPlannerError = false;  // default: switch off

        string curPlan = planNamePrefix + ".best";
        remove(curPlan.c_str());

        // set plan name
        ros::param::set("tfd_modules/plan_name", planNamePrefix);
        // Determine the planner call command
        std::stringstream plannerCmdStr;
        plannerCmdStr << "rosrun tfd_modules tfd_plan_log " << domain << " " << problem << " tfdsearch.out";
        plannerCmdStr << " __name:=tfd_modules";

        // Later: other features for optional debugging???
        std::string plannerCmd = plannerCmdStr.str();

        ROS_INFO_STREAM("calling planner: " << plannerCmd << std::endl);

        // ACTUAL PLANNER CALL
        int ret = system(plannerCmd.c_str());
        if(ret % 256 == 0)   // for child processed -> returning exitstatus * 256
            ret /= 256;
        else
            ret %= 256;
        ROS_INFO_STREAM("Planner returned: " << ret);

        bool plannerError = false;
        bool plannerTimeout = false;
        if(ret != 0) {
            ROS_WARN_STREAM("Something in the symbolic planner failed! (Signal " << ret << ")\n");
            plannerError = true;
            if(ret == 137) {
                plannerTimeout = true;
                ROS_WARN_STREAM("Planner timeout!" << std::endl);
            } else {
                ROS_WARN_STREAM("Planner failure: " << ret << std::endl);
                if(failOnPlannerError) {
                    ROS_FATAL("Aborting run\n");
                    exit(1);
                }
            }
        }

        // check if plan.best exists for return value
        struct stat st;
        bool planWritten = false;
        if(stat(curPlan.c_str(), &st) == 0) {
            planWritten = true;
        }

        if(planWritten) {
            if(plannerTimeout)
                return PR_SUCCESS_TIMEOUT;
            // FIXME: on error still return success as there is a new plan
            return PR_SUCCESS;
        }

        if(plannerError) {
            if(plannerTimeout)
                return PR_FAILURE_TIMEOUT;
            return PR_FAILURE_OTHER;
        }

        // FIXME: when completely explored and no plan, the planner returns fine (no error)
        // so this really IS an error
        return PR_FAILURE_UNREACHABLE;

    }

    continual_planning_executive::PlannerInterface::PlannerResult TFDMEvalInterface::monitor(
            const SymbolicState & init, const SymbolicState & goal, const Plan & plan)
    {
        return TFDMInterface::monitor(init, goal, plan);
    }

    bool TFDMEvalInterface::setupRuns()
    {
        bool ok = true;

        callNumber++;
        char buf[1024];
        sprintf(buf, "/call%03d", callNumber);

        callDir = evalOutputDir + buf;

        // create change call dir.
        // set and record all params, things that are the same for all runs (problem, etc.)
        int ret = mkdir(callDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        if(ret != 0) {
            ROS_FATAL("Failed to create callDir: %s (%d)", callDir.c_str(), ret);
            ok = false;
            return ok;
        }

        ret = chdir(callDir.c_str());
        if(ret != 0) {
            ROS_FATAL("Failed to change to callDir: %s (%d)", callDir.c_str(), ret);
            ok = false;
            return ok;
        }

        return ok;
    }

    bool TFDMEvalInterface::setupRun(const string & runName)
    {
        bool ok = true;

        // create/change to run dir, etc.
        int ret = chdir(callDir.c_str());
        if(ret != 0) {
            ROS_FATAL("Failed to change to callDir: %s (%d)", callDir.c_str(), ret);
            ok = false;
            return ok;
        }

        ret = mkdir(runName.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        if(ret != 0) {
            ROS_FATAL("Failed to create run dir: %s (%d)", runName.c_str(), ret);
            ok = false;
            return ok;
        }

        ret = chdir(runName.c_str());
        if(ret != 0) {
            ROS_FATAL("Failed to change to run dir: %s (%d)", runName.c_str(), ret);
            ok = false;
            return ok;
        }

        // Clean all intermediate data (plan.1/.best/.times), params???, other output files from modules
        // FIXME: done by changing to new dir.

        return ok;
    }

    bool TFDMEvalInterface::recordProblemData(const SymbolicState & init)
    {
        bool ok = true;

        ok &= safeCopy(_problemFileName, "problem.pddl");

        // record how many objects there are per type
        map<string, int> numObjectsMap;
        // type -> object
        for(SymbolicState::TypedObjectConstIterator it = init.getTypedObjects().begin();
                it != init.getTypedObjects().end(); it++) {
            if(numObjectsMap.find(it->first) == numObjectsMap.end()) {
                numObjectsMap[it->first] = 1;
            } else {
                numObjectsMap[it->first]++;
            }
        }

        ofstream probData("problem.data");
        ok &= probData.good();
        for(map<string, int>::iterator it = numObjectsMap.begin(); it != numObjectsMap.end(); it++) {
            probData << it->first << " " << it->second << endl;
        }
        probData.close();

        return ok;
    }

    bool TFDMEvalInterface::safeCopy(const string & from, const string & to)
    {
        string cmd = "cp " + from + " " + to;
        int ret = system(cmd.c_str());
        if(ret != 0) {
            ROS_ERROR("%s: Error %d when calling \"%s\".", __func__, ret, cmd.c_str());
            return false;
        }
        return true;
    }

};

<commit_msg>iface sets run_name and current_eval_dir params<commit_after>#include "tfd_modules/tfdm_eval_interface.h"
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <sys/stat.h>
#include <ros/ros.h>
#include "planParser.h"
#include "domainParser.h"
#include <pluginlib/class_list_macros.h>

PLUGINLIB_DECLARE_CLASS(tfd_modules, tfdm_eval_interface,
        tfd_modules::TFDMEvalInterface, continual_planning_executive::PlannerInterface)

using namespace std;

namespace tfd_modules
{
    bool setupRunLazyEvalPartialCaching()
    {
        // set params for module, etc.
        ros::NodeHandle nh("/tfd_modules");
        nh.setParam("run_name", "lazy_eval_partial_caching");
        nh.setParam("lazy_state_module_evaluation", 1);

        // record all other settings

        return true;
    }

    bool setupRunEagerEvalPartialCaching()
    {
        // set params for module, etc.
        ros::NodeHandle nh("/tfd_modules");
        nh.setParam("run_name", "eager_eval_partial_caching");
        nh.setParam("lazy_state_module_evaluation", 0);

        // record all settings

        return true;
    }

    TFDMEvalInterface::TFDMEvalInterface()
    {
        runs.insert(make_pair("lazy_eval_partial_caching", setupRunLazyEvalPartialCaching));
        runs.insert(make_pair("eager_eval_partial_caching", setupRunEagerEvalPartialCaching));
        defaultRun = "lazy_eval_partial_caching";
    }

    TFDMEvalInterface::~TFDMEvalInterface()
    {
    }

    void TFDMEvalInterface::initialize(const std::string & domainFile, const std::vector<std::string> & options)
    {
        TFDMInterface::initialize(domainFile, options);

        ROS_INFO("I am in %s", get_current_dir_name());//leak

        ros::NodeHandle nhConfig("/tfd_modules/eval");
        if(!nhConfig.getParam("eval_dir", evalOutputDir)) {
            ROS_FATAL("TFDMEvalInterface: /tfd_modules/eval/eval_dir was not set!");
            evalOutputDir = "/tmp";
        }

        // add date
        time_t rawtime;
        struct tm* timeinfo;
        char buffer[1024];

        time(&rawtime);
        timeinfo = localtime(&rawtime);

        strftime(buffer, 1024, "/%Y-%m-%d_%H-%M-%S", timeinfo);

        evalOutputDir += buffer;
        ROS_INFO("evalOutputDir is %s", evalOutputDir.c_str());
        nhConfig.setParam("eval_current_dir", evalOutputDir);

        int ret = mkdir(evalOutputDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        if(ret != 0) {
            ROS_FATAL("Failed to create evalOutputDir: %s (%d)", evalOutputDir.c_str(), ret);
        }

        safeCopy(this->_domainFile, evalOutputDir + "/domain.pddl");

        callNumber = 0;
    }

    continual_planning_executive::PlannerInterface::PlannerResult TFDMEvalInterface::plan(
            const SymbolicState & init, const SymbolicState & goal, Plan & plan)
    {
        if(!writeProblem(init, goal))
            return PR_FAILURE_OTHER;

        if(!setupRuns()) {
            ROS_FATAL("Failed to setup runs.");
        }

        if(!recordProblemData(init)) {
            ROS_ERROR("Failed to record problem data");
        }

        PlannerResult defaultResult = PR_FAILURE_OTHER;

        for(map<string, setupRunFunction>::iterator it = runs.begin(); it != runs.end(); it++) {
            if(!setupRun(it->first)) {
                ROS_ERROR("Failed to setup run for %s", it->first.c_str());
                continue;
            }

            // call the run specific setup function
            if(! (it->second()) ) {
                ROS_ERROR("Failed run specific setup for %s", it->first.c_str());
                continue;
            }

            if(system("rosparam dump planner_params.yaml /tfd_modules") != 0) {
                ROS_ERROR("Failed to dump planner_params");
            }

            // perfrom the planner call
            std::string planNamePrefix = "plan";
            ROS_INFO("Performing planner call for: %s", it->first.c_str());
            PlannerResult result = callPlanner(this->_domainFile, _problemFileName, planNamePrefix);

            if(it->first == defaultRun) {   // actually use this one for plan + result
                std::string planName = planNamePrefix + ".best";

                defaultResult = result;

                // parse plan
                if(result == PR_SUCCESS_TIMEOUT || result == PR_SUCCESS) {
                    std::ifstream planFile(planName.c_str());
                    bool ok = PlanParser::parsePlan(planFile, plan);
                    planFile.close();
                    if(!ok) {
                        ROS_WARN_STREAM("No plan generated or failure in parsing!" << std::endl);
                        defaultResult = PR_FAILURE_OTHER;
                    }
                }
            }
        }

        return defaultResult;
    }

    continual_planning_executive::PlannerInterface::PlannerResult TFDMEvalInterface::callPlanner(const std::string & domain, const std::string & problem,
            const std::string & planNamePrefix)
    {
        const bool failOnPlannerError = false;  // default: switch off

        string curPlan = planNamePrefix + ".best";
        remove(curPlan.c_str());

        // set plan name
        ros::param::set("tfd_modules/plan_name", planNamePrefix);
        // Determine the planner call command
        std::stringstream plannerCmdStr;
        plannerCmdStr << "rosrun tfd_modules tfd_plan_log " << domain << " " << problem << " tfdsearch.out";
        plannerCmdStr << " __name:=tfd_modules";

        // Later: other features for optional debugging???
        std::string plannerCmd = plannerCmdStr.str();

        ROS_INFO_STREAM("calling planner: " << plannerCmd << std::endl);

        // ACTUAL PLANNER CALL
        int ret = system(plannerCmd.c_str());
        if(ret % 256 == 0)   // for child processed -> returning exitstatus * 256
            ret /= 256;
        else
            ret %= 256;
        ROS_INFO_STREAM("Planner returned: " << ret);

        bool plannerError = false;
        bool plannerTimeout = false;
        if(ret != 0) {
            ROS_WARN_STREAM("Something in the symbolic planner failed! (Signal " << ret << ")\n");
            plannerError = true;
            if(ret == 137) {
                plannerTimeout = true;
                ROS_WARN_STREAM("Planner timeout!" << std::endl);
            } else {
                ROS_WARN_STREAM("Planner failure: " << ret << std::endl);
                if(failOnPlannerError) {
                    ROS_FATAL("Aborting run\n");
                    exit(1);
                }
            }
        }

        // check if plan.best exists for return value
        struct stat st;
        bool planWritten = false;
        if(stat(curPlan.c_str(), &st) == 0) {
            planWritten = true;
        }

        if(planWritten) {
            if(plannerTimeout)
                return PR_SUCCESS_TIMEOUT;
            // FIXME: on error still return success as there is a new plan
            return PR_SUCCESS;
        }

        if(plannerError) {
            if(plannerTimeout)
                return PR_FAILURE_TIMEOUT;
            return PR_FAILURE_OTHER;
        }

        // FIXME: when completely explored and no plan, the planner returns fine (no error)
        // so this really IS an error
        return PR_FAILURE_UNREACHABLE;

    }

    continual_planning_executive::PlannerInterface::PlannerResult TFDMEvalInterface::monitor(
            const SymbolicState & init, const SymbolicState & goal, const Plan & plan)
    {
        return TFDMInterface::monitor(init, goal, plan);
    }

    bool TFDMEvalInterface::setupRuns()
    {
        bool ok = true;

        callNumber++;
        char buf[1024];
        sprintf(buf, "/call%03d", callNumber);

        callDir = evalOutputDir + buf;

        // create change call dir.
        // set and record all params, things that are the same for all runs (problem, etc.)
        int ret = mkdir(callDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        if(ret != 0) {
            ROS_FATAL("Failed to create callDir: %s (%d)", callDir.c_str(), ret);
            ok = false;
            return ok;
        }

        ret = chdir(callDir.c_str());
        if(ret != 0) {
            ROS_FATAL("Failed to change to callDir: %s (%d)", callDir.c_str(), ret);
            ok = false;
            return ok;
        }

        return ok;
    }

    bool TFDMEvalInterface::setupRun(const string & runName)
    {
        bool ok = true;

        // create/change to run dir, etc.
        int ret = chdir(callDir.c_str());
        if(ret != 0) {
            ROS_FATAL("Failed to change to callDir: %s (%d)", callDir.c_str(), ret);
            ok = false;
            return ok;
        }

        ret = mkdir(runName.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        if(ret != 0) {
            ROS_FATAL("Failed to create run dir: %s (%d)", runName.c_str(), ret);
            ok = false;
            return ok;
        }

        ret = chdir(runName.c_str());
        if(ret != 0) {
            ROS_FATAL("Failed to change to run dir: %s (%d)", runName.c_str(), ret);
            ok = false;
            return ok;
        }

        // Clean all intermediate data (plan.1/.best/.times), params???, other output files from modules
        // FIXME: done by changing to new dir.

        return ok;
    }

    bool TFDMEvalInterface::recordProblemData(const SymbolicState & init)
    {
        bool ok = true;

        ok &= safeCopy(_problemFileName, "problem.pddl");

        // record how many objects there are per type
        map<string, int> numObjectsMap;
        // type -> object
        for(SymbolicState::TypedObjectConstIterator it = init.getTypedObjects().begin();
                it != init.getTypedObjects().end(); it++) {
            if(numObjectsMap.find(it->first) == numObjectsMap.end()) {
                numObjectsMap[it->first] = 1;
            } else {
                numObjectsMap[it->first]++;
            }
        }

        ofstream probData("problem.data");
        ok &= probData.good();
        for(map<string, int>::iterator it = numObjectsMap.begin(); it != numObjectsMap.end(); it++) {
            probData << it->first << " " << it->second << endl;
        }
        probData.close();

        return ok;
    }

    bool TFDMEvalInterface::safeCopy(const string & from, const string & to)
    {
        string cmd = "cp " + from + " " + to;
        int ret = system(cmd.c_str());
        if(ret != 0) {
            ROS_ERROR("%s: Error %d when calling \"%s\".", __func__, ret, cmd.c_str());
            return false;
        }
        return true;
    }

};

<|endoftext|>


<commit_before>#include <iostream>
#include <thread>
#include <vector>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <chrono>
#include <poll.h>
#include <mutex>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <stdint.h>

#include "main.h"
#include "dgalutility.h"

namespace {
	std::mutex processingLock;
	std::mutex sendingLock;
	std::mutex nodesLock;
}

//Will return true on success, false on failure.
bool setUpListening(int &listenSocket, const char* port){
	struct addrinfo *info, hints;
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET6;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	getaddrinfo(NULL, port, &hints, &info);

	listenSocket = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
	//Ensure we don't tie up the addr and port combination after exit
	int optval = 1;
	setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
	//Turn off ipv6 only so that we can listen for both v4 and v6 on the same socket
	optval = 0;
	setsockopt(listenSocket, SOL_SOCKET, IPV6_V6ONLY, &optval, sizeof(optval));

	if(listenSocket == -1){
		std::cerr << "Error listening: " << errno << " " << strerror(errno) << std::endl;
		return false;
	}

	if(bind(listenSocket, info->ai_addr, info->ai_addrlen) != 0){
		std::cerr << "Error binding to port " << port << ": " << errno << " " << strerror(errno) << std::endl;
		return false;
	}

	if(listen(listenSocket, 10) != 0){
		std::cerr << "Error listening " << errno << " " << strerror(errno) << std::endl;
		return false;
	}

	return true;
}

void processMessages(processingArgContainer pC, std::queue<std::pair<int, std::string> >& sendingQueue){
	while(true){
		if(pC.socketsToProcess.size() != 0){
			processingLock.lock();
			int fd = pC.socketsToProcess.front();
			pC.socketsToProcess.pop();
			std::shared_ptr<dgalNode> node = pC.nodesToProcess.front();
			pC.nodesToProcess.pop();
			processingLock.unlock();

			//Create buffer to read in message type as well as size information
			char buf[sizeof(uint8_t) + sizeof(uint64_t)];
			memset(buf, 0, sizeof(buf));
			int res = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);

			if(res > 0){
				uint8_t type = (uint8_t) buf[0]; //No endian worry here only 1 byte

				uint64_t convert;
				memcpy(&convert, &buf[1], sizeof(uint64_t));

				uint64_t length = dgal::ntohll(convert); //Convert to host endianness

				if(type == dgal::HEARTBEAT){
					//Heart beat recieved
					node->recievedHeartBeat();
					std::cout << "Recieved heart beat from " << fd << std::endl;
				}else if(type == dgal::BESTMESSAGE){
					//Recieving serialized individuals
					std::cout << "Recieving population from " << fd << std::endl;

					//TODO: Add some safety barriers around allocating huge space
					std::string message(length, 0);
					res = recv(fd, &message[0], length, MSG_DONTWAIT);

					if(res > 0 && (uint64_t) res == length){
						//Recieve bests message, schedule to send out to the rest
						std::cout << message << std::endl;
						sendingLock.lock();
						sendingQueue.push(std::make_pair(fd, message));
						sendingLock.unlock();
					}else{
						std::cerr << "Error reading message from socket! Supplied size wrong!" << std::endl;
					}

				}else{
					//Stream error terminate connection
					std::cerr << "Recieved non conforming message shutting down socket" << std::endl;
					shutdown(fd, SHUT_RDWR);
				}
			}else if(res == -1){
				//Error reading
				std::cerr << "Error reading socket " << fd << ": " << errno << " " << strerror(errno) << std::endl;
			}else{
				//Disconnect
				shutdown(fd, SHUT_RDWR);
			}

			processingLock.lock();
			//Release this socket fd to be allowed to be added back into the queue
			pC.queuedSockets.erase(fd);
			processingLock.unlock();
		}
	}
}

/**
 * Thread to process messages that should be sent out to the nodes in the netework
 * @param nodes        list of nodes
 * @param sendingQueue queue that is added to from processMessages when it recieves a list of a nodes bests
 */
void sendMessages(std::unordered_map<int, std::shared_ptr<dgalNode> >& nodes, std::queue<std::pair<int, std::string> >& sendingQueue){
	while(true){
		if(sendingQueue.empty() == false){
			sendingLock.lock();
			std::pair<int, std::string> sendOut = std::move(sendingQueue.front());
			sendingQueue.pop();
			sendingLock.unlock();

			int dontSendTo = sendOut.first;
			std::string message = std::move(sendOut.second);

			std::vector<int> sendToFds;
			std::vector<std::shared_ptr<dgalNode> > sendToNodes;

			//Get a list of all the nodes first so that we aren't holding a lock while possibly on a blocking send call
			nodesLock.lock();
			for(auto itr = nodes.begin(), end = nodes.end(); itr != end; itr++){
				sendToFds.push_back(itr->first);
				sendToNodes.push_back(itr->second);
			}
			nodesLock.unlock();

			//Form the proper character buffer to send out
			uint64_t messageSize = message.length();
			messageSize = dgal::htonll(messageSize);

			std::string sendBuffer(sizeof(uint8_t) + sizeof(uint64_t) + message.length(), 0);

			sendBuffer[0] = dgal::BESTMESSAGE;
			memcpy(&sendBuffer[1], &messageSize, sizeof(uint64_t));
			sendBuffer += message;

			//Send to all nodes except the one that sent this message
			for(size_t i = 0; i < sendToFds.size(); i++){
				if(sendToFds[i] == dontSendTo){
					continue;
				}

				send(sendToFds[i], sendBuffer.data(), messageSize, 0);
			}

		}
	}
}

void socketWatch(const int listenSocket, std::unordered_map<int, std::shared_ptr<dgalNode> >& nodes){
	std::vector<struct pollfd> socketsToPoll;
	struct pollfd listeningPollFD;

	const short lookForEvents = POLLIN | POLLPRI;

	listeningPollFD.fd = listenSocket;
	listeningPollFD.events = lookForEvents;

	socketsToPoll.push_back(listeningPollFD);

	std::queue<int> socketsToProcess;
	std::queue<std::shared_ptr<dgalNode> > nodesToProcess;
	std::unordered_set<int> queuedSockets;

	processingArgContainer args(socketsToProcess, nodesToProcess, queuedSockets);

	std::queue<std::pair<int, std::string> > sendingQueue;

	size_t numThreads = std::thread::hardware_concurrency();
	if(numThreads == 0){
		std::cerr << "Could not determine number of threads to use. Defaulting to 2" << std::endl;
		numThreads = 1;
	}else{
		//Take one off to account for this thread
		numThreads--;
	}

	std::vector<std::thread> processingThreads;

	for(size_t i = 0; i < numThreads; i++){
		processingThreads.push_back(std::thread(processMessages, args, std::ref(sendingQueue)));
	}

	std::thread sendingThread(sendMessages, std::ref(nodes), std::ref(sendingQueue));

	while(true){
		//Wait a maximum of 30 seconds if no response than we either have no nodes or they all disconnected
		int res = poll(socketsToPoll.data(), socketsToPoll.size(), 3000);

		if(res > 0){
			for(unsigned int i = 0; i < socketsToPoll.size(); i++){
				if(socketsToPoll[i].revents == 0){
					continue;
				}

				if(socketsToPoll[i].fd == listenSocket){
					//We are accepting new connections
					struct pollfd newPollWatch;
					newPollWatch.fd = handleNewConnections(listenSocket, nodes);
					newPollWatch.events = lookForEvents;
					socketsToPoll.push_back(newPollWatch);
					continue;
				}

				bool foundNode = false;
				std::shared_ptr<dgalNode> node;
				nodesLock.lock();
				if(nodes.count(socketsToPoll[i].fd) != 0){
					foundNode = true;
					node = nodes[socketsToPoll[i].fd];
				}
				nodesLock.unlock();

				if(foundNode == false){
					std::cerr << "Cannot find node for socket " << socketsToPoll[i].fd << std::endl;
					shutdown(socketsToPoll[i].fd, SHUT_RDWR);
					close(socketsToPoll[i].fd);
					socketsToPoll.erase(socketsToPoll.begin()+i);
					continue;
				}

				if(socketsToPoll[i].revents & POLLERR){
					std::cerr << "POLLERR " << errno << " " << strerror(errno) << std::endl;
				}else if(socketsToPoll[i].revents & POLLHUP || socketsToPoll[i].revents & POLLRDHUP){
					close(socketsToPoll[i].fd);
					nodesLock.lock();
					nodes.erase(socketsToPoll[i].fd);
					nodesLock.unlock();
					socketsToPoll.erase(socketsToPoll.begin() + i);
				}else if(socketsToPoll[i].revents & POLLIN){
					if(queuedSockets.count(socketsToPoll[i].fd) == 1){
						//we already have processing lined up for this node
						continue;
					}
					processingLock.lock();
					socketsToProcess.push(socketsToPoll[i].fd);
					nodesToProcess.push(node);
					queuedSockets.insert(socketsToPoll[i].fd);
					processingLock.unlock();
				}

			}
		}
	}

	for(size_t i = 0; i < processingThreads.size(); i++){
		processingThreads[i].join();
	}
	sendingThread.join();
}

int handleNewConnections(const int listenSocket, std::unordered_map<int, std::shared_ptr<dgalNode> >& nodes){
	struct sockaddr_storage clientInfo;
	int clientSocket;
	socklen_t sockStoreSize = sizeof(struct sockaddr_storage);

	//Accept new connections and add them to the nodes list
	clientSocket = accept(listenSocket, (struct sockaddr *) &clientInfo, &sockStoreSize);
	if(clientSocket == -1){
		std::cerr << "Error accepting " << errno << " " << strerror(errno) << std::endl;
		return -1;
	}

	std::shared_ptr<dgalNode> newClientNode(new dgalNode(clientSocket, "test", 2));
	nodesLock.lock();
	nodes.insert(std::make_pair(clientSocket, newClientNode));
	nodesLock.unlock();

	return clientSocket;
}

int main(int argc, char *argv[]){
	std::string port;
	if(argc > 1){
		port = argv[1];
	}else{
		port = "25665";
	}

	int listeningSocket;
	std::unordered_map<int, std::shared_ptr<dgalNode> > nodes;

	if(setUpListening(listeningSocket, port.c_str()) == false){
		return 1;
	}

	socketWatch(listeningSocket, nodes);

	return 0;
}
<commit_msg>Adding note to make sure server gets fixed.<commit_after>#include <iostream>
#include <thread>
#include <vector>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <chrono>
#include <poll.h>
#include <mutex>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <stdint.h>

#include "main.h"
#include "dgalutility.h"

namespace {
	std::mutex processingLock;
	std::mutex sendingLock;
	std::mutex nodesLock;
}

//Will return true on success, false on failure.
bool setUpListening(int &listenSocket, const char* port){
	struct addrinfo *info, hints;
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET6;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	getaddrinfo(NULL, port, &hints, &info);

	listenSocket = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
	//Ensure we don't tie up the addr and port combination after exit
	int optval = 1;
	setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
	//Turn off ipv6 only so that we can listen for both v4 and v6 on the same socket
	optval = 0;
	setsockopt(listenSocket, SOL_SOCKET, IPV6_V6ONLY, &optval, sizeof(optval));

	if(listenSocket == -1){
		std::cerr << "Error listening: " << errno << " " << strerror(errno) << std::endl;
		return false;
	}

	if(bind(listenSocket, info->ai_addr, info->ai_addrlen) != 0){
		std::cerr << "Error binding to port " << port << ": " << errno << " " << strerror(errno) << std::endl;
		return false;
	}

	if(listen(listenSocket, 10) != 0){
		std::cerr << "Error listening " << errno << " " << strerror(errno) << std::endl;
		return false;
	}

	return true;
}

void processMessages(processingArgContainer pC, std::queue<std::pair<int, std::string> >& sendingQueue){
	while(true){
		if(pC.socketsToProcess.size() != 0){
			processingLock.lock();
			int fd = pC.socketsToProcess.front();
			pC.socketsToProcess.pop();
			std::shared_ptr<dgalNode> node = pC.nodesToProcess.front();
			pC.nodesToProcess.pop();
			processingLock.unlock();

			//Create buffer to read in message type as well as size information
			char buf[sizeof(uint8_t) + sizeof(uint64_t)];
			memset(buf, 0, sizeof(buf));
			int res = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);

			if(res > 0){
				uint8_t type = (uint8_t) buf[0]; //No endian worry here only 1 byte

				uint64_t convert;
				memcpy(&convert, &buf[1], sizeof(uint64_t));

				uint64_t length = dgal::ntohll(convert); //Convert to host endianness

				if(type == dgal::HEARTBEAT){
					//Heart beat recieved
					node->recievedHeartBeat();
					std::cout << "Recieved heart beat from " << fd << std::endl;
				}else if(type == dgal::BESTMESSAGE){
					//Recieving serialized individuals
					std::cout << "Recieving population from " << fd << std::endl;

					//TODO: Add some safety barriers around allocating huge space
					std::string message(length, 0);
					res = recv(fd, &message[0], length, MSG_DONTWAIT);

					if(res > 0 && (uint64_t) res == length){
						//Recieve bests message, schedule to send out to the rest
						std::cout << message << std::endl;
						sendingLock.lock();
						sendingQueue.push(std::make_pair(fd, message));
						sendingLock.unlock();
					}else{
						std::cerr << "Error reading message from socket! Supplied size wrong!" << std::endl;
					}

				}else{
					//Stream error terminate connection
					std::cerr << "Recieved non conforming message shutting down socket" << std::endl;
					shutdown(fd, SHUT_RDWR);
				}
			}else if(res == -1){
				//Error reading
				std::cerr << "Error reading socket " << fd << ": " << errno << " " << strerror(errno) << std::endl;
			}else{
				//Disconnect
				shutdown(fd, SHUT_RDWR);
			}

			processingLock.lock();
			//Release this socket fd to be allowed to be added back into the queue
			pC.queuedSockets.erase(fd);
			processingLock.unlock();
		}
	}
}

/**
 * Thread to process messages that should be sent out to the nodes in the netework
 * @param nodes        list of nodes
 * @param sendingQueue queue that is added to from processMessages when it recieves a list of a nodes bests
 */
void sendMessages(std::unordered_map<int, std::shared_ptr<dgalNode> >& nodes, std::queue<std::pair<int, std::string> >& sendingQueue){
	while(true){
		if(sendingQueue.empty() == false){
			sendingLock.lock();
			std::pair<int, std::string> sendOut = std::move(sendingQueue.front());
			sendingQueue.pop();
			sendingLock.unlock();

			int dontSendTo = sendOut.first;
			std::string message = std::move(sendOut.second);

			std::vector<int> sendToFds;
			std::vector<std::shared_ptr<dgalNode> > sendToNodes;

			//Get a list of all the nodes first so that we aren't holding a lock while possibly on a blocking send call
			nodesLock.lock();
			for(auto itr = nodes.begin(), end = nodes.end(); itr != end; itr++){
				sendToFds.push_back(itr->first);
				sendToNodes.push_back(itr->second);
			}
			nodesLock.unlock();

			//Form the proper character buffer to send out
			uint64_t messageSize = message.length();
			messageSize = dgal::htonll(messageSize);

			std::string sendBuffer(sizeof(uint8_t) + sizeof(uint64_t) + message.length(), 0);

			sendBuffer[0] = dgal::BESTMESSAGE;
			memcpy(&sendBuffer[1], &messageSize, sizeof(uint64_t));
			sendBuffer += message;

			//Send to all nodes except the one that sent this message
			for(size_t i = 0; i < sendToFds.size(); i++){
				if(sendToFds[i] == dontSendTo){
					continue;
				}

				send(sendToFds[i], sendBuffer.data(), messageSize, 0);
			}

		}
	}
}

void socketWatch(const int listenSocket, std::unordered_map<int, std::shared_ptr<dgalNode> >& nodes){
	std::vector<struct pollfd> socketsToPoll;
	struct pollfd listeningPollFD;

	const short lookForEvents = POLLIN | POLLPRI;

	listeningPollFD.fd = listenSocket;
	listeningPollFD.events = lookForEvents;

	socketsToPoll.push_back(listeningPollFD);

	std::queue<int> socketsToProcess;
	std::queue<std::shared_ptr<dgalNode> > nodesToProcess;
	std::unordered_set<int> queuedSockets;

	processingArgContainer args(socketsToProcess, nodesToProcess, queuedSockets);

	std::queue<std::pair<int, std::string> > sendingQueue;

	size_t numThreads = std::thread::hardware_concurrency();
	if(numThreads == 0){
		std::cerr << "Could not determine number of threads to use. Defaulting to 2" << std::endl;
		numThreads = 1;
	}else{
		//Take one off to account for this thread
		numThreads--;
	}

	std::vector<std::thread> processingThreads;

	for(size_t i = 0; i < numThreads; i++){
		processingThreads.push_back(std::thread(processMessages, args, std::ref(sendingQueue)));
	}

	std::thread sendingThread(sendMessages, std::ref(nodes), std::ref(sendingQueue));

	while(true){
		//Wait a maximum of 30 seconds if no response than we either have no nodes or they all disconnected
		int res = poll(socketsToPoll.data(), socketsToPoll.size(), 3000);

		if(res > 0){
			//FIXME: Problem when all nodes close socket connection at end, goes through POLLERR 22
			//Only happens when all nodes finished simulation, not if connection is closed before end of sim.
			for(unsigned int i = 0; i < socketsToPoll.size(); i++){
				if(socketsToPoll[i].revents == 0){
					continue;
				}

				if(socketsToPoll[i].fd == listenSocket){
					//We are accepting new connections
					struct pollfd newPollWatch;
					newPollWatch.fd = handleNewConnections(listenSocket, nodes);
					newPollWatch.events = lookForEvents;
					socketsToPoll.push_back(newPollWatch);
					continue;
				}

				bool foundNode = false;
				std::shared_ptr<dgalNode> node;
				nodesLock.lock();
				if(nodes.count(socketsToPoll[i].fd) != 0){
					foundNode = true;
					node = nodes[socketsToPoll[i].fd];
				}
				nodesLock.unlock();

				if(foundNode == false){
					std::cerr << "Cannot find node for socket " << socketsToPoll[i].fd << std::endl;
					shutdown(socketsToPoll[i].fd, SHUT_RDWR);
					close(socketsToPoll[i].fd);
					socketsToPoll.erase(socketsToPoll.begin()+i);
					continue;
				}

				if(socketsToPoll[i].revents & POLLERR){
					std::cerr << "POLLERR " << errno << " " << strerror(errno) << std::endl;
				}else if(socketsToPoll[i].revents & POLLHUP || socketsToPoll[i].revents & POLLRDHUP){
					close(socketsToPoll[i].fd);
					nodesLock.lock();
					nodes.erase(socketsToPoll[i].fd);
					nodesLock.unlock();
					socketsToPoll.erase(socketsToPoll.begin() + i);
				}else if(socketsToPoll[i].revents & POLLIN){
					if(queuedSockets.count(socketsToPoll[i].fd) == 1){
						//we already have processing lined up for this node
						continue;
					}
					processingLock.lock();
					socketsToProcess.push(socketsToPoll[i].fd);
					nodesToProcess.push(node);
					queuedSockets.insert(socketsToPoll[i].fd);
					processingLock.unlock();
				}

			}
		}
	}

	for(size_t i = 0; i < processingThreads.size(); i++){
		processingThreads[i].join();
	}
	sendingThread.join();
}

int handleNewConnections(const int listenSocket, std::unordered_map<int, std::shared_ptr<dgalNode> >& nodes){
	struct sockaddr_storage clientInfo;
	int clientSocket;
	socklen_t sockStoreSize = sizeof(struct sockaddr_storage);

	//Accept new connections and add them to the nodes list
	clientSocket = accept(listenSocket, (struct sockaddr *) &clientInfo, &sockStoreSize);
	if(clientSocket == -1){
		std::cerr << "Error accepting " << errno << " " << strerror(errno) << std::endl;
		return -1;
	}

	std::shared_ptr<dgalNode> newClientNode(new dgalNode(clientSocket, "test", 2));
	nodesLock.lock();
	nodes.insert(std::make_pair(clientSocket, newClientNode));
	nodesLock.unlock();

	return clientSocket;
}

int main(int argc, char *argv[]){
	std::string port;
	if(argc > 1){
		port = argv[1];
	}else{
		port = "25665";
	}

	int listeningSocket;
	std::unordered_map<int, std::shared_ptr<dgalNode> > nodes;

	if(setUpListening(listeningSocket, port.c_str()) == false){
		return 1;
	}

	socketWatch(listeningSocket, nodes);

	return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIAffector.cpp
    created:    7/8/2010
    author:     Martin Preisler

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

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
Affector::Affector(Animation* parent):
    d_parent(parent),
    d_applicationMethod(AM_Absolute),
    d_targetProperty(""),
    d_interpolator(0)
{}

//----------------------------------------------------------------------------//
Affector::~Affector(void)
{
    while (d_keyFrames.size() > 0)
    {
        destroyKeyFrame(getKeyFrameAtIdx(0));
    }
}

//----------------------------------------------------------------------------//
size_t Affector::getIdxInParent() const
{
    const Animation* parent = getParent();
    assert(getParent() && "No parent, no index in parent!");

    size_t i = 0;
    while (i < parent->getNumAffectors())
    {
        if (parent->getAffectorAtIdx(i) == this)
        {
            return i;
        }

        ++i;
    }

    CEGUI_THROW(UnknownObjectException("Affector::getIdxInParent(): Affector wasn't found in parent, therefore its index is unknown!"));
}

//----------------------------------------------------------------------------//
void Affector::setApplicationMethod(ApplicationMethod method)
{
    d_applicationMethod = method;
}

//----------------------------------------------------------------------------//
Affector::ApplicationMethod Affector::getApplicationMethod() const
{
    return d_applicationMethod;
}

//----------------------------------------------------------------------------//
void Affector::setTargetProperty(const String& target)
{
    d_targetProperty = target;
}

//----------------------------------------------------------------------------//
const String& Affector::getTargetProperty() const
{
    return d_targetProperty;
}

//----------------------------------------------------------------------------//
void Affector::setInterpolator(Interpolator* interpolator)
{
    d_interpolator = interpolator;
}

//----------------------------------------------------------------------------//
void Affector::setInterpolator(const String& name)
{
    d_interpolator = AnimationManager::getSingleton().getInterpolator(name);
}

//----------------------------------------------------------------------------//
Interpolator* Affector::getInterpolator() const
{
    return d_interpolator;
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::createKeyFrame(float position)
{
    if (d_keyFrames.find(position) != d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::createKeyFrame: Unable to create KeyFrame "
                        "at given position, there already is a KeyFrame "
                        "on that position."));
    }

    KeyFrame* ret = CEGUI_NEW_AO KeyFrame(this, position);
    d_keyFrames.insert(std::make_pair(position, ret));

    return ret;
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::createKeyFrame(float position, const String& value,
                                   KeyFrame::Progression progression, const String& sourceProperty)
{
    KeyFrame* ret = createKeyFrame(position);
    ret->setValue(value);
    ret->setProgression(progression);
    ret->setSourceProperty(sourceProperty);

    return ret;
}

//----------------------------------------------------------------------------//
void Affector::destroyKeyFrame(KeyFrame* keyframe)
{
    KeyFrameMap::iterator it = d_keyFrames.find(keyframe->getPosition());

    if (it == d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::destroyKeyFrame: Unable to destroy given KeyFrame! "
                        "No such KeyFrame was found."));
    }

    d_keyFrames.erase(it);
    CEGUI_DELETE_AO keyframe;
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::getKeyFrameAtPosition(float position) const
{
    KeyFrameMap::const_iterator it = d_keyFrames.find(position);

    if (it == d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::getKeyFrameAtPosition: Can't find a KeyFrame with given "
                        "position."));
    }

    return it->second;
}

//----------------------------------------------------------------------------//
bool Affector::hasKeyFrameAtPosition(float position) const
{
	return d_keyFrames.find(position) != d_keyFrames.end();
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::getKeyFrameAtIdx(size_t index) const
{
    if (index >= d_keyFrames.size())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::getKeyFrameAtIdx: Out of bounds!"));
    }

    KeyFrameMap::const_iterator it = d_keyFrames.begin();
    std::advance(it, index);

    return it->second;
}

//----------------------------------------------------------------------------//
size_t Affector::getNumKeyFrames() const
{
    return d_keyFrames.size();
}

//----------------------------------------------------------------------------//
void Affector::moveKeyFrameToPosition(KeyFrame* keyframe, float newPosition)
{
	if (keyframe->getPosition() == newPosition)
		return;

    if (d_keyFrames.find(newPosition) != d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                    "Affector::moveKeyFrameToPosition: There is already a key frame at "
        		    "position: "+ PropertyHelper<float>::toString(newPosition) + "."));
	}

    for (KeyFrameMap::iterator it = d_keyFrames.begin(); it != d_keyFrames.end(); ++it)
    {
        if (it->second == keyframe)
        {
            d_keyFrames.erase(it);
            d_keyFrames.insert(std::make_pair(newPosition, keyframe));

            keyframe->notifyPositionChanged(newPosition);
            return;
        }
    }

    CEGUI_THROW(UnknownObjectException("Affector::moveKeyFrameToPosition - passed key frame wasn't found within this affector"));
}

//----------------------------------------------------------------------------//
void Affector::moveKeyFrameToPosition(float oldPosition, float newPosition)
{
    KeyFrame* kf = getKeyFrameAtPosition(oldPosition);

    moveKeyFrameToPosition(kf, newPosition);
}

//----------------------------------------------------------------------------//
void Affector::savePropertyValues(AnimationInstance* instance)
{
    switch (d_applicationMethod)
    {
    case AM_Relative:
    case AM_RelativeMultiply:
        instance->savePropertyValue(d_targetProperty);
        break;

    default:
        break;
    }

    // now let all keyframes save their desired property values too
    for (KeyFrameMap::const_iterator it = d_keyFrames.begin();
         it != d_keyFrames.end(); ++it)
    {
        it->second->savePropertyValue(instance);
    }
}

//----------------------------------------------------------------------------//
void Affector::apply(AnimationInstance* instance)
{
    PropertySet* target = instance->getTarget();
    const float position = instance->getPosition();

    // special case
    if (d_keyFrames.empty())
    {
        return;
    }

    if (d_targetProperty.empty())
    {
        Logger::getSingleton().logEvent(
            "Affector can't be applied when target property is set!", Warnings);
        return;
    }

    if (!d_interpolator)
    {
        Logger::getSingleton().logEvent(
            "Affector can't be applied when no interpolator is set!", Warnings);
        return;
    }

    KeyFrame* left = 0;
    KeyFrame* right = 0;

    // find 2 neighbouring keyframes
    for (KeyFrameMap::const_iterator it = d_keyFrames.begin();
         it != d_keyFrames.end(); ++it)
    {
        KeyFrame* current = it->second;

        if (current->getPosition() <= position)
        {
            left = current;
        }

        if (current->getPosition() >= position && !right)
        {
            right = current;
        }
    }

    float leftDistance, rightDistance;

    if (left)
    {
        leftDistance = position - left->getPosition();
    }
    else
        // if no keyframe is suitable for left neighbour, pick the first one
    {
        left = d_keyFrames.begin()->second;
        leftDistance = 0;
    }

    if (right)
    {
        rightDistance = right->getPosition() - position;
    }
    else
        // if no keyframe is suitable for the right neighbour, pick the last one
    {
        right = d_keyFrames.rbegin()->second;
        rightDistance = 0;
    }

    // if there is just one keyframe and we are right on it
    if (leftDistance + rightDistance == 0)
    {
        leftDistance = rightDistance = 0.5;
    }

    // alter interpolation position using the right neighbours progression
    // method
    const float interpolationPosition =
        right->alterInterpolationPosition(
            leftDistance / (leftDistance + rightDistance));

    // absolute application method
    if (d_applicationMethod == AM_Absolute)
    {
        const String result = d_interpolator->interpolateAbsolute(
                                  left->getValueForAnimation(instance),
                                  right->getValueForAnimation(instance),
                                  interpolationPosition);

        target->setProperty(d_targetProperty, result);
    }
    // relative application method
    else if (d_applicationMethod == AM_Relative)
    {
        const String& base = instance->getSavedPropertyValue(getTargetProperty());

        const String result = d_interpolator->interpolateRelative(
                                  base,
                                  left->getValueForAnimation(instance),
                                  right->getValueForAnimation(instance),
                                  interpolationPosition);

        target->setProperty(d_targetProperty, result);
    }
    // relative multiply application method
    else if (d_applicationMethod == AM_RelativeMultiply)
    {
        const String& base = instance->getSavedPropertyValue(getTargetProperty());

        const String result = d_interpolator->interpolateRelativeMultiply(
                                  base,
                                  left->getValueForAnimation(instance),
                                  right->getValueForAnimation(instance),
                                  interpolationPosition);

        target->setProperty(d_targetProperty, result);
    }
    // todo: more application methods?
    else
    {
        assert(0);
    }
}

void Affector::writeXMLToStream(XMLSerializer& xml_stream) const
{
    xml_stream.openTag(AnimationAffectorHandler::ElementName);

    String applicationMethod;
    switch(getApplicationMethod())
    {
    case AM_Absolute:
        applicationMethod = AnimationAffectorHandler::ApplicationMethodAbsolute;
        break;
    case AM_Relative:
        applicationMethod = AnimationAffectorHandler::ApplicationMethodRelative;
        break;
    case AM_RelativeMultiply:
        applicationMethod = AnimationAffectorHandler::ApplicationMethodRelativeMultiply;
        break;

    default:
        assert(0 && "How did we get here?");
        break;
    }

    xml_stream.attribute(AnimationAffectorHandler::ApplicationMethodAttribute, applicationMethod);

    xml_stream.attribute(AnimationAffectorHandler::TargetPropertyAttribute, getTargetProperty());

    if (getInterpolator())
    {
        xml_stream.attribute(AnimationAffectorHandler::InterpolatorAttribute, getInterpolator()->getType());
    }

    for (KeyFrameMap::const_iterator it = d_keyFrames.begin();
         it != d_keyFrames.end(); ++it)
    {
        it->second->writeXMLToStream(xml_stream);
    }

    xml_stream.closeTag();
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<commit_msg>Fixed an affector no target property logger warning<commit_after>/***********************************************************************
    filename:   CEGUIAffector.cpp
    created:    7/8/2010
    author:     Martin Preisler

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

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
Affector::Affector(Animation* parent):
    d_parent(parent),
    d_applicationMethod(AM_Absolute),
    d_targetProperty(""),
    d_interpolator(0)
{}

//----------------------------------------------------------------------------//
Affector::~Affector(void)
{
    while (d_keyFrames.size() > 0)
    {
        destroyKeyFrame(getKeyFrameAtIdx(0));
    }
}

//----------------------------------------------------------------------------//
size_t Affector::getIdxInParent() const
{
    const Animation* parent = getParent();
    assert(getParent() && "No parent, no index in parent!");

    size_t i = 0;
    while (i < parent->getNumAffectors())
    {
        if (parent->getAffectorAtIdx(i) == this)
        {
            return i;
        }

        ++i;
    }

    CEGUI_THROW(UnknownObjectException("Affector::getIdxInParent(): Affector wasn't found in parent, therefore its index is unknown!"));
}

//----------------------------------------------------------------------------//
void Affector::setApplicationMethod(ApplicationMethod method)
{
    d_applicationMethod = method;
}

//----------------------------------------------------------------------------//
Affector::ApplicationMethod Affector::getApplicationMethod() const
{
    return d_applicationMethod;
}

//----------------------------------------------------------------------------//
void Affector::setTargetProperty(const String& target)
{
    d_targetProperty = target;
}

//----------------------------------------------------------------------------//
const String& Affector::getTargetProperty() const
{
    return d_targetProperty;
}

//----------------------------------------------------------------------------//
void Affector::setInterpolator(Interpolator* interpolator)
{
    d_interpolator = interpolator;
}

//----------------------------------------------------------------------------//
void Affector::setInterpolator(const String& name)
{
    d_interpolator = AnimationManager::getSingleton().getInterpolator(name);
}

//----------------------------------------------------------------------------//
Interpolator* Affector::getInterpolator() const
{
    return d_interpolator;
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::createKeyFrame(float position)
{
    if (d_keyFrames.find(position) != d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::createKeyFrame: Unable to create KeyFrame "
                        "at given position, there already is a KeyFrame "
                        "on that position."));
    }

    KeyFrame* ret = CEGUI_NEW_AO KeyFrame(this, position);
    d_keyFrames.insert(std::make_pair(position, ret));

    return ret;
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::createKeyFrame(float position, const String& value,
                                   KeyFrame::Progression progression, const String& sourceProperty)
{
    KeyFrame* ret = createKeyFrame(position);
    ret->setValue(value);
    ret->setProgression(progression);
    ret->setSourceProperty(sourceProperty);

    return ret;
}

//----------------------------------------------------------------------------//
void Affector::destroyKeyFrame(KeyFrame* keyframe)
{
    KeyFrameMap::iterator it = d_keyFrames.find(keyframe->getPosition());

    if (it == d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::destroyKeyFrame: Unable to destroy given KeyFrame! "
                        "No such KeyFrame was found."));
    }

    d_keyFrames.erase(it);
    CEGUI_DELETE_AO keyframe;
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::getKeyFrameAtPosition(float position) const
{
    KeyFrameMap::const_iterator it = d_keyFrames.find(position);

    if (it == d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::getKeyFrameAtPosition: Can't find a KeyFrame with given "
                        "position."));
    }

    return it->second;
}

//----------------------------------------------------------------------------//
bool Affector::hasKeyFrameAtPosition(float position) const
{
	return d_keyFrames.find(position) != d_keyFrames.end();
}

//----------------------------------------------------------------------------//
KeyFrame* Affector::getKeyFrameAtIdx(size_t index) const
{
    if (index >= d_keyFrames.size())
    {
        CEGUI_THROW(InvalidRequestException(
                        "Affector::getKeyFrameAtIdx: Out of bounds!"));
    }

    KeyFrameMap::const_iterator it = d_keyFrames.begin();
    std::advance(it, index);

    return it->second;
}

//----------------------------------------------------------------------------//
size_t Affector::getNumKeyFrames() const
{
    return d_keyFrames.size();
}

//----------------------------------------------------------------------------//
void Affector::moveKeyFrameToPosition(KeyFrame* keyframe, float newPosition)
{
	if (keyframe->getPosition() == newPosition)
		return;

    if (d_keyFrames.find(newPosition) != d_keyFrames.end())
    {
        CEGUI_THROW(InvalidRequestException(
                    "Affector::moveKeyFrameToPosition: There is already a key frame at "
        		    "position: "+ PropertyHelper<float>::toString(newPosition) + "."));
	}

    for (KeyFrameMap::iterator it = d_keyFrames.begin(); it != d_keyFrames.end(); ++it)
    {
        if (it->second == keyframe)
        {
            d_keyFrames.erase(it);
            d_keyFrames.insert(std::make_pair(newPosition, keyframe));

            keyframe->notifyPositionChanged(newPosition);
            return;
        }
    }

    CEGUI_THROW(UnknownObjectException("Affector::moveKeyFrameToPosition - passed key frame wasn't found within this affector"));
}

//----------------------------------------------------------------------------//
void Affector::moveKeyFrameToPosition(float oldPosition, float newPosition)
{
    KeyFrame* kf = getKeyFrameAtPosition(oldPosition);

    moveKeyFrameToPosition(kf, newPosition);
}

//----------------------------------------------------------------------------//
void Affector::savePropertyValues(AnimationInstance* instance)
{
    switch (d_applicationMethod)
    {
    case AM_Relative:
    case AM_RelativeMultiply:
        instance->savePropertyValue(d_targetProperty);
        break;

    default:
        break;
    }

    // now let all keyframes save their desired property values too
    for (KeyFrameMap::const_iterator it = d_keyFrames.begin();
         it != d_keyFrames.end(); ++it)
    {
        it->second->savePropertyValue(instance);
    }
}

//----------------------------------------------------------------------------//
void Affector::apply(AnimationInstance* instance)
{
    PropertySet* target = instance->getTarget();
    const float position = instance->getPosition();

    // special case
    if (d_keyFrames.empty())
    {
        return;
    }

    if (d_targetProperty.empty())
    {
        Logger::getSingleton().logEvent(
            "Affector can't be applied when target property is empty!", Warnings);
        return;
    }

    if (!d_interpolator)
    {
        Logger::getSingleton().logEvent(
            "Affector can't be applied when no interpolator is set!", Warnings);
        return;
    }

    KeyFrame* left = 0;
    KeyFrame* right = 0;

    // find 2 neighbouring keyframes
    for (KeyFrameMap::const_iterator it = d_keyFrames.begin();
         it != d_keyFrames.end(); ++it)
    {
        KeyFrame* current = it->second;

        if (current->getPosition() <= position)
        {
            left = current;
        }

        if (current->getPosition() >= position && !right)
        {
            right = current;
        }
    }

    float leftDistance, rightDistance;

    if (left)
    {
        leftDistance = position - left->getPosition();
    }
    else
        // if no keyframe is suitable for left neighbour, pick the first one
    {
        left = d_keyFrames.begin()->second;
        leftDistance = 0;
    }

    if (right)
    {
        rightDistance = right->getPosition() - position;
    }
    else
        // if no keyframe is suitable for the right neighbour, pick the last one
    {
        right = d_keyFrames.rbegin()->second;
        rightDistance = 0;
    }

    // if there is just one keyframe and we are right on it
    if (leftDistance + rightDistance == 0)
    {
        leftDistance = rightDistance = 0.5;
    }

    // alter interpolation position using the right neighbours progression
    // method
    const float interpolationPosition =
        right->alterInterpolationPosition(
            leftDistance / (leftDistance + rightDistance));

    // absolute application method
    if (d_applicationMethod == AM_Absolute)
    {
        const String result = d_interpolator->interpolateAbsolute(
                                  left->getValueForAnimation(instance),
                                  right->getValueForAnimation(instance),
                                  interpolationPosition);

        target->setProperty(d_targetProperty, result);
    }
    // relative application method
    else if (d_applicationMethod == AM_Relative)
    {
        const String& base = instance->getSavedPropertyValue(getTargetProperty());

        const String result = d_interpolator->interpolateRelative(
                                  base,
                                  left->getValueForAnimation(instance),
                                  right->getValueForAnimation(instance),
                                  interpolationPosition);

        target->setProperty(d_targetProperty, result);
    }
    // relative multiply application method
    else if (d_applicationMethod == AM_RelativeMultiply)
    {
        const String& base = instance->getSavedPropertyValue(getTargetProperty());

        const String result = d_interpolator->interpolateRelativeMultiply(
                                  base,
                                  left->getValueForAnimation(instance),
                                  right->getValueForAnimation(instance),
                                  interpolationPosition);

        target->setProperty(d_targetProperty, result);
    }
    // todo: more application methods?
    else
    {
        assert(0);
    }
}

void Affector::writeXMLToStream(XMLSerializer& xml_stream) const
{
    xml_stream.openTag(AnimationAffectorHandler::ElementName);

    String applicationMethod;
    switch(getApplicationMethod())
    {
    case AM_Absolute:
        applicationMethod = AnimationAffectorHandler::ApplicationMethodAbsolute;
        break;
    case AM_Relative:
        applicationMethod = AnimationAffectorHandler::ApplicationMethodRelative;
        break;
    case AM_RelativeMultiply:
        applicationMethod = AnimationAffectorHandler::ApplicationMethodRelativeMultiply;
        break;

    default:
        assert(0 && "How did we get here?");
        break;
    }

    xml_stream.attribute(AnimationAffectorHandler::ApplicationMethodAttribute, applicationMethod);

    xml_stream.attribute(AnimationAffectorHandler::TargetPropertyAttribute, getTargetProperty());

    if (getInterpolator())
    {
        xml_stream.attribute(AnimationAffectorHandler::InterpolatorAttribute, getInterpolator()->getType());
    }

    for (KeyFrameMap::const_iterator it = d_keyFrames.begin();
         it != d_keyFrames.end(); ++it)
    {
        it->second->writeXMLToStream(xml_stream);
    }

    xml_stream.closeTag();
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<|endoftext|>


<commit_before>// ----------------------------------------------------//
//                                                     //
//       This macro reads the PMD clusters which       //
//       are stored in the file "PMD.RecPoints.root"   //
//                                                     //
// ----------------------------------------------------//

#include <Riostream.h>
#include "TBranch.h"
#include "TStopwatch.h"

extern AliRun *gAlice;

Int_t AliPMDRecpointRead(Int_t nevent = 1)
{
  if (gAlice)
    {
      delete AliRunLoader::Instance();
      delete gAlice;//if everything was OK here it is already NULL
      gAlice = 0x0;
    }
  AliRunLoader *fRunLoader = AliRunLoader::Open("galice.root","Event","update");
  if (!fRunLoader)
    {
      cerr<<"Can't load RunLoader"<<endl;
      return 1;
    }
  AliLoader *pmdloader = fRunLoader->GetLoader("PMDLoader");
  Int_t nevent = fRunLoader->GetNumberOfEvents();
  cout << " * *********** nevent = " << nevent << endl;

  if (pmdloader == 0x0)
    {
      cerr<<" ===> Can not find PMD or PMDLoader <===\n";
      delete fRunLoader;
      return 2;
    }

  pmdloader->LoadRecPoints("READ");
  TClonesArray *fRecpoints;
  AliPMDUtility *cc = new AliPMDUtility();
  TH2F *h2 = new TH2F("h2"," ",100,-100.,100.,100,-100.,100.);

  FILE *fpw = fopen("junk_rec.dat","w");

  for (Int_t ievt = 0; ievt < nevent; ievt++)
    {
      fRunLoader->GetEvent(ievt);
      TTree *treeR = pmdloader->TreeR();
      if (treeR == 0x0)
	{
	  cout << " Can not get TreeR" << endl;
	  return 3;
	}

      AliPMDrecpoint1  *pmdrecpoint;
      TBranch *branch1 = treeR->GetBranch("PMDRecpoint");
      branch1->SetAddress(&fRecpoints);
      /**********************************************************************
       *    det   : Detector, 0: PRE & 1:CPV                                *
       *    smn   : Serial Module Number from 0 to 23 for both detector     *
       *    xpos  : x-position of the cluster                               *
       *    ypos  : y-position of the cluster                               *
       *            THESE xpos & ypos are not the true xpos and ypos        *
       *            for some of the unit modules. They are rotated.         *
       *    adc   : ADC contained in the cluster                            *
       *    ncell : Number of cells contained in the cluster                *
       *    rad   : radius of the cluster (1d fit)                          *
       *    xpad  : TRUE x-position of the cluster                          *
       *    ypad  : TRUE y-position of the cluster                          *
       **********************************************************************/

      Int_t   det,smn;
      Float_t xpos,ypos, xpad, ypad;
      Float_t adc, ncell, sigx, sigy;
      Float_t xx, yy;
      Int_t   nmodules = branch1->GetEntries();
      cout << " nmodules = " << nmodules << endl;
      for (Int_t imodule = 0; imodule < nmodules; imodule++)
	{
	  branch1->GetEntry(imodule);
	  Int_t nentries = fRecpoints->GetLast();
	  for(Int_t ient = 0; ient < nentries+1; ient++)
	    {
	      pmdrecpoint = (AliPMDrecpoint1*)fRecpoints->UncheckedAt(ient);
	      det   = (Int_t) pmdrecpoint->GetDetector();
	      smn   = (Int_t) pmdrecpoint->GetSMNumber();
	      xpos  = pmdrecpoint->GetClusX();
	      ypos  = pmdrecpoint->GetClusY();
	      adc   = pmdrecpoint->GetClusADC();
	      ncell = pmdrecpoint->GetClusCells();
	      sigx  = pmdrecpoint->GetClusSigmaX();
	      sigy  = pmdrecpoint->GetClusSigmaY();

	      //
	      // User has to plug in his analysis code here
	      //

	      fprintf(fpw,"%d %d %d %d\n",
		      det,smn,xpos,ypos);
	      //
	      // Plot the cluster centroid to see the PMD geometry
	      // using the PMD Utility class
	      //
	      if (det == 0)
		{
		  // Draw only for PRE plane
		  //cc->RectGeomCellPos(ism,xpad,ypad,xx,yy);
		  cc->RectGeomCellPos(smn,xpos,ypos,xx,yy);
		  h2->Fill(xx,yy);
		}

	      //
	      // End of the User code
	      //
	    }
	}

    }

  h2->Draw();

  fclose(fpw);
  return 0;
}

<commit_msg>alignment data is taken to calculate the new global coordinates<commit_after>// ----------------------------------------------------//
//                                                     //
//       This macro reads the PMD clusters which       //
//       are stored in the file "PMD.RecPoints.root"   //
//                                                     //
// ----------------------------------------------------//

#include <Riostream.h>
#include "TBranch.h"
#include "TStopwatch.h"

extern AliRun *gAlice;

Int_t AliPMDRecpointRead(Int_t nevent = 1)
{
  if (gAlice)
    {
      delete AliRunLoader::Instance();
      delete gAlice;//if everything was OK here it is already NULL
      gAlice = 0x0;
    }
  AliRunLoader *fRunLoader = AliRunLoader::Open("galice.root","Event","update");
  if (!fRunLoader)
    {
      cerr<<"Can't load RunLoader"<<endl;
      return 1;
    }
  AliLoader *pmdloader = fRunLoader->GetLoader("PMDLoader");
  Int_t nevent = fRunLoader->GetNumberOfEvents();
  cout << " * *********** nevent = " << nevent << endl;

  if (pmdloader == 0x0)
    {
      cerr<<" ===> Can not find PMD or PMDLoader <===\n";
      delete fRunLoader;
      return 2;
    }

  pmdloader->LoadRecPoints("READ");

  AliCDBManager *man = AliCDBManager::Instance();
  man->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  man->SetRun(0);

  TClonesArray *fRecpoints;
  AliPMDUtility *cc = new AliPMDUtility();

  cc->ApplyAlignment();

  TH2F *h2 = new TH2F("h2"," ",100,-100.,100.,100,-100.,100.);

  FILE *fpw = fopen("junk_rec.dat","w");

  for (Int_t ievt = 0; ievt < nevent; ievt++)
    {
      fRunLoader->GetEvent(ievt);
      TTree *treeR = pmdloader->TreeR();
      if (treeR == 0x0)
	{
	  cout << " Can not get TreeR" << endl;
	  return 3;
	}

      AliPMDrecpoint1  *pmdrecpoint;
      TBranch *branch1 = treeR->GetBranch("PMDRecpoint");
      branch1->SetAddress(&fRecpoints);
      /**********************************************************************
       *    det   : Detector, 0: PRE & 1:CPV                                *
       *    smn   : Serial Module Number from 0 to 23 for both detector     *
       *    xpos  : x-position of the cluster                               *
       *    ypos  : y-position of the cluster                               *
       *            THESE xpos & ypos are not the true xpos and ypos        *
       *            for some of the unit modules. They are rotated.         *
       *    adc   : ADC contained in the cluster                            *
       *    ncell : Number of cells contained in the cluster                *
       *    rad   : radius of the cluster (1d fit)                          *
       *    xpad  : TRUE x-position of the cluster                          *
       *    ypad  : TRUE y-position of the cluster                          *
       **********************************************************************/

      Int_t   det,smn;
      Float_t xpos,ypos, xpad, ypad;
      Float_t adc, ncell, sigx, sigy;
      Float_t xx, yy;
      Int_t   nmodules = branch1->GetEntries();
      cout << " nmodules = " << nmodules << endl;
      for (Int_t imodule = 0; imodule < nmodules; imodule++)
	{
	  branch1->GetEntry(imodule);
	  Int_t nentries = fRecpoints->GetLast();
	  for(Int_t ient = 0; ient < nentries+1; ient++)
	    {
	      pmdrecpoint = (AliPMDrecpoint1*)fRecpoints->UncheckedAt(ient);
	      det   = (Int_t) pmdrecpoint->GetDetector();
	      smn   = (Int_t) pmdrecpoint->GetSMNumber();
	      xpos  = pmdrecpoint->GetClusX();
	      ypos  = pmdrecpoint->GetClusY();
	      adc   = pmdrecpoint->GetClusADC();
	      ncell = pmdrecpoint->GetClusCells();
	      sigx  = pmdrecpoint->GetClusSigmaX();
	      sigy  = pmdrecpoint->GetClusSigmaY();

	      //
	      // User has to plug in his analysis code here
	      //

	      fprintf(fpw,"%d %d %d %d\n",
		      det,smn,xpos,ypos);
	      //
	      // Plot the cluster centroid to see the PMD geometry
	      // using the PMD Utility class
	      //
	      if (det == 1)
		{
		  // Draw only for PRE plane
		  cc->RectGeomCellPos(smn,xpos,ypos,xx,yy);
		  h2->Fill(xx,yy);
		}

	      //
	      // End of the User code
	      //
	    }
	}

    }

  h2->Draw();

  fclose(fpw);
  return 0;
}

<|endoftext|>


<commit_before>#include "player.h"
#include "subjectblock.h"
#include "types.h"
#include <iostream>
#include <algorithm>
#include <QDebug>
#include "board.h"
#include <QtGlobal>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#define NUMBER_OF_BLOCKS 32
#define NEXT_POS(current_pos) ((current_pos + 1) % 32)

using namespace std;

Player::Player(QGameItem* parent,int _id) : QGameItem(parent)
{
    id = _id;
    name = "";
    position = 0;
    energy = 0;
    bankrupt = false;
    mobile = true;
    penalty = 0;
    plural = false;
    character_type = CharacterType::NONE;

    //initialize map
    using namespace SubjectType;
    registered[BIO] = 0;
    registered[CHEM] = 0;
    registered[CSED] = 0;
    registered[EE] = 0;
    registered[MATH] = 0;
    registered[ME] = 0;
    registered[IME] = 0;
    registered[PHYS] = 0;

    // end initialize
    qDebug() << "Player Created" << endl;
}

Player::~Player()
{
    //delete own_blocks;

    qDebug() << "Player Destroyed" << endl;
}

// Accessor Methods
int Player::getPosition() const
{
    return position;
}

bool Player::isBankrupt() const
{
    return bankrupt;
}

bool Player::isMobile() const
{
    return mobile;
}

int Player::getEnergy() const
{
    return energy;
}

int Player::getPenalty() const
{
    return penalty;
}

bool Player::isPlural() const
{
    return plural;
}

CharacterType::Type Player::getType() const
{
    return character_type;
}

list<Block*> Player::getBlocks() const
{
    return own_blocks;
}

// Methods
void Player::setEnergy(int energy)
{
    this->energy = energy;
}

void Player::setPlural(bool plural)
{
    this->plural = plural;
}

void Player::setBankrupt()
{
    bankrupt = true;
}

// set player to stay mouindo
// parm: how long to stay in mouindo
void Player::setMouindo(int panelty)
{
    this->penalty = panelty;
    mobile = false;
}

// check player escaped or not
bool Player::escapeMouindo()
{
    if(mobile)
        return true;

    else {

        if(penalty == 0) {
            mobile = true;
            return true;
        }

        else {
            // roll a dice
            penalty--;
            return false;

        }
    }
}

void Player::walkBy(int steps)
{
    using namespace BlockCoords;
    const int step_interval = 300; //0.1 seconds
    int current_pos = position;
    int next_pos;

    QSequentialAnimationGroup * seq_animation_group
            = new QSequentialAnimationGroup;

    //add sleep animation
    QPropertyAnimation * sleep
            = new QPropertyAnimation(this,"pos");
    sleep->setDuration(1800);
    //don't move
    sleep->setStartValue(block_coord[current_pos]);
    sleep->setEndValue(block_coord[current_pos]);
    seq_animation_group->addAnimation(sleep);

    while(steps){
        next_pos = NEXT_POS(current_pos);
        QPropertyAnimation * step_animation
                = new QPropertyAnimation(this,"pos");
        step_animation->setDuration(step_interval);
        step_animation->setStartValue(block_coord[current_pos]);
        step_animation->setEndValue(block_coord[next_pos]);
        step_animation->setEasingCurve(QEasingCurve::InOutQuint);
        seq_animation_group->addAnimation(step_animation);
        steps--; //decrease one step
        current_pos = next_pos;
        if(current_pos == 0){
            //maybe add animation for gaining energy
            giveSalary();
        }
    }
    seq_animation_group->start(QAbstractAnimation::DeleteWhenStopped);
    position = current_pos;
}

void Player::jumpTo(int block_num){
    using namespace BlockCoords;
    QPointF target = block_coord[block_num];
    animateTo(target.x(),target.y(),2000);
    position = block_num;

}

bool Player::hasBlock(Block* block)
{
    // subject block check
    if(block->getType() != BlockType::SUBJECT) {
        qDebug() << "This is not a Subject Block!";
        return false;
    }

    list<Block*>::iterator finder = own_blocks.end();
    finder = find(own_blocks.begin(), own_blocks.end(), block);

    // no matching
    if(finder == own_blocks.end())
        return false;
    else
        return true;
}

void Player::addBlock(Block *block)
{
    if(!hasBlock(block)) {
        qDebug() << "You don't have that block. Check Again!";
        return;
    }

    registered.find(((SubjectBlock*)block)->getDept())->second++;
    own_blocks.push_back(block);
}

void Player::removeBlock(Block *block)
{
    if(!hasBlock(block)) {
        qDebug() << "You don't have that block. Check Again!";
        return;
    }

    registered.find(((SubjectBlock*)block)->getDept())->second--;
    own_blocks.remove(block);
}

void Player::giveSalary()
{
    if(character_type == CharacterType::HARD_WORKER)
        energy += 150;
    else
        energy += 100;
}

bool Player::checkWinStatus()
{
    int majored = 0;

    for(map<SubjectType::Type, int>::iterator i = registered.begin(); i != registered.end(); i++) {
        if(i->second == 3)
            majored ++;
    }

    if(plural && majored >= 2)
        return true;
    else if (!plural && majored >= 1)
        return true;
    else
        return false;
}

void Player::payEnergy(int payenergy)
{
    energy-=payenergy;

}
void Player::giveEnergy(int paidenergy){
    energy+=paidenergy;

}

int Player::getId() const {
    return id;
}

void Player::setType(CharacterType::Type type) {
    character_type = type;
}

int Player::getAssetValue() const {

}

<commit_msg>Player: Added return value<commit_after>#include "player.h"
#include "subjectblock.h"
#include "types.h"
#include <iostream>
#include <algorithm>
#include <QDebug>
#include "board.h"
#include <QtGlobal>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#define NUMBER_OF_BLOCKS 32
#define NEXT_POS(current_pos) ((current_pos + 1) % 32)

using namespace std;

Player::Player(QGameItem* parent,int _id) : QGameItem(parent)
{
    id = _id;
    name = "";
    position = 0;
    energy = 0;
    bankrupt = false;
    mobile = true;
    penalty = 0;
    plural = false;
    character_type = CharacterType::NONE;

    //initialize map
    using namespace SubjectType;
    registered[BIO] = 0;
    registered[CHEM] = 0;
    registered[CSED] = 0;
    registered[EE] = 0;
    registered[MATH] = 0;
    registered[ME] = 0;
    registered[IME] = 0;
    registered[PHYS] = 0;

    // end initialize
    qDebug() << "Player Created" << endl;
}

Player::~Player()
{
    //delete own_blocks;

    qDebug() << "Player Destroyed" << endl;
}

// Accessor Methods
int Player::getPosition() const
{
    return position;
}

bool Player::isBankrupt() const
{
    return bankrupt;
}

bool Player::isMobile() const
{
    return mobile;
}

int Player::getEnergy() const
{
    return energy;
}

int Player::getPenalty() const
{
    return penalty;
}

bool Player::isPlural() const
{
    return plural;
}

CharacterType::Type Player::getType() const
{
    return character_type;
}

list<Block*> Player::getBlocks() const
{
    return own_blocks;
}

// Methods
void Player::setEnergy(int energy)
{
    this->energy = energy;
}

void Player::setPlural(bool plural)
{
    this->plural = plural;
}

void Player::setBankrupt()
{
    bankrupt = true;
}

// set player to stay mouindo
// parm: how long to stay in mouindo
void Player::setMouindo(int panelty)
{
    this->penalty = panelty;
    mobile = false;
}

// check player escaped or not
bool Player::escapeMouindo()
{
    if(mobile)
        return true;

    else {

        if(penalty == 0) {
            mobile = true;
            return true;
        }

        else {
            // roll a dice
            penalty--;
            return false;

        }
    }
}

void Player::walkBy(int steps)
{
    using namespace BlockCoords;
    const int step_interval = 300; //0.1 seconds
    int current_pos = position;
    int next_pos;

    QSequentialAnimationGroup * seq_animation_group
            = new QSequentialAnimationGroup;

    //add sleep animation
    QPropertyAnimation * sleep
            = new QPropertyAnimation(this,"pos");
    sleep->setDuration(1800);
    //don't move
    sleep->setStartValue(block_coord[current_pos]);
    sleep->setEndValue(block_coord[current_pos]);
    seq_animation_group->addAnimation(sleep);

    while(steps){
        next_pos = NEXT_POS(current_pos);
        QPropertyAnimation * step_animation
                = new QPropertyAnimation(this,"pos");
        step_animation->setDuration(step_interval);
        step_animation->setStartValue(block_coord[current_pos]);
        step_animation->setEndValue(block_coord[next_pos]);
        step_animation->setEasingCurve(QEasingCurve::InOutQuint);
        seq_animation_group->addAnimation(step_animation);
        steps--; //decrease one step
        current_pos = next_pos;
        if(current_pos == 0){
            //maybe add animation for gaining energy
            giveSalary();
        }
    }
    seq_animation_group->start(QAbstractAnimation::DeleteWhenStopped);
    position = current_pos;
}

void Player::jumpTo(int block_num){
    using namespace BlockCoords;
    QPointF target = block_coord[block_num];
    animateTo(target.x(),target.y(),2000);
    position = block_num;

}

bool Player::hasBlock(Block* block)
{
    // subject block check
    if(block->getType() != BlockType::SUBJECT) {
        qDebug() << "This is not a Subject Block!";
        return false;
    }

    list<Block*>::iterator finder = own_blocks.end();
    finder = find(own_blocks.begin(), own_blocks.end(), block);

    // no matching
    if(finder == own_blocks.end())
        return false;
    else
        return true;
}

void Player::addBlock(Block *block)
{
    if(!hasBlock(block)) {
        qDebug() << "You don't have that block. Check Again!";
        return;
    }

    registered.find(((SubjectBlock*)block)->getDept())->second++;
    own_blocks.push_back(block);
}

void Player::removeBlock(Block *block)
{
    if(!hasBlock(block)) {
        qDebug() << "You don't have that block. Check Again!";
        return;
    }

    registered.find(((SubjectBlock*)block)->getDept())->second--;
    own_blocks.remove(block);
}

void Player::giveSalary()
{
    if(character_type == CharacterType::HARD_WORKER)
        energy += 150;
    else
        energy += 100;
}

bool Player::checkWinStatus()
{
    int majored = 0;

    for(map<SubjectType::Type, int>::iterator i = registered.begin(); i != registered.end(); i++) {
        if(i->second == 3)
            majored ++;
    }

    if(plural && majored >= 2)
        return true;
    else if (!plural && majored >= 1)
        return true;
    else
        return false;
}

void Player::payEnergy(int payenergy)
{
    energy-=payenergy;

}
void Player::giveEnergy(int paidenergy){
    energy+=paidenergy;

}

int Player::getId() const {
    return id;
}

void Player::setType(CharacterType::Type type) {
    character_type = type;
}

int Player::getAssetValue() const {
    return 0;
}

<|endoftext|>