<commit_before>#include <iostream>
#include <cstdlib>
#include <cassert>
#include "MeshPartReader.h"
#include "StringUtils.h"

using namespace std;
using namespace cigma;

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

MeshPartReader::MeshPartReader()
{
    meshPart = 0;
    meshReader = 0;
    coordsReader = 0;
    connectReader = 0;
}

MeshPartReader::~MeshPartReader()
{
    if (meshPart != 0)
    {
        if (meshPart->coords != 0)
        {
            delete [] meshPart->coords;
            meshPart->coords = 0;
        }

        if (meshPart->connect != 0)
        {
            delete [] meshPart->connect;
            meshPart->connect = 0;
        }

        delete meshPart;
        meshPart = 0;
    }
}

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

void MeshPartReader::load_args(AnyOption *opt, const char *opt_prefix)
{
    assert(opt != 0);

    char *in;
    string optstr;
    string mesh_name = opt_prefix;

    in = opt->getValue(mesh_name.c_str());
    if (in != 0)
    {
        this->meshPath = in;
    }

    optstr = mesh_name + "-coordinates";
    in = opt->getValue(optstr.c_str());
    if (in != 0)
    {
        this->coordsPath = in;
    }

    optstr = mesh_name + "-connectivity";
    in = opt->getValue(optstr.c_str());
    if (in != 0)
    {
        this->connectPath = in;
    }
}

void MeshPartReader::validate_args(const char *cmd_name)
{
    if (has_paths())
    {
        if (meshPath == "")
        {
            if (coordsPath == "")
            {
                cerr << cmd_name
                     << ": Detected missing option --mesh-coordinates"
                     << endl;
                exit(1);
            }
            if (connectPath == "")
            {
                cerr << cmd_name
                     << ": Detected missing option --mesh-connectivity"
                     << endl;
                exit(1);
            }
        }
    }
}

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

bool MeshPartReader::has_paths()
{
    return (meshPath != "") || (coordsPath != "") || (connectPath != "");
}

bool MeshPartReader::has_coords_path()
{
    return (meshPath != "") || (coordsPath != "");
}

bool MeshPartReader::has_connect_path()
{
    return (meshPath != "") || (connectPath != "");
}

bool MeshPartReader::has_valid_paths()
{
    // empty state is valid
    if (!has_paths())
    {
        return true;
    }

    // require both coords and connect paths if mesh path is absent
    return (meshPath != "") || ((coordsPath != "") && (connectPath != ""));
}

bool MeshPartReader::prepare_paths()
{
    // This function initializes the required variables used in load_mesh()
    //
    //  precondition: all path variables need to be set
    //                appropriately by calling load_args()
    //
    //  postcondition: if successful, location & file variables
    //                 will be ready for use in load_mesh()

    if (!(has_coords_path() && has_connect_path()))
    {
        // not enough information available to set location variables.
        // top level program should use validate_args() to detect this
        // condition ahead of time and bail out
        return false;
    }

    //
    // Note that each of coordsPath and connectPath will override
    // the corresponding component in meshPath
    //
    if (coordsPath != "")
    {
        parse_dataset_path(coordsPath, coordsLoc, coordsFile, coordsExt);
    }
    if (connectPath != "")
    {
        parse_dataset_path(connectPath, connectLoc, connectFile, connectExt);
    }
    if (meshPath != "")
    {
        parse_dataset_path(meshPath, meshLoc, meshFile, meshExt);

        if (coordsPath == "")
        {
            // no coords path was specified...
            // read coordinates from mesh file
            // coordsLoc will have to be determine later in load_mesh()
            coordsLoc  = "";
            coordsFile = meshFile;
            coordsExt  = meshExt;
        }
        else
        {
            if (coordsLoc == "")
            {
                // reinterpret the meaning of --mesh-coordinates
                coordsLoc  = coordsFile;
                coordsFile = meshFile;
                coordsExt  = meshExt;
            }
        }

        if (connectPath == "")
        {
            // no connect path specified...
            // read connectivity from mesh file
            // connectLoc will have to be determined later in load_mesh()
            connectLoc  = "";
            connectFile = meshFile;
            connectExt  = meshExt;
        }
        else
        {
            // reintepret the meaning of --mesh-connectivity
            connectLoc  = connectFile;
            connectFile = meshFile;
            connectExt  = meshExt;
        }
    }

    return true;
}

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

void MeshPartReader::load_mesh()
{
    //
    // This function initializes the meshPart member variable.
    // Failure can be detected by checking whether meshPart is 0.
    //

    // Nothing to do if paths are empty
    if (!has_paths())
    {
        return;
    }

    bool ready = prepare_paths();
    if (!ready)
    {
        return;
    }

    //
    // Local declarations
    //
    int ierr;
    int nno, nsd;
    double *coords = 0;
    int nel, ndofs;
    int *connect = 0;

    nno = nsd = 0;
    nel = ndofs = 0;

    //
    // Instantiate readers
    //
    if (meshFile != "")
    {
        meshReader = NewReader(meshExt.c_str());
    }
    if (coordsFile != "")
    {
        if (coordsFile == meshFile)
        {
            coordsReader = meshReader;
        }
        else
        {
            coordsReader = NewReader(coordsExt.c_str());
        }
    }
    if (connectFile != "")
    {
        if (connectFile == meshFile)
        {
            connectReader = meshReader;
        }
        else
        {
            connectReader = NewReader(connectExt.c_str());
        }
    }
    if (coordsReader == 0)
    {
        cerr << "Could not make reader for mesh coordinates" << endl;
        exit(1);
    }
    if (connectReader == 0)
    {
        cerr << "Could not make reader for mesh connectivity" << endl;
        exit(1);
    }

    //
    // Open files
    //
    if (meshReader != 0)
    {
        ierr = meshReader->open(meshFile.c_str());
        if (ierr < 0)
        {
            cerr << "Could not open mesh file " << meshFile << endl;
            exit(1);
        }
    }
    if (coordsReader != meshReader)
    {
        ierr = coordsReader->open(coordsFile.c_str());
        if (ierr < 0)
        {
            cerr << "Could not open mesh-coordinates file " << coordsFile << endl;
            exit(1);
        }
    }
    if (connectReader != meshReader)
    {
        ierr = connectReader->open(connectFile.c_str());
        if (ierr < 0)
        {
            cerr << "Could not open mesh-connectivity file " << connectFile << endl;
            exit(1);
        }
    }

    //
    // Last chance to determine coordsLoc and connectLoc.
    // For HDF5 files, check dataset or attribute first?
    // Also, if meshLoc is empty, does it *have* to be "/"?
    //
    if (coordsLoc == "")
    {
        if (coordsReader->getType() == Reader::HDF_READER)
        {
            coordsLoc = meshLoc + "/coordinates";
            // If at this point, the coordsLoc dataset doesn't exist,
            // then determine the following before bailing out:
            //  * assert that meshLoc is a group
            //  * the group meshLoc has a Coordinates string attribute
            //  * load the Coordinates attribute into coordsLoc variable
        }
    }
    if (connectLoc == "")
    {
        if (connectReader->getType() == Reader::HDF_READER)
        {
            connectLoc = meshLoc + "/connectivity";
            // If at this point, the connectLoc dataset doesn't exist,
            // determine the following before bailing out:
            //  * assert that meshLoc is a group
            //  * the group meshLoc has a Connectivity string attribute
            //  * load the Connectivity string attribute into connectLoc
        }
    }

    //
    // Read datasets
    //
    ierr = coordsReader->get_coordinates(coordsLoc.c_str(), &coords, &nno, &nsd);
    if (ierr < 0)
    {
        cerr << "Error: Could not read mesh coordinates!" << endl;
        exit(2);
    }
    assert(coords != 0);

    ierr = connectReader->get_connectivity(connectLoc.c_str(), &connect, &nel, &ndofs);
    if (ierr < 0)
    {
        cerr << "Error: Could not read mesh connectivity!" << endl;
        exit(2);
    }
    assert(connect != 0);

    if ((coords != 0) && (connect != 0))
    {
        meshPart = new MeshPart();

        meshPart->nno = nno;
        meshPart->nsd = nsd;
        meshPart->coords = coords;

        meshPart->nel = nel;
        meshPart->ndofs = ndofs;
        meshPart->connect = connect;
    }

}

// ---------------------------------------------------------------------------
<commit_msg>Updated error msgs (option prefix can change, as it does in CompareCmd)<commit_after>#include <iostream>
#include <cstdlib>
#include <cassert>
#include "MeshPartReader.h"
#include "StringUtils.h"

using namespace std;
using namespace cigma;

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

MeshPartReader::MeshPartReader()
{
    meshPart = 0;
    meshReader = 0;
    coordsReader = 0;
    connectReader = 0;
}

MeshPartReader::~MeshPartReader()
{
    if (meshPart != 0)
    {
        if (meshPart->coords != 0)
        {
            delete [] meshPart->coords;
            meshPart->coords = 0;
        }

        if (meshPart->connect != 0)
        {
            delete [] meshPart->connect;
            meshPart->connect = 0;
        }

        delete meshPart;
        meshPart = 0;
    }
}

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

void MeshPartReader::load_args(AnyOption *opt, const char *opt_prefix)
{
    assert(opt != 0);

    char *in;
    string optstr;
    string mesh_name = opt_prefix;

    in = opt->getValue(mesh_name.c_str());
    if (in != 0)
    {
        this->meshPath = in;
    }

    optstr = mesh_name + "-coordinates";
    in = opt->getValue(optstr.c_str());
    if (in != 0)
    {
        this->coordsPath = in;
    }

    optstr = mesh_name + "-connectivity";
    in = opt->getValue(optstr.c_str());
    if (in != 0)
    {
        this->connectPath = in;
    }
}

void MeshPartReader::validate_args(const char *cmd_name)
{
    if (has_paths())
    {
        if (meshPath == "")
        {
            if (coordsPath == "")
            {
                cerr << cmd_name
                     << ": Missing mesh coordinates option"
                     << endl;
                exit(1);
            }
            if (connectPath == "")
            {
                cerr << cmd_name
                     << ": Missing mesh connectivity option"
                     << endl;
                exit(1);
            }
        }
    }
}

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

bool MeshPartReader::has_paths()
{
    return (meshPath != "") || (coordsPath != "") || (connectPath != "");
}

bool MeshPartReader::has_coords_path()
{
    return (meshPath != "") || (coordsPath != "");
}

bool MeshPartReader::has_connect_path()
{
    return (meshPath != "") || (connectPath != "");
}

bool MeshPartReader::has_valid_paths()
{
    // empty state is valid
    if (!has_paths())
    {
        return true;
    }

    // require both coords and connect paths if mesh path is absent
    return (meshPath != "") || ((coordsPath != "") && (connectPath != ""));
}

bool MeshPartReader::prepare_paths()
{
    // This function initializes the required variables used in load_mesh()
    //
    //  precondition: all path variables need to be set
    //                appropriately by calling load_args()
    //
    //  postcondition: if successful, location & file variables
    //                 will be ready for use in load_mesh()

    if (!(has_coords_path() && has_connect_path()))
    {
        // not enough information available to set location variables.
        // top level program should use validate_args() to detect this
        // condition ahead of time and bail out
        return false;
    }

    //
    // Note that each of coordsPath and connectPath will override
    // the corresponding component in meshPath
    //
    if (coordsPath != "")
    {
        parse_dataset_path(coordsPath, coordsLoc, coordsFile, coordsExt);
    }
    if (connectPath != "")
    {
        parse_dataset_path(connectPath, connectLoc, connectFile, connectExt);
    }
    if (meshPath != "")
    {
        parse_dataset_path(meshPath, meshLoc, meshFile, meshExt);

        if (coordsPath == "")
        {
            // no coords path was specified...
            // read coordinates from mesh file
            // coordsLoc will have to be determine later in load_mesh()
            coordsLoc  = "";
            coordsFile = meshFile;
            coordsExt  = meshExt;
        }
        else
        {
            if (coordsLoc == "")
            {
                // reinterpret the meaning of --mesh-coordinates
                coordsLoc  = coordsFile;
                coordsFile = meshFile;
                coordsExt  = meshExt;
            }
        }

        if (connectPath == "")
        {
            // no connect path specified...
            // read connectivity from mesh file
            // connectLoc will have to be determined later in load_mesh()
            connectLoc  = "";
            connectFile = meshFile;
            connectExt  = meshExt;
        }
        else
        {
            // reintepret the meaning of --mesh-connectivity
            connectLoc  = connectFile;
            connectFile = meshFile;
            connectExt  = meshExt;
        }
    }

    return true;
}

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

void MeshPartReader::load_mesh()
{
    //
    // This function initializes the meshPart member variable.
    // Failure can be detected by checking whether meshPart is 0.
    //

    // Nothing to do if paths are empty
    if (!has_paths())
    {
        return;
    }

    bool ready = prepare_paths();
    if (!ready)
    {
        return;
    }

    //
    // Local declarations
    //
    int ierr;
    int nno, nsd;
    double *coords = 0;
    int nel, ndofs;
    int *connect = 0;

    nno = nsd = 0;
    nel = ndofs = 0;

    //
    // Instantiate readers
    //
    if (meshFile != "")
    {
        meshReader = NewReader(meshExt.c_str());
    }
    if (coordsFile != "")
    {
        if (coordsFile == meshFile)
        {
            coordsReader = meshReader;
        }
        else
        {
            coordsReader = NewReader(coordsExt.c_str());
        }
    }
    if (connectFile != "")
    {
        if (connectFile == meshFile)
        {
            connectReader = meshReader;
        }
        else
        {
            connectReader = NewReader(connectExt.c_str());
        }
    }
    if (coordsReader == 0)
    {
        cerr << "Could not make reader for mesh coordinates" << endl;
        exit(1);
    }
    if (connectReader == 0)
    {
        cerr << "Could not make reader for mesh connectivity" << endl;
        exit(1);
    }

    //
    // Open files
    //
    if (meshReader != 0)
    {
        ierr = meshReader->open(meshFile.c_str());
        if (ierr < 0)
        {
            cerr << "Could not open mesh file " << meshFile << endl;
            exit(1);
        }
    }
    if (coordsReader != meshReader)
    {
        ierr = coordsReader->open(coordsFile.c_str());
        if (ierr < 0)
        {
            cerr << "Could not open mesh-coordinates file " << coordsFile << endl;
            exit(1);
        }
    }
    if (connectReader != meshReader)
    {
        ierr = connectReader->open(connectFile.c_str());
        if (ierr < 0)
        {
            cerr << "Could not open mesh-connectivity file " << connectFile << endl;
            exit(1);
        }
    }

    //
    // Last chance to determine coordsLoc and connectLoc.
    // For HDF5 files, check dataset or attribute first?
    // Also, if meshLoc is empty, does it *have* to be "/"?
    //
    if (coordsLoc == "")
    {
        if (coordsReader->getType() == Reader::HDF_READER)
        {
            coordsLoc = meshLoc + "/coordinates";
            // If at this point, the coordsLoc dataset doesn't exist,
            // then determine the following before bailing out:
            //  * assert that meshLoc is a group
            //  * the group meshLoc has a Coordinates string attribute
            //  * load the Coordinates attribute into coordsLoc variable
        }
    }
    if (connectLoc == "")
    {
        if (connectReader->getType() == Reader::HDF_READER)
        {
            connectLoc = meshLoc + "/connectivity";
            // If at this point, the connectLoc dataset doesn't exist,
            // determine the following before bailing out:
            //  * assert that meshLoc is a group
            //  * the group meshLoc has a Connectivity string attribute
            //  * load the Connectivity string attribute into connectLoc
        }
    }

    //
    // Read datasets
    //
    ierr = coordsReader->get_coordinates(coordsLoc.c_str(), &coords, &nno, &nsd);
    if (ierr < 0)
    {
        cerr << "Error: Could not read mesh coordinates!" << endl;
        exit(2);
    }
    assert(coords != 0);

    ierr = connectReader->get_connectivity(connectLoc.c_str(), &connect, &nel, &ndofs);
    if (ierr < 0)
    {
        cerr << "Error: Could not read mesh connectivity!" << endl;
        exit(2);
    }
    assert(connect != 0);

    if ((coords != 0) && (connect != 0))
    {
        meshPart = new MeshPart();

        meshPart->nno = nno;
        meshPart->nsd = nsd;
        meshPart->coords = coords;

        meshPart->nel = nel;
        meshPart->ndofs = ndofs;
        meshPart->connect = connect;
    }

}

// ---------------------------------------------------------------------------
<|endoftext|>


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

#include "pch.h"
#include <handlers.hpp>
#include <utils.hpp>
#include <http.hpp>
#include <feed_parser.hpp>
#include "api_handler.hpp"

namespace FastCGI { namespace app { namespace api
{
	template <typename Container, typename Pred>
	void for_each(Request& request, const Container& cont, const std::string& join, Pred pred)
	{
		bool first = true;
		auto from = cont.begin(), to = cont.end();
		for (; from != to; ++from)
		{
			if (first) first = false;
			else request << join;
			pred(request, *from);
		}
	}

	std::string escape(const std::string& in)
	{
		if (in.empty())
			return "null";

		std::string out;
		out.reserve(in.length() * 110 / 100);
		out.push_back('"');
		std::for_each(in.begin(), in.end(), [&out](char c)
		{
			switch(c)
			{
			case '"': out += "\\\""; break;
			case '\\': out += "\\\\"; break;
			case '/': out += "\\/"; break;
			case '\b': out += "\\b"; break;
			case '\f': out += "\\f"; break;
			case '\n': out += "\\n"; break;
			case '\r': out += "\\r"; break;
			case '\t': out += "\\t"; break;
			default:
				//unicode charcters...
				out.push_back(c);
			}
		});
		out.push_back('"');
		return out;
	}

	class Subscribe: public APIOperation
	{
	public:
		void render(SessionPtr session, Request& request, PageTranslation& tr)
		{
#if 1
			long long feed_id = 0;
			std::string error;
			param_t url = request.getVariable("url");
			if (!url) error = tr(lng::LNG_URL_MISSING);
			else
			{
				db::ConnectionPtr db = request.dbConn();
				feed_id = session->subscribe(db, url);
				if (feed_id < 0)
				{
					switch(feed_id)
					{
					case SERR_INTERNAL_ERROR: request.on500();
					case SERR_4xx_ANSWER:   error = tr(lng::LNG_FEED_FAILED); break;
					case SERR_5xx_ANSWER:   error = tr(lng::LNG_FEED_SERVER_FAILED); break;
					case SERR_OTHER_ANSWER: error = tr(lng::LNG_FEED_ERROR); break;
					case SERR_NOT_A_FEED:   error = tr(lng::LNG_NOT_A_FEED); break;
					}
				}
			}

			long long folder_id = 0;
			long ord = 0;
			if (error.empty())
			{
				db::ConnectionPtr db = request.dbConn();
				auto select = db->prepare("SELECT folder_id, ord FROM subscription WHERE feed_id=? AND folder_id IN (SELECT _id FROM folder WHERE user_id=?)");
				if (!select) request.on500();
				if (!select->bind(0, feed_id)) request.on500();
				if (!select->bind(1, session->getId())) request.on500();

				auto c = select->query();
				if (!c || !c->next()) request.on500();

				folder_id = c->getLongLong(0);
				ord = c->getLong(1);
			}

			request.setHeader("Content-Type", "application/json; charset=utf-8");

			if (!error.empty())
			{
				request.setHeader("Status", "400 Bad Request");
				request << "{\"error\":" << escape(error);
				if (url) request << ",\"url\":" << escape(url);
				request << "}";
				request.die();
			}

			request << "{\"feed\":" << feed_id << ",\"folder\":" << folder_id << ",\"position\":" << ord << "}";
#else
			auto xhr = http::XmlHttpRequest::Create();
			if (!xhr)
				request.on500();

			request.setHeader("Content-Type", "application/json; charset=utf-8");

			std::string error;
			param_t url = request.getVariable("url");
			if (!url) error = tr(lng::LNG_URL_MISSING);

			dom::XmlDocumentPtr doc;

			if (url)
			{
				xhr->open(http::HTTP_GET, url, false);
				xhr->send();

				int issue = xhr->getStatus() / 100;
				if (issue == 4)      error = tr(lng::LNG_FEED_FAILED);
				else if (issue == 5) error = tr(lng::LNG_FEED_SERVER_FAILED);
				else if (issue != 2) error = tr(lng::LNG_FEED_ERROR);

				if (error.empty())
					doc = xhr->getResponseXml();
			}

			feed::Feed feed;
			if (error.empty() && (!doc || !feed::parse(doc, feed)))
				error = tr(lng::LNG_NOT_A_FEED);

			if (!error.empty())
			{
				request.setHeader("Status", "400 Bad Request");
				request << "{\"error\":" << escape(error); if (url) request << ",\"url\":" << escape(url); request << "}";
				request.die();
			}

			request <<
				"{\"id\":123456789"
				<< ",\"title\":" << escape(feed.m_feed.m_title)
				<< ",\"feed\":" << escape(url)
				<< ",\"site\":" << escape(feed.m_feed.m_url)
				<< ",\"description\":" << escape(feed.m_description)
				<< ",\"categories\":["
				;
			for_each(request, feed.m_categories, ",", [](Request& request, const std::string& cat) { request << escape(cat); });

			request << "],\"entries\":[";
			for_each(request, feed.m_entry, ",", [](Request& request, const feed::Entry& entry)
			{
				request <<
					"{\"id\":123456789"
					<< ",\"title\":" << escape(entry.m_entry.m_title)
					<< ",\"link\":" << escape(entry.m_entry.m_url)
					<< ",\"author\":" << escape(entry.m_author.m_name)
					<< ",\"authorLink\":" << escape("mailto:" + entry.m_author.m_email)
					<< ",\"description\":" << escape(entry.m_description)
					<< ",\"date\":" << entry.m_dateTime
					<< ",\"enclosures\":[";
				for_each(request, entry.m_enclosures, ",", [](Request& request, const feed::Enclosure& enclosure)
				{
					request << "{\"url\":" << escape(enclosure.m_url) << ",\"mime\":" << escape(enclosure.m_type) << ",\"length\":" << enclosure.m_size << "}";
				});
				request
					<< "],\"categories\":[";
				for_each(request, entry.m_categories, ",", [](Request& request, const std::string& cat) { request << escape(cat); });
				request << "],\"content\":" << escape(entry.m_content) << "}";
			});
			request << "]}";
#endif
		}

		const char** getVariables() const
		{
			static const char* vars[] = { "url", nullptr };
			return vars;
		}
	};

}}}

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

#include "pch.h"
#include <handlers.hpp>
#include <utils.hpp>
#include <http.hpp>
#include <feed_parser.hpp>
#include "api_handler.hpp"
#include "json.hpp"

namespace FastCGI { namespace app { namespace api
{
	struct JsonError
	{
		std::string error;
		const char* url;
	};

	struct SubscribeAnswer
	{
		long long feed;
		long long folder;
		int position;
		SubscribeAnswer(): feed(0), folder(0), position(0) {}
	};
}}}

namespace json
{
	JSON_RULE(FastCGI::app::api::JsonError)
	{
		JSON_ADD(error);
		JSON_ADD(url);
	}

	JSON_RULE(FastCGI::app::api::SubscribeAnswer)
	{
		JSON_ADD(feed);
		JSON_ADD(folder);
		JSON_ADD(position);
	}
};

namespace FastCGI { namespace app { namespace api
{
	template <typename Container, typename Pred>
	void for_each(Request& request, const Container& cont, const std::string& join, Pred pred)
	{
		bool first = true;
		auto from = cont.begin(), to = cont.end();
		for (; from != to; ++from)
		{
			if (first) first = false;
			else request << join;
			pred(request, *from);
		}
	}

	class Subscribe: public APIOperation
	{
	public:
		void render(SessionPtr session, Request& request, PageTranslation& tr)
		{
#if 1
			SubscribeAnswer answer;
			JsonError err;
			param_t url = request.getVariable("url");
			if (!url) err.error = tr(lng::LNG_URL_MISSING);
			else
			{
				db::ConnectionPtr db = request.dbConn();
				answer.feed = session->subscribe(db, url);
				if (answer.feed < 0)
				{
					switch(answer.feed)
					{
					case SERR_INTERNAL_ERROR: request.on500();
					case SERR_4xx_ANSWER:   err.error = tr(lng::LNG_FEED_FAILED); break;
					case SERR_5xx_ANSWER:   err.error = tr(lng::LNG_FEED_SERVER_FAILED); break;
					case SERR_OTHER_ANSWER: err.error = tr(lng::LNG_FEED_ERROR); break;
					case SERR_NOT_A_FEED:   err.error = tr(lng::LNG_NOT_A_FEED); break;
					}
				}
			}

			if (err.error.empty())
			{
				db::ConnectionPtr db = request.dbConn();
				auto select = db->prepare("SELECT folder_id, ord FROM subscription WHERE feed_id=? AND folder_id IN (SELECT _id FROM folder WHERE user_id=?)");
				if (!select) request.on500();
				if (!select->bind(0, answer.feed)) request.on500();
				if (!select->bind(1, session->getId())) request.on500();

				auto c = select->query();
				if (!c || !c->next()) request.on500();

				answer.folder = c->getLongLong(0);
				answer.position = c->getLong(1);
			}

			request.setHeader("Content-Type", "application/json; charset=utf-8");

			if (!err.error.empty())
			{
				err.url = url;
				request.setHeader("Status", "400 Bad Request");
				json::render(request, err);
				request.die();
			}

			json::render(request, answer);
#else
			auto xhr = http::XmlHttpRequest::Create();
			if (!xhr)
				request.on500();

			request.setHeader("Content-Type", "application/json; charset=utf-8");

			std::string error;
			param_t url = request.getVariable("url");
			if (!url) error = tr(lng::LNG_URL_MISSING);

			dom::XmlDocumentPtr doc;

			if (url)
			{
				xhr->open(http::HTTP_GET, url, false);
				xhr->send();

				int issue = xhr->getStatus() / 100;
				if (issue == 4)      error = tr(lng::LNG_FEED_FAILED);
				else if (issue == 5) error = tr(lng::LNG_FEED_SERVER_FAILED);
				else if (issue != 2) error = tr(lng::LNG_FEED_ERROR);

				if (error.empty())
					doc = xhr->getResponseXml();
			}

			feed::Feed feed;
			if (error.empty() && (!doc || !feed::parse(doc, feed)))
				error = tr(lng::LNG_NOT_A_FEED);

			if (!error.empty())
			{
				request.setHeader("Status", "400 Bad Request");
				request << "{\"error\":" << escape(error); if (url) request << ",\"url\":" << escape(url); request << "}";
				request.die();
			}

			request <<
				"{\"id\":123456789"
				<< ",\"title\":" << escape(feed.m_feed.m_title)
				<< ",\"feed\":" << escape(url)
				<< ",\"site\":" << escape(feed.m_feed.m_url)
				<< ",\"description\":" << escape(feed.m_description)
				<< ",\"categories\":["
				;
			for_each(request, feed.m_categories, ",", [](Request& request, const std::string& cat) { request << escape(cat); });

			request << "],\"entries\":[";
			for_each(request, feed.m_entry, ",", [](Request& request, const feed::Entry& entry)
			{
				request <<
					"{\"id\":123456789"
					<< ",\"title\":" << escape(entry.m_entry.m_title)
					<< ",\"link\":" << escape(entry.m_entry.m_url)
					<< ",\"author\":" << escape(entry.m_author.m_name)
					<< ",\"authorLink\":" << escape("mailto:" + entry.m_author.m_email)
					<< ",\"description\":" << escape(entry.m_description)
					<< ",\"date\":" << entry.m_dateTime
					<< ",\"enclosures\":[";
				for_each(request, entry.m_enclosures, ",", [](Request& request, const feed::Enclosure& enclosure)
				{
					request << "{\"url\":" << escape(enclosure.m_url) << ",\"mime\":" << escape(enclosure.m_type) << ",\"length\":" << enclosure.m_size << "}";
				});
				request
					<< "],\"categories\":[";
				for_each(request, entry.m_categories, ",", [](Request& request, const std::string& cat) { request << escape(cat); });
				request << "],\"content\":" << escape(entry.m_content) << "}";
			});
			request << "]}";
#endif
		}

		const char** getVariables() const
		{
			static const char* vars[] = { "url", nullptr };
			return vars;
		}
	};

}}}

REGISTER_OPERATION("subscribe", FastCGI::app::api::Subscribe);
<|endoftext|>


<commit_before>/**
 * \file SimpleOverdriveFilter.cpp
 */

#include "SimpleOverdriveFilter.h"

#include <boost/math/special_functions/sign.hpp>

#include "../Tools/ScalarNewtonRaphson.h"

namespace ATK
{
  template<typename DataType_>
  class SimpleOverdriveFunction
  {
  public:
    typedef DataType_ DataType;
  protected:
    DataType A;
    DataType B;
    DataType is;
    DataType vt;

    DataType oldy0;
    DataType oldexpy0;
    DataType oldinvexpy0;
    DataType oldy1;
    DataType oldexpy1;
    DataType oldinvexpy1;
  public:
    SimpleOverdriveFunction(DataType dt, DataType R, DataType C, DataType is, DataType vt)
    :is(is), vt(vt)
    {
      A = dt / (2 * C) + R;
      B = dt / (2 * C) - R;

      oldy0 = oldy1 = 0;
      oldexpy0 = oldinvexpy0 = oldexpy1 = oldinvexpy1 = 1;
    }

    std::pair<DataType, DataType> operator()(DataType x0, DataType x1, DataType y0, DataType y1)
    {
      DataType expdiode_y1_p;
      DataType expdiode_y1_m;
      DataType expdiode_y0_p;
      DataType expdiode_y0_m;

      if(y1 == oldy0)
      {
        expdiode_y1_p = oldexpy0;
        expdiode_y1_m = oldinvexpy0;
      }
      else if(y1 == oldy1)
      {
        expdiode_y1_p = oldexpy1;
        expdiode_y1_m = oldinvexpy1;
      }
      else
      {
        expdiode_y1_p = std::exp(y1 / vt);
        expdiode_y1_m = 1 / expdiode_y1_p;
        oldy1 = y1;
        oldexpy1 = expdiode_y1_p;
        oldinvexpy1 = expdiode_y1_m;
      }

      if(y0 == oldy0)
      {
        expdiode_y0_p = oldexpy0;
        expdiode_y0_m = oldinvexpy0;
      }
      else if(y0 == oldy1)
      {
        expdiode_y0_p = oldexpy1;
        expdiode_y0_m = oldinvexpy1;
      }
      else
      {
        expdiode_y0_p = std::exp(y0 / vt);
        expdiode_y0_m = 1 / expdiode_y0_p;
        oldy0 = y0;
        oldexpy0 = expdiode_y0_p;
        oldinvexpy0 = expdiode_y0_m;
      }

      std::pair<DataType, DataType> diode = std::make_pair(is * (expdiode_y1_p - expdiode_y1_m), is * (expdiode_y1_p + expdiode_y1_m) / vt);
      return std::make_pair(A * diode.first + (y1 + (x0 - x1 + B * is * (expdiode_y0_p - expdiode_y0_m) - y0)), A * diode.second + 1);
    }
  };

  template <typename DataType>
  SimpleOverdriveFilter<DataType>::SimpleOverdriveFilter()
  :TypedBaseFilter<DataType>(1, 1)
  {
    optimizer.reset(new ScalarNewtonRaphson<SimpleOverdriveFunction<DataType> >(function));
  }

  template <typename DataType>
  SimpleOverdriveFilter<DataType>::~SimpleOverdriveFilter()
  {
  }

  template <typename DataType>
  void SimpleOverdriveFilter<DataType>::setup()
  {
    Parent::setup();
    function.reset(new SimpleOverdriveFunction<DataType>(1./input_sampling_rate, 10000, 22e-9, 1e-12, 26e-3));
  }

  template <typename DataType>
  void SimpleOverdriveFilter<DataType>::process_impl(long size)
  {
    for(long i = 0; i < size; ++i)
    {
      outputs[0][i] = optimizer->optimize(converted_inputs[0][i]);
    }
  }

  template class SimpleOverdriveFilter<float>;
  template class SimpleOverdriveFilter<double>;
}
<commit_msg>Simplified the exp optimization, don't need that many tricks<commit_after>/**
 * \file SimpleOverdriveFilter.cpp
 */

#include "SimpleOverdriveFilter.h"

#include <boost/math/special_functions/sign.hpp>

#include "../Tools/ScalarNewtonRaphson.h"

namespace ATK
{
  template<typename DataType_>
  class SimpleOverdriveFunction
  {
  public:
    typedef DataType_ DataType;
  protected:
    DataType A;
    DataType B;
    DataType is;
    DataType vt;

    DataType oldy0;
    DataType oldexpy0;
    DataType oldinvexpy0;
    DataType oldy1;
    DataType oldexpy1;
    DataType oldinvexpy1;
  public:
    SimpleOverdriveFunction(DataType dt, DataType R, DataType C, DataType is, DataType vt)
    :is(is), vt(vt)
    {
      A = dt / (2 * C) + R;
      B = dt / (2 * C) - R;

      oldy0 = oldy1 = 0;
      oldexpy0 = oldinvexpy0 = oldexpy1 = oldinvexpy1 = 1;
    }

    std::pair<DataType, DataType> operator()(DataType x0, DataType x1, DataType y0, DataType y1)
    {
      DataType expdiode_y1_p = std::exp(y1 / vt);
      DataType expdiode_y1_m = 1 / expdiode_y1_p;
      DataType expdiode_y0_p;
      DataType expdiode_y0_m;

      if(y0 == oldy0)
      {
        expdiode_y0_p = oldexpy0;
        expdiode_y0_m = oldinvexpy0;
      }
      else if(y0 == oldy1)
      {
        expdiode_y0_p = oldexpy1;
        expdiode_y0_m = oldinvexpy1;
      }
      else
      {
        expdiode_y0_p = std::exp(y0 / vt);
        expdiode_y0_m = 1 / expdiode_y0_p;
        oldy0 = y0;
        oldexpy0 = expdiode_y0_p;
        oldinvexpy0 = expdiode_y0_m;
      }

      oldy1 = y1;
      oldexpy1 = expdiode_y1_p;
      oldinvexpy1 = expdiode_y1_m;

      std::pair<DataType, DataType> diode = std::make_pair(is * (expdiode_y1_p - expdiode_y1_m), is * (expdiode_y1_p + expdiode_y1_m) / vt);
      return std::make_pair(A * diode.first + (y1 + (x0 - x1 + B * is * (expdiode_y0_p - expdiode_y0_m) - y0)), A * diode.second + 1);
    }
  };

  template <typename DataType>
  SimpleOverdriveFilter<DataType>::SimpleOverdriveFilter()
  :TypedBaseFilter<DataType>(1, 1)
  {
    optimizer.reset(new ScalarNewtonRaphson<SimpleOverdriveFunction<DataType> >(function));
  }

  template <typename DataType>
  SimpleOverdriveFilter<DataType>::~SimpleOverdriveFilter()
  {
  }

  template <typename DataType>
  void SimpleOverdriveFilter<DataType>::setup()
  {
    Parent::setup();
    function.reset(new SimpleOverdriveFunction<DataType>(1./input_sampling_rate, 10000, 22e-9, 1e-12, 26e-3));
  }

  template <typename DataType>
  void SimpleOverdriveFilter<DataType>::process_impl(long size)
  {
    for(long i = 0; i < size; ++i)
    {
      outputs[0][i] = optimizer->optimize(converted_inputs[0][i]);
    }
  }

  template class SimpleOverdriveFilter<float>;
  template class SimpleOverdriveFilter<double>;
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <errno.h>
#include <getopt.h>
#include <cstring>
#include <iostream>
#include <cc++/socket.h>
#include "UDPPacket.h"
// --------------------------------------------------------------------------
static struct option longopts[] = {
	{ "help", no_argument, 0, 'h' },
	{ "send", required_argument, 0, 's' },
	{ "receive", required_argument, 0, 'r' },
	{ "proc-id", required_argument, 0, 'p' },
	{ "node-id", required_argument, 0, 'n' },
	{ "send-pause", required_argument, 0, 'x' },
	{ "timeout", required_argument, 0, 't' },
	{ "data-count", required_argument, 0, 'c' },
	{ "disable-broadcast", no_argument, 0, 'b' },
	{ "show-data", no_argument, 0, 'd' },
	{ "check-lost", no_argument, 0, 'l' },
	{ "verbode", required_argument, 0, 'v' },
	{ NULL, 0, 0, 0 }
};
// --------------------------------------------------------------------------
using namespace std;
using namespace UniSetUDP;
// --------------------------------------------------------------------------
enum Command
{
	cmdNOP,
	cmdSend,
	cmdReceive
};
// --------------------------------------------------------------------------
static bool split_addr( const string addr, string& host, ost::tpport_t& port )
{
	string::size_type pos = addr.rfind(':');
	if(  pos != string::npos )
	{
		host = addr.substr(0,pos);
		string s_port(addr.substr(pos+1,addr.size()-1));
		port = UniSetTypes::uni_atoi(s_port.c_str());
		return true;
	}

	return false;
}
// --------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	int optindex = 0;
	int opt = 0;
	Command cmd = cmdNOP;
	int verb = 0;
	std::string addr = "";
	ost::tpport_t port=0;
	int usecpause = 2000000;
	timeout_t tout = TIMEOUT_INF;
	bool broadcast = true;
	int procID = 1;
	int nodeID = 1;
	size_t count = 50;
	bool lost = false;
	bool show = false;

	while( (opt = getopt_long(argc, argv, "hs:c:r:p:n:t:x:blvd",longopts,&optindex)) != -1 )
	{
		switch (opt)
		{
			case 'h':
				cout << "-h|--help                - this message" << endl;
				cout << "[-s|--send] host:port    - Send message." << endl;
				cout << "[-c|--data-count] num    - Send num count of value. Default: 50." << endl;
				cout << "[-r|--receive] host:port - Receive message." << endl;
				cout << "[-p|--proc-id] id        - Set packet header. From 'procID'. Default: 1" << endl;
				cout << "[-n|--node-id] id        - Set packet header. From 'nodeID'. Default: 1" << endl;
				cout << "[-t|--timeout] msec      - timeout for receive. Default: 0 msec (waitup)." << endl;
				cout << "[-x|--send-pause] msec   - pause for send packets. Default: 200 msec." << endl;
				cout << "[-b|--disable-broadcast] - Disable broadcast mode." << endl;
				cout << "[-l|--check-lost]        - Check the lost packets." << endl;
				cout << "[-v|--verbose]           - verbose mode." << endl;
				cout << "[-d|--show-data]         - show receive data." << endl;
				cout << endl;
			return 0;

			case 'r':
				cmd = cmdReceive;
				addr = string(optarg);
			break;

			case 's':
				addr = string(optarg);
				cmd = cmdSend;
			break;

			case 't':
				tout = UniSetTypes::uni_atoi(optarg);
			break;

			case 'x':
				usecpause = UniSetTypes::uni_atoi(optarg)*1000;
			break;

			case 'c':
				count = UniSetTypes::uni_atoi(optarg);
			break;

			case 'p':
				procID = UniSetTypes::uni_atoi(optarg);
			break;

			case 'n':
				nodeID = UniSetTypes::uni_atoi(optarg);
			break;

			case 'b':
				broadcast = false;
			break;

			case 'd':
				show = true;
			break;

			case 'l':
				lost = true;
			break;

			case 'v':
				verb = 1;
			break;

			case '?':
			default:
				cerr << "? argumnet" << endl;
				return 0;
		}
	}

	if( cmd == cmdNOP )
	{
		cerr << "No command... Use -h for help" << endl;
		return -1;
	}

	if( tout < 0 )
		tout = TIMEOUT_INF;

	ost::Thread::setException(ost::Thread::throwException);

	try
	{
		string s_host;
		if( !split_addr(addr,s_host,port) )
		{
			cerr << "(main): Unknown 'host:port' for '" << addr << "'" << endl;
			return 1;
		}

		if( verb )
		{
			cout << " host=" << s_host
				<< " port=" << port
				<< " timeout=";
			if( tout == TIMEOUT_INF )
				cout << "Waitup";
			else
				cout << tout;

			cout << " msecpause=" << usecpause/1000
				<< endl;
		}

		ost::IPV4Host host(s_host.c_str());
//		udp.UDPTransmit::setBroadcast(broadcast);

		switch( cmd )
		{
			case cmdReceive:
			{
				ost::UDPDuplex udp(host,port);

//				char buf[UniSetUDP::MaxDataLen];
				UniSetUDP::UDPMessage pack;
				UniSetUDP::UDPPacket buf;
				unsigned long prev_num=1;

				while(1)
				{
					try
					{
						if( !udp.isInputReady(tout) )
						{
							cout << "(recv): Timeout.." << endl;
							continue;
						}

						size_t ret = udp.UDPReceive::receive( &(buf.data), sizeof(buf.data) );
						size_t sz = UniSetUDP::UDPMessage::getMessage(pack,buf);
						if( sz == 0 )
						{
							cerr << "(recv): FAILED header ret=" << ret
								<< " sizeof=" << sz<< endl;
							continue;
						}

						if( lost )
						{
							if( prev_num != (pack.num-1) )
								cerr << "WARNING! Incorrect sequence of packets! current=" << pack.num
									<< " prev=" << prev_num << endl;

							prev_num = pack.num;
						}

//						if( verb )
//							cout << "receive OK. header: " << pack.msg.header
//								 << " bytes: " << ret << endl;

						if( show )
							cout << "receive data: " << pack << endl;
					}
					catch( ost::SockException& e )
					{
						cerr << "(recv): " << e.getString() << " (" << addr << ")" << endl;
					}
					catch( ... )
					{
						cerr << "(recv): catch ..." << endl;
					}
				}
			}
			break;

			case cmdSend:
			{
				ost::UDPSocket* udp;
			if( !broadcast )
			udp = new ost::UDPSocket();
			else
			        udp = new ost::UDPBroadcast(host,port);

				UniSetUDP::UDPMessage mypack;
				mypack.nodeID = nodeID;
				mypack.procID = procID;

				for( size_t i=0; i < count; i++ )
				{
					UDPAData d(i,i);
					mypack.addAData(d);
				}

				for( int i=0; i < count; i++ )
					mypack.addDData(i,i);

				udp->setPeer(host,port);
				unsigned long packetnum = 0;

				UniSetUDP::UDPPacket s_buf;

				while(1)
				{
					mypack.num = packetnum++;
					if( packetnum > UniSetUDP::MaxPacketNum )
						packetnum = 1;

					try
					{
						if( udp->isPending(ost::Socket::pendingOutput,tout) )
						{
							mypack.transport_msg(s_buf);

							if( verb )
								cout << "(send): to addr=" << addr << " d_count=" << mypack.dcount
									<< " a_count=" << mypack.acount << " bytes=" << s_buf.len << endl;

							size_t ret = udp->send((char*)&s_buf.data, s_buf.len);
							if( ret < s_buf.len )
							cerr << "(send): FAILED ret=" << ret << " < sizeof=" << s_buf.len << endl;
						}
					}
					catch( ost::SockException& e )
					{
						cerr << "(send): " << e.getString() << " (" << addr << ")" << endl;
					}
					catch( ... )
					{
						cerr << "(send): catch ..." << endl;
					}

					usleep(usecpause);
				}
			}
			break;

			default:
				cerr << endl << "Unknown command: '" << cmd << "'. Use -h for help" << endl;
				return -1;
			break;
		}
	}
	catch( std::exception& e )
	{
		cerr << "(main): " << e.what() << endl;
	}
	catch( ... )
	{
		cerr << "(main): catch ..." << endl;
		return 1;
	}

	return 0;
}
// --------------------------------------------------------------------------
<commit_msg>Добавил в утилиты тестирования возможность задать количество циклов обмена. До этого была "безконечно" пока не прервёшь программу.<commit_after>#include <cstdlib>
#include <errno.h>
#include <getopt.h>
#include <cstring>
#include <iostream>
#include <cc++/socket.h>
#include "UDPPacket.h"
// --------------------------------------------------------------------------
static struct option longopts[] = {
	{ "help", no_argument, 0, 'h' },
	{ "send", required_argument, 0, 's' },
	{ "receive", required_argument, 0, 'r' },
	{ "proc-id", required_argument, 0, 'p' },
	{ "node-id", required_argument, 0, 'n' },
	{ "send-pause", required_argument, 0, 'x' },
	{ "timeout", required_argument, 0, 't' },
	{ "data-count", required_argument, 0, 'c' },
	{ "disable-broadcast", no_argument, 0, 'b' },
	{ "show-data", no_argument, 0, 'd' },
	{ "check-lost", no_argument, 0, 'l' },
	{ "verbode", required_argument, 0, 'v' },
	{ "num-cycles", required_argument, 0, 'z' },
	{ NULL, 0, 0, 0 }
};
// --------------------------------------------------------------------------
using namespace std;
using namespace UniSetUDP;
// --------------------------------------------------------------------------
enum Command
{
	cmdNOP,
	cmdSend,
	cmdReceive
};
// --------------------------------------------------------------------------
static bool split_addr( const string addr, string& host, ost::tpport_t& port )
{
	string::size_type pos = addr.rfind(':');
	if(  pos != string::npos )
	{
		host = addr.substr(0,pos);
		string s_port(addr.substr(pos+1,addr.size()-1));
		port = UniSetTypes::uni_atoi(s_port.c_str());
		return true;
	}

	return false;
}
// --------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	int optindex = 0;
	int opt = 0;
	Command cmd = cmdNOP;
	int verb = 0;
	std::string addr = "";
	ost::tpport_t port=0;
	int usecpause = 2000000;
	timeout_t tout = TIMEOUT_INF;
	bool broadcast = true;
	int procID = 1;
	int nodeID = 1;
	size_t count = 50;
	bool lost = false;
	bool show = false;
	int ncycles = -1;

	while( (opt = getopt_long(argc, argv, "hs:c:r:p:n:t:x:blvdz:",longopts,&optindex)) != -1 )
	{
		switch (opt)
		{
			case 'h':
				cout << "-h|--help                - this message" << endl;
				cout << "[-s|--send] host:port    - Send message." << endl;
				cout << "[-c|--data-count] num    - Send num count of value. Default: 50." << endl;
				cout << "[-r|--receive] host:port - Receive message." << endl;
				cout << "[-p|--proc-id] id        - Set packet header. From 'procID'. Default: 1" << endl;
				cout << "[-n|--node-id] id        - Set packet header. From 'nodeID'. Default: 1" << endl;
				cout << "[-t|--timeout] msec      - timeout for receive. Default: 0 msec (waitup)." << endl;
				cout << "[-x|--send-pause] msec   - pause for send packets. Default: 200 msec." << endl;
				cout << "[-b|--disable-broadcast] - Disable broadcast mode." << endl;
				cout << "[-l|--check-lost]        - Check the lost packets." << endl;
				cout << "[-v|--verbose]           - verbose mode." << endl;
				cout << "[-d|--show-data]         - show receive data." << endl;
				cout << "[-z|--num-cycles] num    - Number of cycles of exchange. Default: -1 - infinitely." << endl;
				cout << endl;
			return 0;

			case 'r':
				cmd = cmdReceive;
				addr = string(optarg);
			break;

			case 's':
				addr = string(optarg);
				cmd = cmdSend;
			break;

			case 't':
				tout = UniSetTypes::uni_atoi(optarg);
			break;

			case 'x':
				usecpause = UniSetTypes::uni_atoi(optarg)*1000;
			break;

			case 'c':
				count = UniSetTypes::uni_atoi(optarg);
			break;

			case 'p':
				procID = UniSetTypes::uni_atoi(optarg);
			break;

			case 'n':
				nodeID = UniSetTypes::uni_atoi(optarg);
			break;

			case 'b':
				broadcast = false;
			break;

			case 'd':
				show = true;
			break;

			case 'l':
				lost = true;
			break;

			case 'v':
				verb = 1;
			break;

			case 'z':
				ncycles = UniSetTypes::uni_atoi(optarg);
			break;

			case '?':
			default:
				cerr << "? argumnet" << endl;
				return 0;
		}
	}

	if( cmd == cmdNOP )
	{
		cerr << "No command... Use -h for help" << endl;
		return -1;
	}

	if( tout < 0 )
		tout = TIMEOUT_INF;

	ost::Thread::setException(ost::Thread::throwException);

	try
	{
		string s_host;
		if( !split_addr(addr,s_host,port) )
		{
			cerr << "(main): Unknown 'host:port' for '" << addr << "'" << endl;
			return 1;
		}

		if( verb )
		{
			cout << " host=" << s_host
				<< " port=" << port
				<< " timeout=";
			if( tout == TIMEOUT_INF )
				cout << "Waitup";
			else
				cout << tout;

			cout << " msecpause=" << usecpause/1000
				<< endl;
		}

		ost::IPV4Host host(s_host.c_str());
//		udp.UDPTransmit::setBroadcast(broadcast);

		switch( cmd )
		{
			case cmdReceive:
			{
				ost::UDPDuplex udp(host,port);

//				char buf[UniSetUDP::MaxDataLen];
				UniSetUDP::UDPMessage pack;
				UniSetUDP::UDPPacket buf;
				unsigned long prev_num=1;

				int nc = 1;
				if( ncycles > 0 )
					nc = ncycles;

				while( nc )
				{
					try
					{
						if( !udp.isInputReady(tout) )
						{
							cout << "(recv): Timeout.." << endl;
							continue;
						}

						size_t ret = udp.UDPReceive::receive( &(buf.data), sizeof(buf.data) );
						size_t sz = UniSetUDP::UDPMessage::getMessage(pack,buf);
						if( sz == 0 )
						{
							cerr << "(recv): FAILED header ret=" << ret
								<< " sizeof=" << sz<< endl;
							continue;
						}

						if( lost )
						{
							if( prev_num != (pack.num-1) )
								cerr << "WARNING! Incorrect sequence of packets! current=" << pack.num
									<< " prev=" << prev_num << endl;

							prev_num = pack.num;
						}

//						if( verb )
//							cout << "receive OK. header: " << pack.msg.header
//								 << " bytes: " << ret << endl;

						if( show )
							cout << "receive data: " << pack << endl;
					}
					catch( ost::SockException& e )
					{
						cerr << "(recv): " << e.getString() << " (" << addr << ")" << endl;
					}
					catch( ... )
					{
						cerr << "(recv): catch ..." << endl;
					}

					if( ncycles > 0 )
					{
						nc--;
						if( nc <=0 )
							break;
					}
				}
			}
			break;

			case cmdSend:
			{
				ost::UDPSocket* udp;
			if( !broadcast )
			udp = new ost::UDPSocket();
			else
			        udp = new ost::UDPBroadcast(host,port);

				UniSetUDP::UDPMessage mypack;
				mypack.nodeID = nodeID;
				mypack.procID = procID;

				for( size_t i=0; i < count; i++ )
				{
					UDPAData d(i,i);
					mypack.addAData(d);
				}

				for( int i=0; i < count; i++ )
					mypack.addDData(i,i);

				udp->setPeer(host,port);
				unsigned long packetnum = 0;

				UniSetUDP::UDPPacket s_buf;

				int nc = 1;
				if( ncycles > 0 )
					nc = ncycles;

				while( nc )
				{
					mypack.num = packetnum++;
					if( packetnum > UniSetUDP::MaxPacketNum )
						packetnum = 1;

					try
					{
						if( udp->isPending(ost::Socket::pendingOutput,tout) )
						{
							mypack.transport_msg(s_buf);

							if( verb )
								cout << "(send): to addr=" << addr << " d_count=" << mypack.dcount
									<< " a_count=" << mypack.acount << " bytes=" << s_buf.len << endl;

							size_t ret = udp->send((char*)&s_buf.data, s_buf.len);
							if( ret < s_buf.len )
							cerr << "(send): FAILED ret=" << ret << " < sizeof=" << s_buf.len << endl;
						}
					}
					catch( ost::SockException& e )
					{
						cerr << "(send): " << e.getString() << " (" << addr << ")" << endl;
					}
					catch( ... )
					{
						cerr << "(send): catch ..." << endl;
					}

					if( ncycles > 0 )
					{
						nc--;
						if( nc <=0 )
							break;
					}

					usleep(usecpause);
				}
			}
			break;

			default:
				cerr << endl << "Unknown command: '" << cmd << "'. Use -h for help" << endl;
				return -1;
			break;
		}
	}
	catch( std::exception& e )
	{
		cerr << "(main): " << e.what() << endl;
	}
	catch( ... )
	{
		cerr << "(main): catch ..." << endl;
		return 1;
	}

	return 0;
}
// --------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include "googledataresource.h"

#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <qstring.h>
#include <KWindowSystem>

extern "C" {
#include <gcalendar.h>
#include <gcontact.h>
#include <gcal_status.h>
}

/** FIXME: for some reason the 'retrieveItem' functions is not being called.
 * this makes the entries to lack its contents (name, email, etc).
 * I should investigate why and fix, for while this is a workaround:
 * I report the payload in the 'retrieveItems' function.
 */
#define ITEM_BUG_WTF

using namespace Akonadi;

GoogleDataResource::GoogleDataResource( const QString &id )
	: ResourceBase(id), dlgConf(0), authenticated(false)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
						      Settings::self(), QDBusConnection::ExportAdaptors );

	if (!(gcal = gcal_new(GCONTACT)))
		exit(1);
	gcal_set_store_xml(gcal, 1);
}

GoogleDataResource::~GoogleDataResource()
{
	gcal_delete(gcal);
	gcal_cleanup_contacts(&all_contacts);
	if (dlgConf)
		delete dlgConf;
}

void GoogleDataResource::retrieveCollections()
{
	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	Collection c;
	c.setParent(Collection::root());
	c.setRemoteId("google-contacts");
	c.setName(name());

	QStringList mimeTypes;
	mimeTypes << "text/directory";
	c.setContentMimeTypes(mimeTypes);

	Collection::List list;
	list << c;
	collectionsRetrieved(list);

}

void GoogleDataResource::retrieveItems( const Akonadi::Collection &collection )
{
	Q_UNUSED( collection );

	Item::List items;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	/* Downloading the contacts can be slow and it is blocking. Will
	 * it mess up with akonadi?
	 */
	if ((result = gcal_get_contacts(gcal, &all_contacts)))
		exit(1);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_contacts.length; ++i) {
		Item item(QLatin1String("text/directory"));
		gcal_contact_t contact = gcal_contact_element(&all_contacts, i);

#ifdef ITEM_BUG_WTF
		KABC::Addressee addressee;
		KABC::PhoneNumber number;
		KABC::Key key;
		QString temp;

		/* name */
		temp = gcal_contact_get_title(contact);
		addressee.setNameFromString(temp);
		/* email */
		temp = gcal_contact_get_email(contact);
		addressee.insertEmail(temp, true);
		/* edit url: required to do edit/delete */
		temp = gcal_contact_get_url(contact);
		addressee.setUid(temp);
		/* ETag: required by Google Data protocol 2.0 */
		temp = gcal_contact_get_etag(contact);
		key.setId(temp);
		addressee.insertKey(key);
		/* TODO: telefone, address, etc */

		item.setPayload<KABC::Addressee>(addressee);
#endif

		item.setRemoteId(gcal_contact_get_id(contact));

		items << item;
	}

	itemsRetrieved(items);
}

bool GoogleDataResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED( parts );
	const QString entry_id = item.remoteId();
	QString temp;
	Item newItem(item);
	gcal_contact_t contact;
	KABC::Addressee addressee;
	KABC::PhoneNumber number;
	KABC::Key key;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return false;
	}

	/*
	 * And another question, are the requests in the same sequence that
	 * I informed in 'retrieveItems'? For while, I try to locate the entry...
	 */
	for (size_t i = 0; i < all_contacts.length; ++i) {
		contact = gcal_contact_element(&all_contacts, i);
		if (entry_id == gcal_contact_get_id(contact)) {
			/* name */
			temp = gcal_contact_get_title(contact);
			addressee.setNameFromString(temp);

			/* email */
			temp = gcal_contact_get_email(contact);
			addressee.insertEmail(temp, true);

			/* edit url: required to do edit/delete */
			temp = gcal_contact_get_url(contact);
			addressee.setUid(temp);

			/* ETag: required by Google Data protocol 2.0 */
			temp = gcal_contact_get_etag(contact);
			key.setId(temp);
			addressee.insertKey(key);

			/* TODO: telefone, address, etc */

			newItem.setPayload<KABC::Addressee>(addressee);
			return true;
		}

	}

	return false;
}

void GoogleDataResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GoogleDataResource::configure( WId windowId )
{
	Q_UNUSED( windowId );
	char *user, *pass;
	int result = -1;
	QByteArray byteUser, bytePass;

	if (!dlgConf)
		dlgConf = new dlgGoogleDataConf;

	if (windowId && dlgConf)
		KWindowSystem::setMainWindow(dlgConf, windowId);

	dlgConf->exec();

	byteUser = dlgConf->eAccount->text().toLocal8Bit();
	bytePass = dlgConf->ePass->text().toLocal8Bit();
	user = const_cast<char *>(byteUser.constData());
	pass = const_cast<char *>(bytePass.constData());
	if (user)
		if (pass)
			result = gcal_get_authentication(gcal, user, pass);

	/* TODO: in case of authentication error, display an error
	 * message.
	 */
	if (!result)
		authenticated = true;

	synchronize();
}

void GoogleDataResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{

	Q_UNUSED(collection);

	KABC::Addressee addressee;
	gcal_contact_t contact;
	QString temp;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	if (item.hasPayload<KABC::Addressee>())
		addressee = item.payload<KABC::Addressee>();

	if (!(contact = gcal_contact_new(NULL)))
		exit(1);

	temp = addressee.realName();
	gcal_contact_set_title(contact, const_cast<char *>(qPrintable(temp)));

	temp = addressee.fullEmail();
	gcal_contact_set_email(contact, const_cast<char *>(qPrintable(temp)));

	/* TODO: add remaining fields */

	if ((result = gcal_add_contact(gcal, contact)))
		exit(1);

	gcal_contact_delete(contact);

}

void GoogleDataResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);

	KABC::Addressee addressee;
	gcal_contact_t contact;
	KABC::Key key;
	QString temp;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	if (item.hasPayload<KABC::Addressee>())
		addressee = item.payload<KABC::Addressee>();

	if (!(contact = gcal_contact_new(NULL)))
		exit(1);

	temp = addressee.realName();
	gcal_contact_set_title(contact, const_cast<char *>(qPrintable(temp)));

	temp = addressee.fullEmail();
	gcal_contact_set_email(contact, const_cast<char *>(qPrintable(temp)));

	temp = addressee.uid();
	gcal_contact_set_id(contact, const_cast<char *>(qPrintable(temp)));

	/* I suppose that this retrieves the first element in the key list */
	key = addressee.keys()[0];
	temp = key.id();
	gcal_contact_set_etag(contact, const_cast<char *>(qPrintable(temp)));

	/* TODO: add remaining fields */

	if ((result = gcal_update_contact(gcal, contact)))
		exit(1);

	/* Updates the ETag/url: I suppose that akonadi will save this object */
	temp = gcal_contact_get_url(contact);
	addressee.setUid(temp);

	temp = gcal_contact_get_etag(contact);
	key.setId(temp);
	addressee.insertKey(key);

	gcal_contact_delete(contact);

}

void GoogleDataResource::itemRemoved( const Akonadi::Item &item )
{
	KABC::Addressee addressee;
	gcal_contact_t contact;
	KABC::Key key;
	QString temp;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	if (item.hasPayload<KABC::Addressee>())
		addressee = item.payload<KABC::Addressee>();

	if (!(contact = gcal_contact_new(NULL)))
		exit(1);

	temp = addressee.uid();
	gcal_contact_set_id(contact, const_cast<char *>(qPrintable(temp)));

	/* I suppose that this retrieves the first element in the key list */
	key = addressee.keys()[0];
	temp = key.id();
	gcal_contact_set_etag(contact, const_cast<char *>(qPrintable(temp)));

	if ((result = gcal_erase_contact(gcal, contact)))
		exit(1);

	gcal_contact_delete(contact);

}

AKONADI_RESOURCE_MAIN( GoogleDataResource )

#include "googledataresource.moc"
<commit_msg>Returning the item (patch by krake).<commit_after>#include "googledataresource.h"

#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <qstring.h>
#include <KWindowSystem>

extern "C" {
#include <gcalendar.h>
#include <gcontact.h>
#include <gcal_status.h>
}

/** FIXME: for some reason the 'retrieveItem' functions is not being called.
 * this makes the entries to lack its contents (name, email, etc).
 * I should investigate why and fix, for while this is a workaround:
 * I report the payload in the 'retrieveItems' function.
 */
#define ITEM_BUG_WTF

using namespace Akonadi;

GoogleDataResource::GoogleDataResource( const QString &id )
	: ResourceBase(id), dlgConf(0), authenticated(false)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
						      Settings::self(), QDBusConnection::ExportAdaptors );

	if (!(gcal = gcal_new(GCONTACT)))
		exit(1);
	gcal_set_store_xml(gcal, 1);
}

GoogleDataResource::~GoogleDataResource()
{
	gcal_delete(gcal);
	gcal_cleanup_contacts(&all_contacts);
	if (dlgConf)
		delete dlgConf;
}

void GoogleDataResource::retrieveCollections()
{
	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	Collection c;
	c.setParent(Collection::root());
	c.setRemoteId("google-contacts");
	c.setName(name());

	QStringList mimeTypes;
	mimeTypes << "text/directory";
	c.setContentMimeTypes(mimeTypes);

	Collection::List list;
	list << c;
	collectionsRetrieved(list);

}

void GoogleDataResource::retrieveItems( const Akonadi::Collection &collection )
{
	Q_UNUSED( collection );

	Item::List items;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	/* Downloading the contacts can be slow and it is blocking. Will
	 * it mess up with akonadi?
	 */
	if ((result = gcal_get_contacts(gcal, &all_contacts)))
		exit(1);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_contacts.length; ++i) {
		Item item(QLatin1String("text/directory"));
		gcal_contact_t contact = gcal_contact_element(&all_contacts, i);

#ifdef ITEM_BUG_WTF
		KABC::Addressee addressee;
		KABC::PhoneNumber number;
		KABC::Key key;
		QString temp;

		/* name */
		temp = gcal_contact_get_title(contact);
		addressee.setNameFromString(temp);
		/* email */
		temp = gcal_contact_get_email(contact);
		addressee.insertEmail(temp, true);
		/* edit url: required to do edit/delete */
		temp = gcal_contact_get_url(contact);
		addressee.setUid(temp);
		/* ETag: required by Google Data protocol 2.0 */
		temp = gcal_contact_get_etag(contact);
		key.setId(temp);
		addressee.insertKey(key);
		/* TODO: telefone, address, etc */

		item.setPayload<KABC::Addressee>(addressee);
#endif

		item.setRemoteId(gcal_contact_get_id(contact));

		items << item;
	}

	itemsRetrieved(items);
}

bool GoogleDataResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED( parts );
	const QString entry_id = item.remoteId();
	QString temp;
	Item newItem(item);
	gcal_contact_t contact;
	KABC::Addressee addressee;
	KABC::PhoneNumber number;
	KABC::Key key;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return false;
	}

	/*
	 * And another question, are the requests in the same sequence that
	 * I informed in 'retrieveItems'? For while, I try to locate the entry...
	 */
	for (size_t i = 0; i < all_contacts.length; ++i) {
		contact = gcal_contact_element(&all_contacts, i);
		if (entry_id == gcal_contact_get_id(contact)) {
			/* name */
			temp = gcal_contact_get_title(contact);
			addressee.setNameFromString(temp);

			/* email */
			temp = gcal_contact_get_email(contact);
			addressee.insertEmail(temp, true);

			/* edit url: required to do edit/delete */
			temp = gcal_contact_get_url(contact);
			addressee.setUid(temp);

			/* ETag: required by Google Data protocol 2.0 */
			temp = gcal_contact_get_etag(contact);
			key.setId(temp);
			addressee.insertKey(key);

			/* TODO: telefone, address, etc */

			newItem.setPayload<KABC::Addressee>(addressee);

                        itemRetrieved(newItem);
			return true;
		}

	}

	return false;
}

void GoogleDataResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GoogleDataResource::configure( WId windowId )
{
	Q_UNUSED( windowId );
	char *user, *pass;
	int result = -1;
	QByteArray byteUser, bytePass;

	if (!dlgConf)
		dlgConf = new dlgGoogleDataConf;

	if (windowId && dlgConf)
		KWindowSystem::setMainWindow(dlgConf, windowId);

	dlgConf->exec();

	byteUser = dlgConf->eAccount->text().toLocal8Bit();
	bytePass = dlgConf->ePass->text().toLocal8Bit();
	user = const_cast<char *>(byteUser.constData());
	pass = const_cast<char *>(bytePass.constData());
	if (user)
		if (pass)
			result = gcal_get_authentication(gcal, user, pass);

	/* TODO: in case of authentication error, display an error
	 * message.
	 */
	if (!result)
		authenticated = true;

	synchronize();
}

void GoogleDataResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{

	Q_UNUSED(collection);

	KABC::Addressee addressee;
	gcal_contact_t contact;
	QString temp;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	if (item.hasPayload<KABC::Addressee>())
		addressee = item.payload<KABC::Addressee>();

	if (!(contact = gcal_contact_new(NULL)))
		exit(1);

	temp = addressee.realName();
	gcal_contact_set_title(contact, const_cast<char *>(qPrintable(temp)));

	temp = addressee.fullEmail();
	gcal_contact_set_email(contact, const_cast<char *>(qPrintable(temp)));

	/* TODO: add remaining fields */

	if ((result = gcal_add_contact(gcal, contact)))
		exit(1);

	gcal_contact_delete(contact);

}

void GoogleDataResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);

	KABC::Addressee addressee;
	gcal_contact_t contact;
	KABC::Key key;
	QString temp;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	if (item.hasPayload<KABC::Addressee>())
		addressee = item.payload<KABC::Addressee>();

	if (!(contact = gcal_contact_new(NULL)))
		exit(1);

	temp = addressee.realName();
	gcal_contact_set_title(contact, const_cast<char *>(qPrintable(temp)));

	temp = addressee.fullEmail();
	gcal_contact_set_email(contact, const_cast<char *>(qPrintable(temp)));

	temp = addressee.uid();
	gcal_contact_set_id(contact, const_cast<char *>(qPrintable(temp)));

	/* I suppose that this retrieves the first element in the key list */
	key = addressee.keys()[0];
	temp = key.id();
	gcal_contact_set_etag(contact, const_cast<char *>(qPrintable(temp)));

	/* TODO: add remaining fields */

	if ((result = gcal_update_contact(gcal, contact)))
		exit(1);

	/* Updates the ETag/url: I suppose that akonadi will save this object */
	temp = gcal_contact_get_url(contact);
	addressee.setUid(temp);

	temp = gcal_contact_get_etag(contact);
	key.setId(temp);
	addressee.insertKey(key);

	gcal_contact_delete(contact);

}

void GoogleDataResource::itemRemoved( const Akonadi::Item &item )
{
	KABC::Addressee addressee;
	gcal_contact_t contact;
	KABC::Key key;
	QString temp;
	int result;

	if (!authenticated) {
		kError() << "No athentication for Google Contacts available";
		const QString message = i18nc("@info:status",
					      "No  yet authenticated for"
					      " use of Google Contacts");
		emit error(message);

		emit status(Broken, message);
		return;
	}

	if (item.hasPayload<KABC::Addressee>())
		addressee = item.payload<KABC::Addressee>();

	if (!(contact = gcal_contact_new(NULL)))
		exit(1);

	temp = addressee.uid();
	gcal_contact_set_id(contact, const_cast<char *>(qPrintable(temp)));

	/* I suppose that this retrieves the first element in the key list */
	key = addressee.keys()[0];
	temp = key.id();
	gcal_contact_set_etag(contact, const_cast<char *>(qPrintable(temp)));

	if ((result = gcal_erase_contact(gcal, contact)))
		exit(1);

	gcal_contact_delete(contact);

}

AKONADI_RESOURCE_MAIN( GoogleDataResource )

#include "googledataresource.moc"
<|endoftext|>


<commit_before>#include <stdio.h>
#include <cmath>

#include <geometry_msgs/PoseStamped.h>
#include <jsk_rviz_plugins/OverlayText.h>
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <std_msgs/UInt8.h>

#include <autoware_msgs/lane.h>
#include <autoware_msgs/traffic_light.h>

#include <cross_road_area.hpp>
#include <decision_maker_node.hpp>
#include <state.hpp>
#include <state_context.hpp>

namespace decision_maker
{
void DecisionMakerNode::callbackFromCurrentPose(const geometry_msgs::PoseStamped &msg)
{
  geometry_msgs::PoseStamped _pose = current_pose_ = msg;
  bool initLocalizationFlag = ctx->isCurrentState(state_machine::INITIAL_LOCATEVEHICLE_STATE);
  if (initLocalizationFlag &&
      isLocalizationConvergence(_pose.pose.position.x, _pose.pose.position.y, _pose.pose.position.z,
                                _pose.pose.orientation.x, _pose.pose.orientation.y, _pose.pose.orientation.z))
  {
    ROS_INFO("Localization was convergence");
  }
}

bool DecisionMakerNode::handleStateCmd(const uint64_t _state_num)
{
  bool _ret;
  ctx->setEnableForceSetState(true);
  if (!ctx->isCurrentState(_state_num))
  {
    _ret = ctx->setCurrentState((state_machine::StateFlags)_state_num);
    if(_state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHTRED_STATE
		    || _state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE){
	    isManualLight = true;
    }
  }
  else
  {
    _ret = ctx->disableCurrentState((state_machine::StateFlags)_state_num);
    if(_state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_RED_STATE
		    || _state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE){
	    isManualLight = false;
  }
  ctx->setEnableForceSetState(false);

  return _ret;
}

void DecisionMakerNode::callbackFromSimPose(const geometry_msgs::PoseStamped &msg)
{
  ROS_INFO("Received system is going to simulation mode");
  handleStateCmd(state_machine::DRIVE_STATE);
  Subs["sim_pose"].shutdown();
}

void DecisionMakerNode::callbackFromStateCmd(const std_msgs::Int32 &msg)
{
  ROS_INFO("Received forcing state changing request: %llx", 1ULL << (uint64_t)msg.data);
  handleStateCmd((uint64_t)1ULL << (uint64_t)msg.data);
}

void DecisionMakerNode::callbackFromLaneChangeFlag(const std_msgs::Int32 &msg)
{
  if (msg.data == enumToInteger<E_ChangeFlags>(E_ChangeFlags::LEFT))
  {
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE);
    ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE);
  }
  else if (msg.data == enumToInteger<E_ChangeFlags>(E_ChangeFlags::RIGHT))
  {
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE);
    ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE);
  }
  else
  {
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE);
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE);
  }
}

void DecisionMakerNode::callbackFromConfig(const autoware_msgs::ConfigDecisionMaker &msg)
{
  ROS_INFO("Param setted by Runtime Manager");
  enableDisplayMarker = msg.enable_display_marker;
  ctx->setEnableForceSetState(msg.enable_force_state_change);

  param_target_waypoint_ = msg.target_waypoint;
  param_stopline_target_waypoint_ = msg.stopline_target_waypoint;
  param_shift_width_ = msg.shift_width;
}

void DecisionMakerNode::callbackFromLightColor(const ros::MessageEvent<autoware_msgs::traffic_light const> &event)
{
  const autoware_msgs::traffic_light *light = event.getMessage().get();
//  const ros::M_string &header = event.getConnectionHeader();
//  std::string topic = header.at("topic");

  if(!isManualLight){// && topic.find("manage") == std::string::npos){
	  current_traffic_light_ = light->traffic_light;
	  if (current_traffic_light_ == state_machine::E_RED || current_traffic_light_ == state_machine::E_YELLOW)
	  {
		  ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_RED_STATE);
		  ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE);
	  }
	  else
	  {
		  ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE);
		  ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_RED_STATE);
	  }
  }
}

void DecisionMakerNode::callbackFromPointsRaw(const sensor_msgs::PointCloud2::ConstPtr &msg)
{
  if (ctx->setCurrentState(state_machine::INITIAL_LOCATEVEHICLE_STATE))
    Subs["points_raw"].shutdown();
}

void DecisionMakerNode::insertPointWithinCrossRoad(const std::vector<CrossRoadArea> &_intersects,
                                                   autoware_msgs::LaneArray &lane_array)
{
  for (auto &lane : lane_array.lanes)
  {
    for (auto &wp : lane.waypoints)
    {
      geometry_msgs::Point pp;
      pp.x = wp.pose.pose.position.x;
      pp.y = wp.pose.pose.position.y;
      pp.z = wp.pose.pose.position.z;

      for (auto &area : intersects)
      {
        if (CrossRoadArea::isInsideArea(&area, pp))
        {
          // area's
          if (area.insideLanes.empty() || wp.gid != area.insideLanes.back().waypoints.back().gid + 1)
          {
            autoware_msgs::lane nlane;
            area.insideLanes.push_back(nlane);
          }
          area.insideLanes.back().waypoints.push_back(wp);
          area.insideWaypoint_points.push_back(pp);  // geometry_msgs::point
          // area.insideLanes.Waypoints.push_back(wp);//autoware_msgs::waypoint
          // lane's wp
          wp.wpstate.aid = area.area_id;
        }
      }
    }
  }
}

geometry_msgs::Point to_geoPoint(const vector_map_msgs::Point &vp)
{
  geometry_msgs::Point gp;
  gp.x = vp.ly;
  gp.y = vp.bx;
  gp.z = vp.h;
  return gp;
}

void DecisionMakerNode::setWaypointState(autoware_msgs::LaneArray &lane_array)
{
  insertPointWithinCrossRoad(intersects, lane_array);
  // STR
  for (auto &area : intersects)
  {
    for (auto &laneinArea : area.insideLanes)
    {
      // To straight/left/right recognition by using angle
      // between first-waypoint and end-waypoint in intersection area.
      int angle_deg = ((int)std::floor(calcIntersectWayAngle(laneinArea)));  // normalized
      int steering_state;

      if (angle_deg <= ANGLE_LEFT)
        steering_state = autoware_msgs::WaypointState::STR_LEFT;
      else if (angle_deg >= ANGLE_RIGHT)
        steering_state = autoware_msgs::WaypointState::STR_RIGHT;
      else
        steering_state = autoware_msgs::WaypointState::STR_STRAIGHT;

      for (auto &wp_lane : laneinArea.waypoints)
        for (auto &lane : lane_array.lanes)
          for (auto &wp : lane.waypoints)
            if (wp.gid == wp_lane.gid && wp.wpstate.aid == area.area_id)
            {
              wp.wpstate.steering_state = steering_state;
            }
    }
  }
  // STOP
  std::vector<StopLine> stoplines = g_vmap.findByFilter([&](const StopLine &stopline) {
    return (g_vmap.findByKey(Key<RoadSign>(stopline.signid)).type == (int)vector_map_msgs::RoadSign::TYPE_STOP);
  });

  for (auto &lane : lane_array.lanes)
  {
    for (size_t wp_idx = 0; wp_idx < lane.waypoints.size() - 1; wp_idx++)
    {
      for (auto &stopline : stoplines)
      {
        geometry_msgs::Point bp =
            to_geoPoint(g_vmap.findByKey(Key<Point>(g_vmap.findByKey(Key<Line>(stopline.lid)).bpid)));
        geometry_msgs::Point fp =
            to_geoPoint(g_vmap.findByKey(Key<Point>(g_vmap.findByKey(Key<Line>(stopline.lid)).fpid)));

        if (amathutils::isIntersectLine(lane.waypoints.at(wp_idx).pose.pose.position.x,
                                        lane.waypoints.at(wp_idx).pose.pose.position.y,
                                        lane.waypoints.at(wp_idx + 1).pose.pose.position.x,
                                        lane.waypoints.at(wp_idx + 1).pose.pose.position.y, bp.x, bp.y, fp.x, fp.y))
        {
          geometry_msgs::Point center_point;
          center_point.x = (bp.x * 2 + fp.x) / 3;
          center_point.y = (bp.y * 2 + fp.y) / 3;
          if (amathutils::isPointLeftFromLine(
                  center_point.x, center_point.y, lane.waypoints.at(wp_idx).pose.pose.position.x,
                  lane.waypoints.at(wp_idx).pose.pose.position.y, lane.waypoints.at(wp_idx + 1).pose.pose.position.x,
                  lane.waypoints.at(wp_idx + 1).pose.pose.position.y))
          {
            lane.waypoints.at(wp_idx).wpstate.stopline_state = 1;
            // lane.waypoints.at(wp_idx + 1).wpstate.stopline_state = 1;
          }
        }
      }
    }
  }
}

// for based waypoint
void DecisionMakerNode::callbackFromLaneWaypoint(const autoware_msgs::LaneArray &msg)
{
  ROS_INFO("[%s]:LoadedWaypointLaneArray\n", __func__);
  current_based_lane_array_ = msg;  // cached based path
  // indexing
  int gid = 0;
  for (auto &lane : current_based_lane_array_.lanes)
  {
    int lid = 0;
    for (auto &wp : lane.waypoints)
    {
      wp.gid = gid++;
      wp.lid = lid++;
      wp.wpstate.aid = 0;
      wp.wpstate.steering_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.accel_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.stopline_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.lanechange_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.event_state = 0;
    }
  }
  setWaypointState(current_based_lane_array_);
  current_controlled_lane_array_ = current_shifted_lane_array_ = current_based_lane_array_;  // controlled path

  publishControlledLaneArray();
  updateLaneWaypointsArray();
}

state_machine::StateFlags getStateFlags(uint8_t msg_state)
{
  if (msg_state == (uint8_t)autoware_msgs::WaypointState::STR_LEFT)
    return state_machine::DRIVE_STR_LEFT_STATE;
  else if (msg_state == (uint8_t)autoware_msgs::WaypointState::STR_RIGHT)
    return state_machine::DRIVE_STR_RIGHT_STATE;
  else
    return state_machine::DRIVE_STR_STRAIGHT_STATE;
}

void DecisionMakerNode::callbackFromFinalWaypoint(const autoware_msgs::lane &msg)
{
  if (!hasvMap())
  {
    std::cerr << "Not found vmap subscribe" << std::endl;
    return;
  }

  if (!ctx->isCurrentState(state_machine::DRIVE_STATE))
  {
    std::cerr << "State is not DRIVE_STATE[" << ctx->getCurrentStateName() << "]" << std::endl;
    return;
  }
  // cached
  current_finalwaypoints_ = msg;

  size_t idx = current_finalwaypoints_.waypoints.size() - 1 > param_stopline_target_waypoint_ ?
                   param_stopline_target_waypoint_ :
                   current_finalwaypoints_.waypoints.size() - 1;

  if (current_finalwaypoints_.waypoints.at(idx).wpstate.stopline_state)
	  ctx->setCurrentState(state_machine::DRIVE_ACC_STOPLINE_STATE);
  // steering
  idx = current_finalwaypoints_.waypoints.size() - 1 > param_target_waypoint_ ?
            param_target_waypoint_ :
            current_finalwaypoints_.waypoints.size() - 1;
  if (ctx->isCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE))
  {
	  ctx->setCurrentState(state_machine::DRIVE_STR_LEFT_STATE);
  }
  if (ctx->isCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE))
  {
	  ctx->setCurrentState(state_machine::DRIVE_STR_RIGHT_STATE);
  }
  else
  {
	  ctx->setCurrentState(getStateFlags(current_finalwaypoints_.waypoints.at(idx).wpstate.steering_state));
  }

  // for publish plan of velocity
  publishToVelocityArray();
}
void DecisionMakerNode::callbackFromTwistCmd(const geometry_msgs::TwistStamped &msg)
{
  static bool Twistflag = false;

  if (Twistflag)
    ctx->handleTwistCmd(false);
  else
    Twistflag = true;
}

void DecisionMakerNode::callbackFromClosestWaypoint(const std_msgs::Int32 &msg)
{
  closest_waypoint_ = msg.data;
}

void DecisionMakerNode::callbackFromVectorMapArea(const vector_map_msgs::AreaArray &msg)
{
  initVectorMap();
}
void DecisionMakerNode::callbackFromVectorMapPoint(const vector_map_msgs::PointArray &msg)
{
  initVectorMap();
}
void DecisionMakerNode::callbackFromVectorMapLine(const vector_map_msgs::LineArray &msg)
{
  initVectorMap();
}
void DecisionMakerNode::callbackFromVectorMapCrossRoad(const vector_map_msgs::CrossRoadArray &msg)
{
  initVectorMap();
}

void DecisionMakerNode::callbackFromCurrentVelocity(const geometry_msgs::TwistStamped &msg)
{
  current_velocity_ = amathutils::mps2kmph(msg.twist.linear.x);
}
}
<commit_msg>fix a state num name<commit_after>#include <stdio.h>
#include <cmath>

#include <geometry_msgs/PoseStamped.h>
#include <jsk_rviz_plugins/OverlayText.h>
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <std_msgs/UInt8.h>

#include <autoware_msgs/lane.h>
#include <autoware_msgs/traffic_light.h>

#include <cross_road_area.hpp>
#include <decision_maker_node.hpp>
#include <state.hpp>
#include <state_context.hpp>

namespace decision_maker
{
void DecisionMakerNode::callbackFromCurrentPose(const geometry_msgs::PoseStamped &msg)
{
  geometry_msgs::PoseStamped _pose = current_pose_ = msg;
  bool initLocalizationFlag = ctx->isCurrentState(state_machine::INITIAL_LOCATEVEHICLE_STATE);
  if (initLocalizationFlag &&
      isLocalizationConvergence(_pose.pose.position.x, _pose.pose.position.y, _pose.pose.position.z,
                                _pose.pose.orientation.x, _pose.pose.orientation.y, _pose.pose.orientation.z))
  {
    ROS_INFO("Localization was convergence");
  }
}

bool DecisionMakerNode::handleStateCmd(const uint64_t _state_num)
{
  bool _ret;
  ctx->setEnableForceSetState(true);
  if (!ctx->isCurrentState(_state_num))
  {
    _ret = ctx->setCurrentState((state_machine::StateFlags)_state_num);
    if(_state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_RED_STATE
		    || _state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE){
	    isManualLight = true;
    }
  }
  else
  {
    _ret = ctx->disableCurrentState((state_machine::StateFlags)_state_num);
    if(_state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_RED_STATE
		    || _state_num == state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE){
	    isManualLight = false;
  }
  ctx->setEnableForceSetState(false);

  return _ret;
}

void DecisionMakerNode::callbackFromSimPose(const geometry_msgs::PoseStamped &msg)
{
  ROS_INFO("Received system is going to simulation mode");
  handleStateCmd(state_machine::DRIVE_STATE);
  Subs["sim_pose"].shutdown();
}

void DecisionMakerNode::callbackFromStateCmd(const std_msgs::Int32 &msg)
{
  ROS_INFO("Received forcing state changing request: %llx", 1ULL << (uint64_t)msg.data);
  handleStateCmd((uint64_t)1ULL << (uint64_t)msg.data);
}

void DecisionMakerNode::callbackFromLaneChangeFlag(const std_msgs::Int32 &msg)
{
  if (msg.data == enumToInteger<E_ChangeFlags>(E_ChangeFlags::LEFT))
  {
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE);
    ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE);
  }
  else if (msg.data == enumToInteger<E_ChangeFlags>(E_ChangeFlags::RIGHT))
  {
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE);
    ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE);
  }
  else
  {
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE);
    ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE);
  }
}

void DecisionMakerNode::callbackFromConfig(const autoware_msgs::ConfigDecisionMaker &msg)
{
  ROS_INFO("Param setted by Runtime Manager");
  enableDisplayMarker = msg.enable_display_marker;
  ctx->setEnableForceSetState(msg.enable_force_state_change);

  param_target_waypoint_ = msg.target_waypoint;
  param_stopline_target_waypoint_ = msg.stopline_target_waypoint;
  param_shift_width_ = msg.shift_width;
}

void DecisionMakerNode::callbackFromLightColor(const ros::MessageEvent<autoware_msgs::traffic_light const> &event)
{
  const autoware_msgs::traffic_light *light = event.getMessage().get();
//  const ros::M_string &header = event.getConnectionHeader();
//  std::string topic = header.at("topic");

  if(!isManualLight){// && topic.find("manage") == std::string::npos){
	  current_traffic_light_ = light->traffic_light;
	  if (current_traffic_light_ == state_machine::E_RED || current_traffic_light_ == state_machine::E_YELLOW)
	  {
		  ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_RED_STATE);
		  ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE);
	  }
	  else
	  {
		  ctx->setCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_GREEN_STATE);
		  ctx->disableCurrentState(state_machine::DRIVE_BEHAVIOR_TRAFFICLIGHT_RED_STATE);
	  }
  }
}

void DecisionMakerNode::callbackFromPointsRaw(const sensor_msgs::PointCloud2::ConstPtr &msg)
{
  if (ctx->setCurrentState(state_machine::INITIAL_LOCATEVEHICLE_STATE))
    Subs["points_raw"].shutdown();
}

void DecisionMakerNode::insertPointWithinCrossRoad(const std::vector<CrossRoadArea> &_intersects,
                                                   autoware_msgs::LaneArray &lane_array)
{
  for (auto &lane : lane_array.lanes)
  {
    for (auto &wp : lane.waypoints)
    {
      geometry_msgs::Point pp;
      pp.x = wp.pose.pose.position.x;
      pp.y = wp.pose.pose.position.y;
      pp.z = wp.pose.pose.position.z;

      for (auto &area : intersects)
      {
        if (CrossRoadArea::isInsideArea(&area, pp))
        {
          // area's
          if (area.insideLanes.empty() || wp.gid != area.insideLanes.back().waypoints.back().gid + 1)
          {
            autoware_msgs::lane nlane;
            area.insideLanes.push_back(nlane);
          }
          area.insideLanes.back().waypoints.push_back(wp);
          area.insideWaypoint_points.push_back(pp);  // geometry_msgs::point
          // area.insideLanes.Waypoints.push_back(wp);//autoware_msgs::waypoint
          // lane's wp
          wp.wpstate.aid = area.area_id;
        }
      }
    }
  }
}

geometry_msgs::Point to_geoPoint(const vector_map_msgs::Point &vp)
{
  geometry_msgs::Point gp;
  gp.x = vp.ly;
  gp.y = vp.bx;
  gp.z = vp.h;
  return gp;
}

void DecisionMakerNode::setWaypointState(autoware_msgs::LaneArray &lane_array)
{
  insertPointWithinCrossRoad(intersects, lane_array);
  // STR
  for (auto &area : intersects)
  {
    for (auto &laneinArea : area.insideLanes)
    {
      // To straight/left/right recognition by using angle
      // between first-waypoint and end-waypoint in intersection area.
      int angle_deg = ((int)std::floor(calcIntersectWayAngle(laneinArea)));  // normalized
      int steering_state;

      if (angle_deg <= ANGLE_LEFT)
        steering_state = autoware_msgs::WaypointState::STR_LEFT;
      else if (angle_deg >= ANGLE_RIGHT)
        steering_state = autoware_msgs::WaypointState::STR_RIGHT;
      else
        steering_state = autoware_msgs::WaypointState::STR_STRAIGHT;

      for (auto &wp_lane : laneinArea.waypoints)
        for (auto &lane : lane_array.lanes)
          for (auto &wp : lane.waypoints)
            if (wp.gid == wp_lane.gid && wp.wpstate.aid == area.area_id)
            {
              wp.wpstate.steering_state = steering_state;
            }
    }
  }
  // STOP
  std::vector<StopLine> stoplines = g_vmap.findByFilter([&](const StopLine &stopline) {
    return (g_vmap.findByKey(Key<RoadSign>(stopline.signid)).type == (int)vector_map_msgs::RoadSign::TYPE_STOP);
  });

  for (auto &lane : lane_array.lanes)
  {
    for (size_t wp_idx = 0; wp_idx < lane.waypoints.size() - 1; wp_idx++)
    {
      for (auto &stopline : stoplines)
      {
        geometry_msgs::Point bp =
            to_geoPoint(g_vmap.findByKey(Key<Point>(g_vmap.findByKey(Key<Line>(stopline.lid)).bpid)));
        geometry_msgs::Point fp =
            to_geoPoint(g_vmap.findByKey(Key<Point>(g_vmap.findByKey(Key<Line>(stopline.lid)).fpid)));

        if (amathutils::isIntersectLine(lane.waypoints.at(wp_idx).pose.pose.position.x,
                                        lane.waypoints.at(wp_idx).pose.pose.position.y,
                                        lane.waypoints.at(wp_idx + 1).pose.pose.position.x,
                                        lane.waypoints.at(wp_idx + 1).pose.pose.position.y, bp.x, bp.y, fp.x, fp.y))
        {
          geometry_msgs::Point center_point;
          center_point.x = (bp.x * 2 + fp.x) / 3;
          center_point.y = (bp.y * 2 + fp.y) / 3;
          if (amathutils::isPointLeftFromLine(
                  center_point.x, center_point.y, lane.waypoints.at(wp_idx).pose.pose.position.x,
                  lane.waypoints.at(wp_idx).pose.pose.position.y, lane.waypoints.at(wp_idx + 1).pose.pose.position.x,
                  lane.waypoints.at(wp_idx + 1).pose.pose.position.y))
          {
            lane.waypoints.at(wp_idx).wpstate.stopline_state = 1;
            // lane.waypoints.at(wp_idx + 1).wpstate.stopline_state = 1;
          }
        }
      }
    }
  }
}

// for based waypoint
void DecisionMakerNode::callbackFromLaneWaypoint(const autoware_msgs::LaneArray &msg)
{
  ROS_INFO("[%s]:LoadedWaypointLaneArray\n", __func__);
  current_based_lane_array_ = msg;  // cached based path
  // indexing
  int gid = 0;
  for (auto &lane : current_based_lane_array_.lanes)
  {
    int lid = 0;
    for (auto &wp : lane.waypoints)
    {
      wp.gid = gid++;
      wp.lid = lid++;
      wp.wpstate.aid = 0;
      wp.wpstate.steering_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.accel_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.stopline_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.lanechange_state = autoware_msgs::WaypointState::NULLSTATE;
      wp.wpstate.event_state = 0;
    }
  }
  setWaypointState(current_based_lane_array_);
  current_controlled_lane_array_ = current_shifted_lane_array_ = current_based_lane_array_;  // controlled path

  publishControlledLaneArray();
  updateLaneWaypointsArray();
}

state_machine::StateFlags getStateFlags(uint8_t msg_state)
{
  if (msg_state == (uint8_t)autoware_msgs::WaypointState::STR_LEFT)
    return state_machine::DRIVE_STR_LEFT_STATE;
  else if (msg_state == (uint8_t)autoware_msgs::WaypointState::STR_RIGHT)
    return state_machine::DRIVE_STR_RIGHT_STATE;
  else
    return state_machine::DRIVE_STR_STRAIGHT_STATE;
}

void DecisionMakerNode::callbackFromFinalWaypoint(const autoware_msgs::lane &msg)
{
  if (!hasvMap())
  {
    std::cerr << "Not found vmap subscribe" << std::endl;
    return;
  }

  if (!ctx->isCurrentState(state_machine::DRIVE_STATE))
  {
    std::cerr << "State is not DRIVE_STATE[" << ctx->getCurrentStateName() << "]" << std::endl;
    return;
  }
  // cached
  current_finalwaypoints_ = msg;

  size_t idx = current_finalwaypoints_.waypoints.size() - 1 > param_stopline_target_waypoint_ ?
                   param_stopline_target_waypoint_ :
                   current_finalwaypoints_.waypoints.size() - 1;

  if (current_finalwaypoints_.waypoints.at(idx).wpstate.stopline_state)
	  ctx->setCurrentState(state_machine::DRIVE_ACC_STOPLINE_STATE);
  // steering
  idx = current_finalwaypoints_.waypoints.size() - 1 > param_target_waypoint_ ?
            param_target_waypoint_ :
            current_finalwaypoints_.waypoints.size() - 1;
  if (ctx->isCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_LEFT_STATE))
  {
	  ctx->setCurrentState(state_machine::DRIVE_STR_LEFT_STATE);
  }
  if (ctx->isCurrentState(state_machine::DRIVE_BEHAVIOR_LANECHANGE_RIGHT_STATE))
  {
	  ctx->setCurrentState(state_machine::DRIVE_STR_RIGHT_STATE);
  }
  else
  {
	  ctx->setCurrentState(getStateFlags(current_finalwaypoints_.waypoints.at(idx).wpstate.steering_state));
  }

  // for publish plan of velocity
  publishToVelocityArray();
}
void DecisionMakerNode::callbackFromTwistCmd(const geometry_msgs::TwistStamped &msg)
{
  static bool Twistflag = false;

  if (Twistflag)
    ctx->handleTwistCmd(false);
  else
    Twistflag = true;
}

void DecisionMakerNode::callbackFromClosestWaypoint(const std_msgs::Int32 &msg)
{
  closest_waypoint_ = msg.data;
}

void DecisionMakerNode::callbackFromVectorMapArea(const vector_map_msgs::AreaArray &msg)
{
  initVectorMap();
}
void DecisionMakerNode::callbackFromVectorMapPoint(const vector_map_msgs::PointArray &msg)
{
  initVectorMap();
}
void DecisionMakerNode::callbackFromVectorMapLine(const vector_map_msgs::LineArray &msg)
{
  initVectorMap();
}
void DecisionMakerNode::callbackFromVectorMapCrossRoad(const vector_map_msgs::CrossRoadArray &msg)
{
  initVectorMap();
}

void DecisionMakerNode::callbackFromCurrentVelocity(const geometry_msgs::TwistStamped &msg)
{
  current_velocity_ = amathutils::mps2kmph(msg.twist.linear.x);
}
}
<|endoftext|>