<commit_before>#include <ros/ros.h>

#include <atwork_ros_msgs/TaskInfo.h>
#include <atwork_ros_msgs/Task.h>
#include <atwork_ros_msgs/NavigationTask.h>
#include <atwork_ros_msgs/ObjectIdentifier.h>
#include <atwork_ros_msgs/TransportationTask.h>
#include <atwork_ros_msgs/LocationIdentifier.h>

#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <task_executor/TaskAction.h>

#include <string>
#include <vector>

std::vector< atwork_ros_msgs::Task > tasks;

// Called once when the goal completes
void doneCb(const actionlib::SimpleClientGoalState& state,
            const task_executor::TaskResultConstPtr& result) {
	ROS_INFO("Finished in state [%s]", state.toString().c_str());
	ROS_INFO("Answer: %d", result->status);

	for(auto t : tasks) {
		if (t.id.data == result->id) {
			t.status.data = result->status;
		}
	}

	ros::shutdown();
}

// Called once when the goal becomes active
void activeCb() {
	ROS_INFO("Goal just went active");
}

// Called every time feedback is received for the goal
void feedbackCb(const task_executor::TaskFeedbackConstPtr& feedback) {
	ROS_INFO("Got Feedback of length %d", feedback->status);

	for(auto t : msg->tasks) {
		if (t.id.data == result->id) {
			t.status.data = result->status;
		}
	}
}

// Add tasks to vector
void TaskCallback(const atwork_ros_msgs::TaskInfoConstPtr& msg) {
	for(auto t : tasks) {
		bool exists = false;
		for(auto task : tasks) {
			if(t.id.data == task.id.data) {
				exists = true;
			}
		}
		if (!exists) {
			tasks.push_back(t);
		}
	}
}

void SendGoals(actionlib::SimpleActionClient<task_executor::TaskAction> * ac) {
	for(auto t : tasks) {
		if(t.status.data == 0) {
			// send a goal to the action
			task_executor::TaskGoal goal;
			goal.task = t;
			ac->sendGoal(goal, &doneCb, &activeCb, &feedbackCb);
			ROS_INFO("Sent task %d to as", (int) t.id.data);
		} else {
			ROS_INFO("Task %d already sent", (int) t.id.data);
		}
	}
	std::cout << tasks.size() << std::endl;

/*

	//wait for the action to return
	bool finished_before_timeout = ac.waitForResult(ros::Duration(180.0));

	if (finished_before_timeout) {
		actionlib::SimpleClientGoalState state = ac.getState();
		ROS_INFO("Action finished: %s",state.toString().c_str());
	}
	else {
		ROS_INFO("Action did not finish before the time out.");
	}*/
}

int main(int argc, char **argv) {
	ros::init(argc, argv, "master");
	ros::NodeHandle n;
	ros::Rate loop_rate(1);

	// subsribe to refbox_receiver to receive tasks
	ros::Subscriber sub = n.subscribe("/refbox_receiver/task_info", 1000, TaskCallback);

	// create the action client for tasks
	actionlib::SimpleActionClient<task_executor::TaskAction> ac("Task", true);

	// wait for the action server to start
	ROS_INFO("Waiting for action server to start.");
	ac.waitForServer();
	ROS_INFO("Action server started.");

	while (ros::ok()) {
		SendGoals(&ac);
		ros::spinOnce();
		loop_rate.sleep();
	}

	return 0;
}
<commit_msg>Actionclient<commit_after>#include <ros/ros.h>

#include <atwork_ros_msgs/TaskInfo.h>
#include <atwork_ros_msgs/Task.h>
#include <atwork_ros_msgs/NavigationTask.h>
#include <atwork_ros_msgs/ObjectIdentifier.h>
#include <atwork_ros_msgs/TransportationTask.h>
#include <atwork_ros_msgs/LocationIdentifier.h>

#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <task_executor/TaskAction.h>

#include <string>
#include <vector>

std::vector< atwork_ros_msgs::Task > tasks;

// Called once when the goal completes
void doneCb(const actionlib::SimpleClientGoalState& state,
            const task_executor::TaskResultConstPtr& result) {
	ROS_INFO("Finished in state [%s]", state.toString().c_str());
	ROS_INFO("Answer: %d", result->status);

	for(auto t : tasks) {
		if (t.id.data == result->id) {
			t.status.data = result->status;
		}
	}

	ros::shutdown();
}

// Called once when the goal becomes active
void activeCb() {
	ROS_INFO("Goal just went active");
}

// Called every time feedback is received for the goal
void feedbackCb(const task_executor::TaskFeedbackConstPtr& feedback) {
	ROS_INFO("Got Feedback of length %d", feedback->status);

	for(auto t : msg->tasks) {
		if (t.id.data == result->id) {
			t.status.data = result->status;
		}
	}
}

// Add tasks to vector
void TaskCallback(const atwork_ros_msgs::TaskInfoConstPtr& msg) {
	for(auto t : msg->tasks) {
		bool exists = false;
		for(auto task : tasks) {
			if(t.id.data == task.id.data) {
				exists = true;
			}
		}
		if (!exists) {
			tasks.push_back(t);
		}
	}
}

void SendGoals(actionlib::SimpleActionClient<task_executor::TaskAction> * ac) {
	for(auto t : tasks) {
		if(t.status.data == 1) {
			// send a goal to the action
			task_executor::TaskGoal goal;
			goal.task = t;
			ac->sendGoal(goal, &doneCb, &activeCb, &feedbackCb);
			ROS_INFO("Sent task %d to as", (int) t.id.data);
		}
	}
}

int main(int argc, char **argv) {
	ros::init(argc, argv, "master");
	ros::NodeHandle n;
	ros::Rate loop_rate(1);

	// subsribe to refbox_receiver to receive tasks
	ros::Subscriber sub = n.subscribe("/refbox_receiver/task_info", 1000, TaskCallback);

	// create the action client for tasks
	actionlib::SimpleActionClient<task_executor::TaskAction> ac("Task", true);

	// wait for the action server to start
	ROS_INFO("Waiting for action server to start.");
	ac.waitForServer();
	ROS_INFO("Action server started.");

	while (ros::ok()) {
		SendGoals(&ac);
		ros::spinOnce();
		loop_rate.sleep();
	}

	return 0;
}
<|endoftext|>


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

#ifndef SRC_MAIN_CC_COMMON_CPP_PROTOBUF_UTIL_TEXTPROTO_IO_H_
#define SRC_MAIN_CC_COMMON_CPP_PROTOBUF_UTIL_TEXTPROTO_IO_H_

#include "src/main/cc/common_cpp/protobuf_util/textproto_io.h"

#include <fcntl.h>

#include <filesystem>

#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/message.h"
#include "google/protobuf/text_format.h"

namespace wfa {

absl::Status ReadTextProtoFile(absl::string_view path,
                               google::protobuf::Message& message) {
  int fd = open(path.data(), O_RDONLY);
  if (fd <= 0) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to open file: ", path));
  }
  google::protobuf::io::FileInputStream file_input(fd);
  file_input.SetCloseOnDelete(true);
  if (!google::protobuf::TextFormat::Parse(&file_input, &message)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to parse textproto file: ", path));
  }
  return absl::OkStatus();
}

absl::Status WriteTextProtoFile(absl::string_view path,
                                const google::protobuf::Message& message) {
  // The output file is only accessible by owner.
  int fd = open(path.data(), O_CREAT | O_WRONLY, S_IRWXU);
  if (fd <= 0) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to create file: ", path));
  }
  google::protobuf::io::FileOutputStream file_output(fd);
  file_output.SetCloseOnDelete(true);
  if (!google::protobuf::TextFormat::Print(message, &file_output)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to write textproto file: ", path));
  }
  return absl::OkStatus();
}

}  // namespace wfa

#endif  // SRC_MAIN_CC_COMMON_CPP_PROTOBUF_UTIL_TEXTPROTO_IO_H_
<commit_msg>Fix include prefix (#26)<commit_after>// Copyright 2021 The Cross-Media Measurement Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SRC_MAIN_CC_COMMON_CPP_PROTOBUF_UTIL_TEXTPROTO_IO_H_
#define SRC_MAIN_CC_COMMON_CPP_PROTOBUF_UTIL_TEXTPROTO_IO_H_

#include "common_cpp/protobuf_util/textproto_io.h"

#include <fcntl.h>

#include <filesystem>

#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/message.h"
#include "google/protobuf/text_format.h"

namespace wfa {

absl::Status ReadTextProtoFile(absl::string_view path,
                               google::protobuf::Message& message) {
  int fd = open(path.data(), O_RDONLY);
  if (fd <= 0) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to open file: ", path));
  }
  google::protobuf::io::FileInputStream file_input(fd);
  file_input.SetCloseOnDelete(true);
  if (!google::protobuf::TextFormat::Parse(&file_input, &message)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to parse textproto file: ", path));
  }
  return absl::OkStatus();
}

absl::Status WriteTextProtoFile(absl::string_view path,
                                const google::protobuf::Message& message) {
  // The output file is only accessible by owner.
  int fd = open(path.data(), O_CREAT | O_WRONLY, S_IRWXU);
  if (fd <= 0) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to create file: ", path));
  }
  google::protobuf::io::FileOutputStream file_output(fd);
  file_output.SetCloseOnDelete(true);
  if (!google::protobuf::TextFormat::Print(message, &file_output)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Unable to write textproto file: ", path));
  }
  return absl::OkStatus();
}

}  // namespace wfa

#endif  // SRC_MAIN_CC_COMMON_CPP_PROTOBUF_UTIL_TEXTPROTO_IO_H_
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "URL.h"

#include <decaf/lang/Integer.h>
#include <decaf/lang/String.h>
#include <decaf/lang/Pointer.h>
#include <decaf/net/URI.h>
#include <decaf/net/URLConnection.h>
#include <decaf/net/URLStreamHandler.h>
#include <decaf/net/URLStreamHandlerFactory.h>
#include <decaf/net/MalformedURLException.h>
#include <decaf/lang/exceptions/IllegalArgumentException.h>
#include <decaf/internal/net/URLType.h>
#include <decaf/internal/net/URLUtils.h>
#include <decaf/util/HashMap.h>
#include <decaf/util/concurrent/Mutex.h>

#include <decaf/internal/net/URLStreamHandlerManager.h>

using namespace std;
using namespace decaf;
using namespace decaf::io;
using namespace decaf::net;
using namespace decaf::internal;
using namespace decaf::internal::net;
using namespace decaf::util;
using namespace decaf::util::concurrent;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
using namespace decaf::internal;
using namespace decaf::internal::net;

////////////////////////////////////////////////////////////////////////////////
namespace decaf {
namespace net {

    class URLImpl {
    public:

        URLType url;
        Pointer<URLStreamHandler> streamHandler;

    public:

        URLImpl() : url(), streamHandler() {}

        void fixURL(bool fixHost) {
            int index;
            if (!url.getHost().isEmpty()) {
                url.setAuthority(url.getHost());
                if (url.getPort() != -1) {
                    url.setAuthority(url.getAuthority() + ":" + Integer::toString(url.getPort()));
                }
            }

            if (fixHost) {
                String host = url.getHost();
                if (!host.isEmpty() && (index = host.lastIndexOf('@')) > -1) {
                    url.setUserInfo(host.substring(0, index));
                    url.setHost(host.substring(index + 1));
                } else {
                    url.setUserInfo("");
                }
            }

            String file = url.getFile();
            if (!file.isEmpty() && (index = file.indexOf('?')) > -1) {
                url.setQuery(file.substring(index + 1));
                url.setPath(file.substring(0, index));
            } else {
                url.setQuery("");
                url.setPath(url.getFile());
            }
        }

        /**
         * Sets the receiver's stream handler to one which is appropriate for its
         * protocol. Throws a MalformedURLException if no reasonable handler is
         * available.
         *

         * Note that this will overwrite any existing stream handler with the new
         * one. Senders must check if the streamHandler is NULL before calling the
         * method if they do not want this behavior (a speed optimization).
         */
        void setupStreamHandler() {
            URLStreamHandlerManager* manager = URLStreamHandlerManager::getInstance();
            streamHandler.reset(manager->getURLStreamHandler(url.getProtocol()));
        }
    };

}}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& url) : impl(new URLImpl) {
    initialize(NULL, url, NULL);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const URL& context, const String& spec) : impl(new URLImpl) {
    initialize(&context, spec, NULL);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const URL& context, const String& spec, URLStreamHandler* streamHandler) : impl(new URLImpl) {
    initialize(&context, spec, streamHandler);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& protocol, const String& host, int port,
         const String& file, URLStreamHandler* handler) : impl(new URLImpl) {
    initialize(protocol, host, port, file, handler);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& protocol, const String& host, const String& file) : impl(new URLImpl) {
    initialize(protocol, host, -1, file, NULL);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& protocol, const String& host, int port, const String& file) : impl(new URLImpl) {
    initialize(protocol, host, port, file, NULL);
}

////////////////////////////////////////////////////////////////////////////////
void URL::initialize(const URL* context, const String& theSpec, URLStreamHandler* handler) {

    if (handler != NULL) {
        impl->streamHandler.reset(handler);
    }

    String spec = theSpec.trim();  // trim

    // The spec includes a protocol if it includes a colon character
    // before the first occurrence of a slash character.
    String protocol = URLUtils::getSchemePrefix(spec);
    impl->url.setProtocol(protocol);
    int schemeSpecificPartStart = !protocol.isEmpty() ? (protocol.length() + 1) : 0;

    // If the context URL has a different protocol, discard it because we can't use it.
    if (!protocol.isEmpty() && context != NULL && !protocol.equals(context->getProtocol())) {
        context = NULL;
    }

    // Inherit from the context URL if it exists.
    if (context != NULL) {
        set(context->getProtocol(), context->getHost(), context->getPort(),
            context->getAuthority(), context->getUserInfo(), context->getPath(),
            context->getQuery(), String());

        if (impl->streamHandler == NULL) {
            impl->streamHandler = context->impl->streamHandler;
        }
    } else if (protocol.isEmpty()) {
        throw MalformedURLException(
            __FILE__, __LINE__,
            (std::string("Protocol not found: ") + spec.toString()).c_str());
    }

    // If the stream handler has not been determined, set it
    // to the default for the specified protocol.
    if (impl->streamHandler == NULL) {
        impl->setupStreamHandler();
        if (impl->streamHandler == NULL) {
            throw MalformedURLException(
                __FILE__, __LINE__,
                (std::string("unknown protocol: ") + impl->url.getProtocol().toString()).c_str());
        }
    }

    // Let the handler parse the URL. If the handler throws any exception, then
    // throw MalformedURLException instead.
    try {
        impl->streamHandler->parseURL(*this, spec, schemeSpecificPartStart, spec.length());
    } catch (Exception& e) {
        throw MalformedURLException(__FILE__, __LINE__, e.getMessage().c_str());
    }

    if (impl->url.getPort() < -1) {
        throw MalformedURLException(
            __FILE__, __LINE__, "port out of range: %d", impl->url.getPort());
    }
}

////////////////////////////////////////////////////////////////////////////////
void URL::initialize(const String& protocol, const String& host, int port,
                     const String& file, URLStreamHandler* handler) {

    if (port < -1) {
        throw MalformedURLException(__FILE__, __LINE__, "Port out of range: %d", port);
    }

    if (protocol.isEmpty()) {
        throw NullPointerException(
        __FILE__, __LINE__, "Unknown protocol: %s", "NULL");
    }

    String theHost;

    if (host.indexOf(":") != -1 && host.charAt(0) != '[') {
        theHost = String("[").concat(host).concat("]");
    } else {
        theHost = host;
    }

    impl->url.setProtocol(protocol);
    impl->url.setHost(theHost);
    impl->url.setPort(port);

    String theFile = URLUtils::authoritySafePath(theHost, file);

    // Set the fields from the arguments. Handle the case where the
    // passed in "file" includes both a file and a reference part.
    int hash = theFile.indexOf("#");
    if (hash >= 0) {
        impl->url.setFile(theFile.substring(0, hash));
        impl->url.setRef(theFile.substring(hash + 1));
    } else {
        impl->url.setFile(theFile);
    }
    impl->fixURL(false);

    // Set the stream handler for the URL either to the handler argument if it was
    // specified, or to the default for the receiver's protocol if the handler was NULL.
    if (handler == NULL) {
        impl->setupStreamHandler();
        if (impl->streamHandler == NULL) {
            throw MalformedURLException(
                __FILE__, __LINE__, (std::string("Unknown protocol: ") + protocol.toString()).c_str());
        }
    } else {
        impl->streamHandler.reset(handler);
    }
}

////////////////////////////////////////////////////////////////////////////////
URL::~URL() {
    try {
        delete impl;
    }
    DECAF_CATCHALL_NOTHROW()
}

////////////////////////////////////////////////////////////////////////////////
bool URL::equals(const URL& other) const {
    return impl->streamHandler->equals(*this, other);
}

////////////////////////////////////////////////////////////////////////////////
String URL::getAuthority() const {
    return impl->url.getAuthority();
}

////////////////////////////////////////////////////////////////////////////////
int URL::getDefaultPort() const {
    return impl->streamHandler->getDefaultPort();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getFile() const {
    return impl->url.getFile();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getHost() const {
    return impl->url.getHost();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getPath() const {
    return impl->url.getPath();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getUserInfo() const {
    return impl->url.getUserInfo();
}

////////////////////////////////////////////////////////////////////////////////
int URL::getPort() const {
    return impl->url.getPort();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getProtocol() const {
    return impl->url.getProtocol();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getQuery() const {
    return impl->url.getQuery();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getRef() const {
    return impl->url.getRef();
}

////////////////////////////////////////////////////////////////////////////////
int URL::hashCode() const {
    int hashCode = impl->url.getHashCode();
    if (hashCode == -1) {
        hashCode = impl->streamHandler->hashCode(*this);
        impl->url.setHashCode(hashCode);
    }

    return hashCode;
}

////////////////////////////////////////////////////////////////////////////////
URLConnection* URL::openConnection() {
    return impl->streamHandler->openConnection(*this);
}

////////////////////////////////////////////////////////////////////////////////
URLConnection* URL::openConnection(const Proxy* proxy) {
    if (proxy == NULL) {
        throw IllegalArgumentException(__FILE__, __LINE__, "proxy should not be NULL");
    }

    return impl->streamHandler->openConnection(*this, proxy);
}

////////////////////////////////////////////////////////////////////////////////
InputStream* URL::openStream() {
    return NULL;  // TODO figure out Connection lifetime
}

////////////////////////////////////////////////////////////////////////////////
bool URL::sameFile(const URL& other) const {
    if (impl->streamHandler == NULL) {
        throw MalformedURLException(
            __FILE__, __LINE__, (std::string("Unknown protocol: ") + getProtocol().toString()).c_str());
    }
    return impl->streamHandler->sameFile(*this, other);
}

////////////////////////////////////////////////////////////////////////////////
String URL::toExternalForm() const {
    if (impl->streamHandler == NULL) {
        return String("unknown protocol(").concat(getProtocol()).concat(")://").concat(getHost()).concat(getFile());
    }
    return impl->streamHandler->toExternalForm(*this);
}

////////////////////////////////////////////////////////////////////////////////
std::string URL::toString() const {
    return toExternalForm().toString();
}

////////////////////////////////////////////////////////////////////////////////
URI URL::toURI() const {
    return URI(this->toString());
}

////////////////////////////////////////////////////////////////////////////////
void URL::set(const String& protocol, const String& host, int port, const String& file, const String& ref) {

    if (impl->url.getProtocol().isEmpty()) {
        impl->url.setProtocol(protocol);
    }

    impl->url.setHost(host);
    impl->url.setFile(file);
    impl->url.setPort(port);
    impl->url.setRef(ref);
    impl->url.setHashCode(-1);

    impl->fixURL(true);
}

////////////////////////////////////////////////////////////////////////////////
void URL::set(const String& protocol, const String& host, int port,
              const String& authority, const String& userInfo,
              const String& path, const String& query, const String& ref) {

    String filePart = path;
    if (!query.isEmpty()) {
        if (!filePart.isEmpty()) {
            filePart = filePart.concat("?").concat(query);
        } else {
            filePart = String("?").concat(query);
        }
    }
    set(protocol, host, port, filePart, ref);

    impl->url.setAuthority(authority);
    impl->url.setUserInfo(userInfo);
    impl->url.setPath(path);
    impl->url.setQuery(query);
}

////////////////////////////////////////////////////////////////////////////////
URLStreamHandler* URL::getURLStreamHandler() const {
    return this->impl->streamHandler.get();
}

////////////////////////////////////////////////////////////////////////////////
void URL::setURLStreamHandlerFactory(URLStreamHandlerFactory* factory) {
    URLStreamHandlerManager* manager = URLStreamHandlerManager::getInstance();
    manager->setURLStreamHandlerFactory(factory);
}
<commit_msg>fix a memory leak<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "URL.h"

#include <decaf/lang/Integer.h>
#include <decaf/lang/String.h>
#include <decaf/lang/Pointer.h>
#include <decaf/net/URI.h>
#include <decaf/net/URLConnection.h>
#include <decaf/net/URLStreamHandler.h>
#include <decaf/net/URLStreamHandlerFactory.h>
#include <decaf/net/MalformedURLException.h>
#include <decaf/lang/exceptions/IllegalArgumentException.h>
#include <decaf/internal/net/URLType.h>
#include <decaf/internal/net/URLUtils.h>
#include <decaf/util/HashMap.h>
#include <decaf/util/concurrent/Mutex.h>

#include <decaf/internal/net/URLStreamHandlerManager.h>

using namespace std;
using namespace decaf;
using namespace decaf::io;
using namespace decaf::net;
using namespace decaf::internal;
using namespace decaf::internal::net;
using namespace decaf::util;
using namespace decaf::util::concurrent;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
using namespace decaf::internal;
using namespace decaf::internal::net;

////////////////////////////////////////////////////////////////////////////////
namespace decaf {
namespace net {

    class URLImpl {
    public:

        URLType url;
        Pointer<URLStreamHandler> streamHandler;

    public:

        URLImpl() : url(), streamHandler() {}

        void fixURL(bool fixHost) {
            int index;
            if (!url.getHost().isEmpty()) {
                url.setAuthority(url.getHost());
                if (url.getPort() != -1) {
                    url.setAuthority(url.getAuthority() + ":" + Integer::toString(url.getPort()));
                }
            }

            if (fixHost) {
                String host = url.getHost();
                if (!host.isEmpty() && (index = host.lastIndexOf('@')) > -1) {
                    url.setUserInfo(host.substring(0, index));
                    url.setHost(host.substring(index + 1));
                } else {
                    url.setUserInfo("");
                }
            }

            String file = url.getFile();
            if (!file.isEmpty() && (index = file.indexOf('?')) > -1) {
                url.setQuery(file.substring(index + 1));
                url.setPath(file.substring(0, index));
            } else {
                url.setQuery("");
                url.setPath(url.getFile());
            }
        }

        /**
         * Sets the receiver's stream handler to one which is appropriate for its
         * protocol. Throws a MalformedURLException if no reasonable handler is
         * available.
         *

         * Note that this will overwrite any existing stream handler with the new
         * one. Senders must check if the streamHandler is NULL before calling the
         * method if they do not want this behavior (a speed optimization).
         */
        void setupStreamHandler() {
            URLStreamHandlerManager* manager = URLStreamHandlerManager::getInstance();
            streamHandler.reset(manager->getURLStreamHandler(url.getProtocol()));
        }
    };

}}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& url) : impl(new URLImpl) {
    initialize(NULL, url, NULL);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const URL& context, const String& spec) : impl(new URLImpl) {
    initialize(&context, spec, NULL);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const URL& context, const String& spec, URLStreamHandler* streamHandler) : impl(new URLImpl) {
    initialize(&context, spec, streamHandler);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& protocol, const String& host, int port,
         const String& file, URLStreamHandler* handler) : impl(new URLImpl) {
    initialize(protocol, host, port, file, handler);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& protocol, const String& host, const String& file) : impl(new URLImpl) {
    initialize(protocol, host, -1, file, NULL);
}

////////////////////////////////////////////////////////////////////////////////
URL::URL(const String& protocol, const String& host, int port, const String& file) : impl(new URLImpl) {
    initialize(protocol, host, port, file, NULL);
}

////////////////////////////////////////////////////////////////////////////////
void URL::initialize(const URL* context, const String& theSpec, URLStreamHandler* handler) {

    // If we throw in this method the constructor does not complete, so we
    // need to protect against a leak of the URLImpl and release at the end.
    Pointer<URLImpl> finalizer(impl);

    if (handler != NULL) {
        impl->streamHandler.reset(handler);
    }

    String spec = theSpec.trim();  // trim

    // The spec includes a protocol if it includes a colon character
    // before the first occurrence of a slash character.
    String protocol = URLUtils::getSchemePrefix(spec);
    impl->url.setProtocol(protocol);
    int schemeSpecificPartStart = !protocol.isEmpty() ? (protocol.length() + 1) : 0;

    // If the context URL has a different protocol, discard it because we can't use it.
    if (!protocol.isEmpty() && context != NULL && !protocol.equals(context->getProtocol())) {
        context = NULL;
    }

    // Inherit from the context URL if it exists.
    if (context != NULL) {
        set(context->getProtocol(), context->getHost(), context->getPort(),
            context->getAuthority(), context->getUserInfo(), context->getPath(),
            context->getQuery(), String());

        if (impl->streamHandler == NULL) {
            impl->streamHandler = context->impl->streamHandler;
        }
    } else if (protocol.isEmpty()) {
        throw MalformedURLException(
            __FILE__, __LINE__,
            (std::string("Protocol not found: ") + spec.toString()).c_str());
    }

    // If the stream handler has not been determined, set it
    // to the default for the specified protocol.
    if (impl->streamHandler == NULL) {
        impl->setupStreamHandler();
        if (impl->streamHandler == NULL) {
            throw MalformedURLException(
                __FILE__, __LINE__,
                (std::string("unknown protocol: ") + impl->url.getProtocol().toString()).c_str());
        }
    }

    // Let the handler parse the URL. If the handler throws any exception, then
    // throw MalformedURLException instead.
    try {
        impl->streamHandler->parseURL(*this, spec, schemeSpecificPartStart, spec.length());
    } catch (Exception& e) {
        throw MalformedURLException(__FILE__, __LINE__, e.getMessage().c_str());
    }

    if (impl->url.getPort() < -1) {
        throw MalformedURLException(
            __FILE__, __LINE__, "port out of range: %d", impl->url.getPort());
    }

    finalizer.release();
}

////////////////////////////////////////////////////////////////////////////////
void URL::initialize(const String& protocol, const String& host, int port,
                     const String& file, URLStreamHandler* handler) {

    // If we throw in this method the constructor does not complete, so we
    // need to protect against a leak of the URLImpl and release at the end.
    Pointer<URLImpl> finalizer(impl);

    if (port < -1) {
        throw MalformedURLException(__FILE__, __LINE__, "Port out of range: %d", port);
    }

    if (protocol.isEmpty()) {
        throw NullPointerException(
        __FILE__, __LINE__, "Unknown protocol: %s", "NULL");
    }

    String theHost;

    if (host.indexOf(":") != -1 && host.charAt(0) != '[') {
        theHost = String("[").concat(host).concat("]");
    } else {
        theHost = host;
    }

    impl->url.setProtocol(protocol);
    impl->url.setHost(theHost);
    impl->url.setPort(port);

    String theFile = URLUtils::authoritySafePath(theHost, file);

    // Set the fields from the arguments. Handle the case where the
    // passed in "file" includes both a file and a reference part.
    int hash = theFile.indexOf("#");
    if (hash >= 0) {
        impl->url.setFile(theFile.substring(0, hash));
        impl->url.setRef(theFile.substring(hash + 1));
    } else {
        impl->url.setFile(theFile);
    }
    impl->fixURL(false);

    // Set the stream handler for the URL either to the handler argument if it was
    // specified, or to the default for the receiver's protocol if the handler was NULL.
    if (handler == NULL) {
        impl->setupStreamHandler();
        if (impl->streamHandler == NULL) {
            throw MalformedURLException(
                __FILE__, __LINE__, (std::string("Unknown protocol: ") + protocol.toString()).c_str());
        }
    } else {
        impl->streamHandler.reset(handler);
    }

    finalizer.release();
}

////////////////////////////////////////////////////////////////////////////////
URL::~URL() {
    try {
        delete impl;
    }
    DECAF_CATCHALL_NOTHROW()
}

////////////////////////////////////////////////////////////////////////////////
bool URL::equals(const URL& other) const {
    return impl->streamHandler->equals(*this, other);
}

////////////////////////////////////////////////////////////////////////////////
String URL::getAuthority() const {
    return impl->url.getAuthority();
}

////////////////////////////////////////////////////////////////////////////////
int URL::getDefaultPort() const {
    return impl->streamHandler->getDefaultPort();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getFile() const {
    return impl->url.getFile();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getHost() const {
    return impl->url.getHost();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getPath() const {
    return impl->url.getPath();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getUserInfo() const {
    return impl->url.getUserInfo();
}

////////////////////////////////////////////////////////////////////////////////
int URL::getPort() const {
    return impl->url.getPort();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getProtocol() const {
    return impl->url.getProtocol();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getQuery() const {
    return impl->url.getQuery();
}

////////////////////////////////////////////////////////////////////////////////
String URL::getRef() const {
    return impl->url.getRef();
}

////////////////////////////////////////////////////////////////////////////////
int URL::hashCode() const {
    int hashCode = impl->url.getHashCode();
    if (hashCode == -1) {
        hashCode = impl->streamHandler->hashCode(*this);
        impl->url.setHashCode(hashCode);
    }

    return hashCode;
}

////////////////////////////////////////////////////////////////////////////////
URLConnection* URL::openConnection() {
    return impl->streamHandler->openConnection(*this);
}

////////////////////////////////////////////////////////////////////////////////
URLConnection* URL::openConnection(const Proxy* proxy) {
    if (proxy == NULL) {
        throw IllegalArgumentException(__FILE__, __LINE__, "proxy should not be NULL");
    }

    return impl->streamHandler->openConnection(*this, proxy);
}

////////////////////////////////////////////////////////////////////////////////
InputStream* URL::openStream() {
    return NULL;  // TODO figure out Connection lifetime
}

////////////////////////////////////////////////////////////////////////////////
bool URL::sameFile(const URL& other) const {
    if (impl->streamHandler == NULL) {
        throw MalformedURLException(
            __FILE__, __LINE__, (std::string("Unknown protocol: ") + getProtocol().toString()).c_str());
    }
    return impl->streamHandler->sameFile(*this, other);
}

////////////////////////////////////////////////////////////////////////////////
String URL::toExternalForm() const {
    if (impl->streamHandler == NULL) {
        return String("unknown protocol(").concat(getProtocol()).concat(")://").concat(getHost()).concat(getFile());
    }
    return impl->streamHandler->toExternalForm(*this);
}

////////////////////////////////////////////////////////////////////////////////
std::string URL::toString() const {
    return toExternalForm().toString();
}

////////////////////////////////////////////////////////////////////////////////
URI URL::toURI() const {
    return URI(this->toString());
}

////////////////////////////////////////////////////////////////////////////////
void URL::set(const String& protocol, const String& host, int port, const String& file, const String& ref) {

    if (impl->url.getProtocol().isEmpty()) {
        impl->url.setProtocol(protocol);
    }

    impl->url.setHost(host);
    impl->url.setFile(file);
    impl->url.setPort(port);
    impl->url.setRef(ref);
    impl->url.setHashCode(-1);

    impl->fixURL(true);
}

////////////////////////////////////////////////////////////////////////////////
void URL::set(const String& protocol, const String& host, int port,
              const String& authority, const String& userInfo,
              const String& path, const String& query, const String& ref) {

    String filePart = path;
    if (!query.isEmpty()) {
        if (!filePart.isEmpty()) {
            filePart = filePart.concat("?").concat(query);
        } else {
            filePart = String("?").concat(query);
        }
    }
    set(protocol, host, port, filePart, ref);

    impl->url.setAuthority(authority);
    impl->url.setUserInfo(userInfo);
    impl->url.setPath(path);
    impl->url.setQuery(query);
}

////////////////////////////////////////////////////////////////////////////////
URLStreamHandler* URL::getURLStreamHandler() const {
    return this->impl->streamHandler.get();
}

////////////////////////////////////////////////////////////////////////////////
void URL::setURLStreamHandlerFactory(URLStreamHandlerFactory* factory) {
    URLStreamHandlerManager* manager = URLStreamHandlerManager::getInstance();
    manager->setURLStreamHandlerFactory(factory);
}
<|endoftext|>


<commit_before>/*
 * Originally written by Xinef - Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
*/

#include "gruuls_lair.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellScript.h"

enum Yells
{
    SAY_AGGRO                   = 0,
    SAY_SLAM                    = 1,
    SAY_SHATTER                 = 2,
    SAY_SLAY                    = 3,
    SAY_DEATH                   = 4,

    EMOTE_GROW                  = 5
};

enum Spells
{
    SPELL_GROWTH                = 36300,
    SPELL_CAVE_IN               = 36240,
    SPELL_GROUND_SLAM           = 33525,
    SPELL_REVERBERATION         = 36297,
    SPELL_HURTFUL_STRIKE        = 33813,
    SPELL_SHATTER               = 33654,

    SPELL_SHATTER_EFFECT        = 33671,
    SPELL_STONED                = 33652,
};

enum Events
{
    EVENT_GROWTH                = 1,
    EVENT_CAVE_IN               = 2,
    EVENT_GROUND_SLAM           = 3,
    EVENT_HURTFUL_STRIKE        = 4,
    EVENT_REVERBERATION         = 5,
    EVENT_SHATTER               = 6,
    EVENT_RECENTLY_SPOKEN       = 7
};

class boss_gruul : public CreatureScript
{
public:
    boss_gruul() : CreatureScript("boss_gruul") { }

    struct boss_gruulAI : public BossAI
    {
        boss_gruulAI(Creature* creature) : BossAI(creature, DATA_GRUUL) { }

        void Reset() override
        {
            _Reset();
            _caveInTimer = 29000;
        }

        void EnterCombat(Unit* /*who*/) override
        {
            _EnterCombat();
            Talk(SAY_AGGRO);

            events.ScheduleEvent(EVENT_GROWTH, 30000);
            events.ScheduleEvent(EVENT_CAVE_IN, _caveInTimer);
            events.ScheduleEvent(EVENT_REVERBERATION, 20000);
            events.ScheduleEvent(EVENT_HURTFUL_STRIKE, 10000);
            events.ScheduleEvent(EVENT_GROUND_SLAM, 35000);
        }

        void KilledUnit(Unit*  /*who*/) override
        {
            if (events.GetNextEventTime(EVENT_RECENTLY_SPOKEN) == 0)
            {
                events.ScheduleEvent(EVENT_RECENTLY_SPOKEN, 5000);
                Talk(SAY_SLAY);
            }
        }

        void JustDied(Unit* /*killer*/) override
        {
            _JustDied();
            Talk(SAY_DEATH);
        }

        void UpdateAI(uint32 diff) override
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);
            if (me->HasUnitState(UNIT_STATE_CASTING))
                return;

            switch (events.ExecuteEvent())
            {
                case EVENT_GROWTH:
                    Talk(EMOTE_GROW);
                    DoCast(me, SPELL_GROWTH);
                    events.ScheduleEvent(EVENT_GROWTH, 30000);
                    break;
                case EVENT_CAVE_IN:
                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                        me->CastSpell(target, SPELL_CAVE_IN, false);
                    if (_caveInTimer >= 4000)
                        _caveInTimer -= 1500;
                    events.ScheduleEvent(EVENT_CAVE_IN, _caveInTimer);
                    break;
                case EVENT_REVERBERATION:
                    me->CastSpell(me, SPELL_REVERBERATION, false);
                    events.ScheduleEvent(EVENT_REVERBERATION, 22000);
                    break;
                case EVENT_HURTFUL_STRIKE:
                    if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1, 5.0f))
                        me->CastSpell(target, SPELL_HURTFUL_STRIKE, false);
                    events.ScheduleEvent(EVENT_HURTFUL_STRIKE, 15000);
                    break;
                case EVENT_GROUND_SLAM:
                    Talk(SAY_SLAM);
                    me->CastSpell(me, SPELL_GROUND_SLAM, false);
                    events.DelayEvents(8001);
                    events.ScheduleEvent(EVENT_GROUND_SLAM, 60000);
                    events.ScheduleEvent(EVENT_SHATTER, 8000);
                    break;
                case EVENT_SHATTER:
                    Talk(SAY_SHATTER);
                    me->CastSpell(me, SPELL_SHATTER, false);
                    break;
            }

            DoMeleeAttackIfReady();
        }

    private:
        uint32 _caveInTimer;
    };

    CreatureAI* GetAI(Creature* creature) const override
    {
        return GetInstanceAI<boss_gruulAI>(creature);
    }
};

class spell_gruul_ground_slam : public SpellScriptLoader
{
public:
    spell_gruul_ground_slam() : SpellScriptLoader("spell_gruul_ground_slam") { }

    class spell_gruul_ground_slam_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_gruul_ground_slam_SpellScript);

        void HandleScriptEffect(SpellEffIndex /*effIndex*/)
        {
            if (Unit* target = GetHitUnit())
                target->KnockbackFrom(GetCaster()->GetPositionX(), GetCaster()->GetPositionY(), 15.0f, 15.0f);
        }

        void Register() override
        {
            OnEffectHitTarget += SpellEffectFn(spell_gruul_ground_slam_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_gruul_ground_slam_SpellScript();
    }
};

class spell_gruul_ground_slam_trigger : public SpellScriptLoader
{
public:
    spell_gruul_ground_slam_trigger() : SpellScriptLoader("spell_gruul_ground_slam_trigger") { }

    class spell_gruul_ground_slam_trigger_AuraScript : public AuraScript
    {
        PrepareAuraScript(spell_gruul_ground_slam_trigger_AuraScript);

        void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
        {
            if (GetUnitOwner()->GetAuraCount(GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell) == 5)
                GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_STONED, true);
        }

        void Register() override
        {
            AfterEffectRemove += AuraEffectRemoveFn(spell_gruul_ground_slam_trigger_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
        }
    };

    AuraScript* GetAuraScript() const override
    {
        return new spell_gruul_ground_slam_trigger_AuraScript();
    }
};

class spell_gruul_shatter : public SpellScriptLoader
{
public:
    spell_gruul_shatter() : SpellScriptLoader("spell_gruul_shatter") { }

    class spell_gruul_shatter_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_gruul_shatter_SpellScript);

        void HandleScriptEffect(SpellEffIndex /*effIndex*/)
        {
            if (Unit* target = GetHitUnit())
            {
                target->RemoveAurasDueToSpell(SPELL_STONED);
                target->CastSpell((Unit*)nullptr, SPELL_SHATTER_EFFECT, true);
            }
        }

        void Register() override
        {
            OnEffectHitTarget += SpellEffectFn(spell_gruul_shatter_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_gruul_shatter_SpellScript();
    }
};

class spell_gruul_shatter_effect : public SpellScriptLoader
{
public:
    spell_gruul_shatter_effect() : SpellScriptLoader("spell_gruul_shatter_effect") { }

    class spell_gruul_shatter_effect_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_gruul_shatter_effect_SpellScript);

        void CalculateDamage()
        {
            if (!GetHitUnit())
                return;

            float radius = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster());
            if (!radius)
                return;

            float distance = GetCaster()->GetDistance2d(GetHitUnit());
            if (distance > 1.0f)
                SetHitDamage(int32(GetHitDamage() * ((radius - distance) / radius)));
        }

        void Register() override
        {
            OnHit += SpellHitFn(spell_gruul_shatter_effect_SpellScript::CalculateDamage);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_gruul_shatter_effect_SpellScript();
    }
};

void AddSC_boss_gruul()
{
    new boss_gruul();
    new spell_gruul_ground_slam();
    new spell_gruul_ground_slam_trigger();
    new spell_gruul_shatter();
    new spell_gruul_shatter_effect();
}
<commit_msg>fix(scripts/Gruul): Boss script fine tuning (#4126)<commit_after>/*
 * Originally written by Xinef - Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
*/

#include "gruuls_lair.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
#include "SpellScript.h"

enum Yells
{
    SAY_AGGRO                   = 0,
    SAY_SLAM                    = 1,
    SAY_SHATTER                 = 2,
    SAY_SLAY                    = 3,
    SAY_DEATH                   = 4,

    EMOTE_GROW                  = 5
};

enum Spells
{
    SPELL_GROWTH                = 36300,
    SPELL_CAVE_IN               = 36240,
    SPELL_GROUND_SLAM           = 33525,
    SPELL_REVERBERATION         = 36297,
    SPELL_HURTFUL_STRIKE        = 33813,
    SPELL_SHATTER               = 33654,

    SPELL_SHATTER_EFFECT        = 33671,
    SPELL_STONED                = 33652,
};

enum Events
{
    EVENT_GROWTH                = 1,
    EVENT_CAVE_IN               = 2,
    EVENT_GROUND_SLAM           = 3,
    EVENT_HURTFUL_STRIKE        = 4,
    EVENT_REVERBERATION         = 5,
    EVENT_SHATTER               = 6,
    EVENT_RECENTLY_SPOKEN       = 7
};

class boss_gruul : public CreatureScript
{
public:
    boss_gruul() : CreatureScript("boss_gruul") { }

    struct boss_gruulAI : public BossAI
    {
        boss_gruulAI(Creature* creature) : BossAI(creature, DATA_GRUUL) { }

        void Reset() override
        {
            _Reset();
            _caveInTimer = 29000;
        }

        void EnterCombat(Unit* /*who*/) override
        {
            _EnterCombat();
            Talk(SAY_AGGRO);

            events.ScheduleEvent(EVENT_GROWTH, 30000);
            events.ScheduleEvent(EVENT_CAVE_IN, _caveInTimer);
            events.ScheduleEvent(EVENT_REVERBERATION, 20000);
            events.ScheduleEvent(EVENT_HURTFUL_STRIKE, 10000);
            events.ScheduleEvent(EVENT_GROUND_SLAM, 35000);
        }

        void KilledUnit(Unit*  /*who*/) override
        {
            if (events.GetNextEventTime(EVENT_RECENTLY_SPOKEN) == 0)
            {
                events.ScheduleEvent(EVENT_RECENTLY_SPOKEN, 5000);
                Talk(SAY_SLAY);
            }
        }

        void JustDied(Unit* /*killer*/) override
        {
            _JustDied();
            Talk(SAY_DEATH);
        }

        void UpdateAI(uint32 diff) override
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);
            if (me->HasUnitState(UNIT_STATE_CASTING))
                return;

            switch (events.ExecuteEvent())
            {
                case EVENT_GROWTH:
                    Talk(EMOTE_GROW);
                    DoCast(me, SPELL_GROWTH);
                    events.ScheduleEvent(EVENT_GROWTH, 30000);
                    break;
                case EVENT_CAVE_IN:
                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
                        me->CastSpell(target, SPELL_CAVE_IN, false);
                    if (_caveInTimer >= 4000)
                        _caveInTimer -= 1500;
                    events.ScheduleEvent(EVENT_CAVE_IN, _caveInTimer);
                    break;
                case EVENT_REVERBERATION:
                    me->CastSpell(me, SPELL_REVERBERATION, false);
                    events.ScheduleEvent(EVENT_REVERBERATION, 22000);
                    break;
                case EVENT_HURTFUL_STRIKE:
                    if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1, 5.0f))
                    {
                        me->CastSpell(target, SPELL_HURTFUL_STRIKE, false);
                    }
                    else
                    {
                        me->CastSpell(me->GetVictim(), SPELL_HURTFUL_STRIKE, false);
                    }
                    events.ScheduleEvent(EVENT_HURTFUL_STRIKE, 15000);
                    break;
                case EVENT_GROUND_SLAM:
                    Talk(SAY_SLAM);
                    me->CastSpell(me, SPELL_GROUND_SLAM, false);
                    events.DelayEvents(8001);
                    events.ScheduleEvent(EVENT_GROUND_SLAM, 60000);
                    events.ScheduleEvent(EVENT_SHATTER, 8000);
                    me->SetControlled(true, UNIT_STATE_ROOT);
                    break;
                case EVENT_SHATTER:
                    Talk(SAY_SHATTER);
                    me->SetControlled(false, UNIT_STATE_ROOT);
                    me->CastSpell(me, SPELL_SHATTER, false);
                    break;
            }

            if (!me->HasUnitState(UNIT_STATE_ROOT))
            {
                DoMeleeAttackIfReady();
            }
        }

    private:
        uint32 _caveInTimer;
    };

    CreatureAI* GetAI(Creature* creature) const override
    {
        return GetInstanceAI<boss_gruulAI>(creature);
    }
};

class spell_gruul_ground_slam : public SpellScriptLoader
{
public:
    spell_gruul_ground_slam() : SpellScriptLoader("spell_gruul_ground_slam") { }

    class spell_gruul_ground_slam_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_gruul_ground_slam_SpellScript);

        void HandleScriptEffect(SpellEffIndex /*effIndex*/)
        {
            if (Unit* target = GetHitUnit())
                target->KnockbackFrom(GetCaster()->GetPositionX(), GetCaster()->GetPositionY(), 15.0f, 15.0f);
        }

        void Register() override
        {
            OnEffectHitTarget += SpellEffectFn(spell_gruul_ground_slam_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_gruul_ground_slam_SpellScript();
    }
};

class spell_gruul_ground_slam_trigger : public SpellScriptLoader
{
public:
    spell_gruul_ground_slam_trigger() : SpellScriptLoader("spell_gruul_ground_slam_trigger") { }

    class spell_gruul_ground_slam_trigger_AuraScript : public AuraScript
    {
        PrepareAuraScript(spell_gruul_ground_slam_trigger_AuraScript);

        void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
        {
            if (GetUnitOwner()->GetAuraCount(GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell) == 5)
                GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_STONED, true);
        }

        void Register() override
        {
            AfterEffectRemove += AuraEffectRemoveFn(spell_gruul_ground_slam_trigger_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
        }
    };

    AuraScript* GetAuraScript() const override
    {
        return new spell_gruul_ground_slam_trigger_AuraScript();
    }
};

class spell_gruul_shatter : public SpellScriptLoader
{
public:
    spell_gruul_shatter() : SpellScriptLoader("spell_gruul_shatter") { }

    class spell_gruul_shatter_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_gruul_shatter_SpellScript);

        void HandleScriptEffect(SpellEffIndex /*effIndex*/)
        {
            if (Unit* target = GetHitUnit())
            {
                target->RemoveAurasDueToSpell(SPELL_STONED);
                target->CastSpell((Unit*)nullptr, SPELL_SHATTER_EFFECT, true);
            }
        }

        void Register() override
        {
            OnEffectHitTarget += SpellEffectFn(spell_gruul_shatter_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_gruul_shatter_SpellScript();
    }
};

class spell_gruul_shatter_effect : public SpellScriptLoader
{
public:
    spell_gruul_shatter_effect() : SpellScriptLoader("spell_gruul_shatter_effect") { }

    class spell_gruul_shatter_effect_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_gruul_shatter_effect_SpellScript);

        void CalculateDamage()
        {
            if (!GetHitUnit())
                return;

            float radius = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster());
            if (!radius)
                return;

            float distance = GetCaster()->GetDistance2d(GetHitUnit());
            if (distance > 1.0f)
                SetHitDamage(int32(GetHitDamage() * ((radius - distance) / radius)));
        }

        void Register() override
        {
            OnHit += SpellHitFn(spell_gruul_shatter_effect_SpellScript::CalculateDamage);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_gruul_shatter_effect_SpellScript();
    }
};

void AddSC_boss_gruul()
{
    new boss_gruul();
    new spell_gruul_ground_slam();
    new spell_gruul_ground_slam_trigger();
    new spell_gruul_shatter();
    new spell_gruul_shatter_effect();
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include "refalrts-platform-specific.h"

int refalrts::api::system(const char *command) {
  int retcode = ::system(command);

  if (retcode != -1) {
    if (WIFEXITED(retcode)) {
      retcode = WEXITSTATUS(retcode);
    } else {
      retcode = -1;
    }
  }

  return retcode;
}

bool refalrts::api::get_current_directory(char buffer[], size_t size) {
  return getcwd(buffer, size) != 0;
}

refalrts::RefalNumber refalrts::api::get_pid() {
  return static_cast<refalrts::RefalNumber>(::getpid());
}

refalrts::RefalNumber refalrts::api::get_ppid() {
  return static_cast<refalrts::RefalNumber>(::getppid());
}

struct refalrts::api::stat {
  struct ::stat stat;
};

const refalrts::api::stat *
refalrts::api::stat_create(const char *filename) {
  refalrts::api::stat *api_stat = new ::refalrts::api::stat();
  int res = ::stat(filename, &api_stat->stat);
  if (res == 0) {
    return api_stat;
  } else {
    delete api_stat;
    return 0;
  }
}

signed refalrts::api::stat_compare(
  const refalrts::api::stat *left, const refalrts::api::stat *right
) {
  if (left->stat.st_dev < right->stat.st_dev) {
    return -1;
  } else if (left->stat.st_dev > right->stat.st_dev) {
    return +1;
  } else if (left->stat.st_ino < right->stat.st_ino) {
    return -1;
  } else if (left->stat.st_ino > right->stat.st_ino) {
    return +1;
  } else {
    return 0;
  }
}

void refalrts::api::stat_destroy(const refalrts::api::stat *stat) {
  delete stat;
}

const char refalrts::api::path_env_separator = ':';
const char *const refalrts::api::directory_separators = "/";

bool refalrts::api::is_directory_ended_to_separator(const char *directory) {
  size_t len = strlen(directory);
  return (len == 0) || directory[len - 1] == '/';
}

bool refalrts::api::is_single_file_name(const char *name) {
  return strchr(name, '/') == 0;
}

const char *refalrts::api::default_lib_extension = ".so";

struct refalrts::api::ClockNs {
  struct timespec start_of_program;
};

refalrts::api::ClockNs *refalrts::api::init_clock_ns() {
  ClockNs *res = new ClockNs;
  clock_gettime(CLOCK_REALTIME, &res->start_of_program);
  return res;
}

double refalrts::api::clock_ns(refalrts::api::ClockNs *clk) {
  struct timespec now;
  struct timespec start = clk->start_of_program;

  clock_gettime(CLOCK_REALTIME, &now);

  return (now.tv_sec - start.tv_sec) * 1.0e9 + (now.tv_nsec - start.tv_nsec);
}

void refalrts::api::free_clock_ns(refalrts::api::ClockNs *clk) {
  delete clk;
}
<commit_msg>Ускорение сборки на Windows Subsystem for Linux (#206)<commit_after>#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include "refalrts-platform-specific.h"

int refalrts::api::system(const char *command) {
  int retcode = ::system(command);

  if (retcode != -1) {
    if (WIFEXITED(retcode)) {
      retcode = WEXITSTATUS(retcode);
    } else {
      retcode = -1;
    }
  }

  return retcode;
}

bool refalrts::api::get_current_directory(char buffer[], size_t size) {
  return getcwd(buffer, size) != 0;
}

refalrts::RefalNumber refalrts::api::get_pid() {
  return static_cast<refalrts::RefalNumber>(::getpid());
}

refalrts::RefalNumber refalrts::api::get_ppid() {
  return static_cast<refalrts::RefalNumber>(::getppid());
}

struct refalrts::api::stat {
  struct ::stat stat;
};

const refalrts::api::stat *
refalrts::api::stat_create(const char *filename) {
  refalrts::api::stat *api_stat = new ::refalrts::api::stat();
  int res = ::stat(filename, &api_stat->stat);
  if (res == 0) {
    return api_stat;
  } else {
    delete api_stat;
    return 0;
  }
}

signed refalrts::api::stat_compare(
  const refalrts::api::stat *left, const refalrts::api::stat *right
) {
  if (left->stat.st_dev < right->stat.st_dev) {
    return -1;
  } else if (left->stat.st_dev > right->stat.st_dev) {
    return +1;
  } else if (left->stat.st_ino < right->stat.st_ino) {
    return -1;
  } else if (left->stat.st_ino > right->stat.st_ino) {
    return +1;
  } else {
    return 0;
  }
}

void refalrts::api::stat_destroy(const refalrts::api::stat *stat) {
  delete stat;
}

const char refalrts::api::path_env_separator = ':';
const char *const refalrts::api::directory_separators = "/";

bool refalrts::api::is_directory_ended_to_separator(const char *directory) {
  size_t len = strlen(directory);
  return (len == 0) || directory[len - 1] == '/';
}

bool refalrts::api::is_single_file_name(const char *name) {
  return strchr(name, '/') == 0;
}

const char *refalrts::api::default_lib_extension = ".so";

#ifndef REFAL_5_LAMBDA_SKIP_GETTIME
#define REFAL_5_LAMBDA_SKIP_GETTIME 0
#endif  /* ifdef REFAL_5_LAMBDA_SKIP_GETTIME */

struct refalrts::api::ClockNs {
  struct timespec start_of_program;
#if REFAL_5_LAMBDA_SKIP_GETTIME
  struct timespec now;
#endif /* REFAL_5_LAMBDA_SKIP_GETTIME */
};

refalrts::api::ClockNs *refalrts::api::init_clock_ns() {
  ClockNs *res = new ClockNs;
  clock_gettime(CLOCK_REALTIME, &res->start_of_program);
#if REFAL_5_LAMBDA_SKIP_GETTIME
  memcpy(&res->now, &res->start_of_program, sizeof(res->now));
#endif  /* REFAL_5_LAMBDA_SKIP_GETTIME */
  return res;
}

double refalrts::api::clock_ns(refalrts::api::ClockNs *clk) {
  struct timespec now;
  struct timespec start = clk->start_of_program;

#if REFAL_5_LAMBDA_SKIP_GETTIME
  static long skip = 0;

  if (skip++ % REFAL_5_LAMBDA_SKIP_GETTIME == 0) {
    clock_gettime(CLOCK_REALTIME, &clk->now);
  }
  memcpy(&now, &clk->now, sizeof(now));
#else  /* REFAL_5_LAMBDA_SKIP_GETTIME */
  clock_gettime(CLOCK_REALTIME, &now);
#endif  /* REFAL_5_LAMBDA_SKIP_GETTIME */

  return (now.tv_sec - start.tv_sec) * 1.0e9 + (now.tv_nsec - start.tv_nsec);
}

void refalrts::api::free_clock_ns(refalrts::api::ClockNs *clk) {
  delete clk;
}
<|endoftext|>


<commit_before>#ifndef MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#define MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/RandomNumberGenerator.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/core/ForceField.hpp>
#include <mjolnir/core/SystemMotionRemover.hpp>
#include <mjolnir/core/Unit.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

// g-BAOAB Langevin integrator developed by the following papers
// Leimkuhler B., Matthews C., Proc. R. Soc. A Math. Phys. Eng. Sci. (2016)
template<typename traitsT>
class gBAOABLangevinIntegrator
{
  public:
    using traits_type                = traitsT;
    using real_type                  = typename traits_type::real_type;
    using coordinate_type            = typename traits_type::coordinate_type;
    using indices_type               = std::array<std::size_t, 2>;
    using system_type                = System<traitsT>;
    using forcefield_type            = ForceField<traitsT>;
    using constraint_forcefield_type = typename forcefield_type::constraint_forcefield_type;
    using constraint_type            = std::pair<indices_type, real_type>;
    using constraints_type           = std::vector<constraint_type>;
    using rng_type                   = RandomNumberGenerator<traits_type>;
    using remover_type               = SystemMotionRemover<traits_type>;

  public:

    gBAOABLangevinIntegrator(const real_type dt, std::vector<real_type>&& gamma,
                             remover_type&& remover)
        : dt_(dt), halfdt_(dt / 2), gammas_(std::move(gamma)),
          exp_gamma_dt_(gammas_.size()), noise_coeff_ (gammas_.size()),
          remover_(std::move(remover)),
          old_position_(gammas_.size()),
          old_pos_rattle_(gammas_.size())
    {}
    ~gBAOABLangevinIntegrator() = default;

    void initialize(system_type& sys, forcefield_type& ff, rng_type& rng);

    real_type step(const real_type time, system_type& sys, forcefield_type& ff,
                   rng_type& rng);

    void update(const system_type& sys)
    {
        if(!sys.has_attribute("temperature"))
        {
            throw std::out_of_range("mjolnir::g-BAOABLangevinIntegrator: "
                "Langevin Integrator requires reference temperature, but "
                "`temperature` is not found in `system.attribute`.");
        }
        this->temperature_ = sys.attribute("temperature");
        this->reset_parameter(sys);
        return;
    }

    real_type delta_t() const noexcept {return dt_;}
    std::vector<real_type> const& parameters() const noexcept {return gammas_;}

  private:

    void reset_parameter(const system_type& sys) noexcept
    {
        const auto kBT = physics::constants<real_type>::kB() * this->temperature_;
        for(std::size_t i=0; i<sys.size(); ++i)
        {
            const auto gamma     = this->gammas_.at(i);
            const auto gamma_dt  = -1 * gamma * this->dt_;
            this->exp_gamma_dt_.at(i) = std::exp(gamma_dt);
            this->noise_coeff_ .at(i) = std::sqrt(
                    kBT * (1 - std::exp(2 * gamma_dt)) * sys.rmass(i));
        }
        return;
    };

    coordinate_type gen_R(rng_type& rng) noexcept
    {
        const auto x = rng.gaussian();
        const auto y = rng.gaussian();
        const auto z = rng.gaussian();
        return math::make_coordinate<coordinate_type>(x, y, z);
    }

    void correct_coordinate(system_type& sys, const forcefield_type& ff)
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        std::size_t rattle_step = 0;
        const constraint_forcefield_type& constraint_ff = ff.constraint();
        const constraints_type&           constraints = constraint_ff.constraints();

        while(rattle_step<constraint_ff.max_iteration())
        {
            bool corrected = false;
            for(std::size_t i=0; i<constraints.size(); ++i)
            {
                const auto& indices_v0 = constraints[i];
                const auto& indices    = indices_v0.first;
                auto& p1 = sys.position(indices[0]);
                auto& p2 = sys.position(indices[1]);
                auto& v1 = sys.velocity(indices[0]);
                auto& v2 = sys.velocity(indices[1]);

                const auto      dp = sys.adjust_direction(p2 - p1);
                const real_type dp2 = math::length_sq(dp);
                const real_type missmatch2 = square_v0s_[i] - dp2;

                if(correction_tolerance_ < std::abs(missmatch2))
                {
                    auto& op1 = this->old_pos_rattle_[indices[0]];
                    auto& op2 = this->old_pos_rattle_[indices[1]];

                    const auto old_dp = sys.adjust_direction(op2 - op1);
                    const real_type dot_old_new_dp = math::dot_product(old_dp, dp);
                    const real_type lambda =
                        0.5 * missmatch2 * reduced_mass_[i] / dot_old_new_dp;
                    const coordinate_type correction_force = lambda * old_dp;
                    const auto& rm1 = sys.rmass(indices[0]);
                    const auto& rm2 = sys.rmass(indices[1]);
                    const coordinate_type correction_vec1  = correction_force * rm1;
                    const coordinate_type correction_vec2  = correction_force * rm2;
                    p1 -= correction_vec1;
                    p2 += correction_vec2;
                    v1 -= correction_vec1 * r_dt_in_correction_;
                    v2 += correction_vec2 * r_dt_in_correction_;

                    corrected = true;
                }
            }

            if(!corrected) {break;}

            ++rattle_step;
        }

        if(rattle_step >= constraint_ff.max_iteration())
        {
            MJOLNIR_LOG_WARN("coordinate rattle iteration number exceeds rattle max iteration");
        }

        return;
    }

    void correct_velocity(system_type& sys, const forcefield_type& ff)
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        const constraint_forcefield_type& constraint_ff = ff.constraint();
        const constraints_type&           constraints   = constraint_ff.constraints();

        std::size_t rattle_step = 0;
        while(rattle_step<constraint_ff.max_iteration())
        {
            bool corrected = false;
            for(std::size_t i=0; i<constraints.size(); ++i)
            {
                const auto& constraint       = constraints[i];
                const auto& indices          = constraint.first;
                auto& p1  = sys.position(indices[0]);
                auto& p2  = sys.position(indices[1]);
                auto& v1  = sys.velocity(indices[0]);
                auto& v2  = sys.velocity(indices[1]);

                const auto pos_diff      = sys.adjust_direction(p2 - p1);
                const auto vel_diff      = v2 - v1;
                const real_type dot_pdvd = math::dot_product(pos_diff, vel_diff);
                const real_type lambda   = dot_pdvd * reduced_mass_[i] * r_square_v0s_[i];

                if(correction_tolerance_ < std::abs(lambda))
                {
                    const auto& rm1 = sys.rmass(indices[0]);
                    const auto& rm2 = sys.rmass(indices[1]);

                    const auto correction_vec = lambda * pos_diff;
                    v1 += correction_vec * rm1;
                    v2 -= correction_vec * rm2;
                    corrected = true;
                }
            }

            if(!corrected) {break;}

            ++rattle_step;
        }

        if(constraint_ff.max_iteration() <= rattle_step)
        {
            MJOLNIR_LOG_WARN("velocity rattle iteration number exceeds rattle max iteration.");
        }
        return;
   }

  private:
    real_type   dt_;
    real_type   halfdt_;
    std::vector<real_type>       gammas_;
    std::vector<real_type>       exp_gamma_dt_;
    std::vector<real_type>       noise_coeff_;
    std::vector<real_type>       square_v0s_;
    std::vector<real_type>       r_square_v0s_;
    std::vector<real_type>       reduced_mass_;
    remover_type remover_;

    real_type   temperature_;
    real_type   correction_tolerance_;
    real_type   correction_tolerance_dt_;
    real_type   correction_tolerance_dt_itr_;
    real_type   dt_in_correction_;
    real_type   r_dt_in_correction_;

    static constexpr std::size_t correction_iter_num_ = 1;

    std::vector<coordinate_type> old_position_;
    std::vector<coordinate_type> old_pos_rattle_;

};

template<typename traitsT>
void gBAOABLangevinIntegrator<traitsT>::initialize(
        system_type& system, forcefield_type& ff, rng_type&)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    const constraint_forcefield_type& constraint_ff = ff.constraint();
    const constraints_type&           constraints   = constraint_ff.constraints();
    const real_type                   tolerance     = constraint_ff.tolerance();
    // calculate parameters for constraint
    this->correction_tolerance_        = tolerance;
    this->correction_tolerance_dt_     = tolerance / dt_;
    this->correction_tolerance_dt_itr_ = tolerance * 2. * correction_iter_num_ / dt_;
    this->dt_in_correction_            = dt_ * 0.5 / correction_iter_num_;
    this->r_dt_in_correction_          = 1. / dt_in_correction_;

    // calculate parameters for each particles
    this->update(system);

    // calculate force
    for(std::size_t i=0; i<system.size(); ++i)
    {
        system.force(i) = math::make_coordinate<coordinate_type>(0, 0, 0);
    }
    ff.calc_force(system);

    // buffering old position
    for(std::size_t i=0; i<system.size(); ++i)
    {
        old_position_[i] = system.position(i);
    }

    square_v0s_.resize(constraints.size());
    r_square_v0s_.resize(constraints.size());
    reduced_mass_.resize(constraints.size());
    for(std::size_t i=0; i<constraints.size(); ++i)
    {
        // calculate square v0
        square_v0s_[i] = std::pow(constraints[i].second, 2);
        r_square_v0s_[i] = 1.0 / square_v0s_[i];

        // calculate inverse reduced mass
        const auto& constraint = constraints[i];
        std::size_t first_idx  = constraint.first[0];
        std::size_t second_idx = constraint.first[1];
        reduced_mass_[i] = 1.0 / (system.rmass(first_idx) + system.rmass(second_idx));
    }
    MJOLNIR_LOG_INFO("huga");

    return;
}

template<typename traitsT>
typename gBAOABLangevinIntegrator<traitsT>::real_type
gBAOABLangevinIntegrator<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff, rng_type& rng)
{
    // B step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i)  += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    correct_velocity(sys, ff);

    // A step
    for(std::size_t correction_step=0; correction_step<correction_iter_num_; ++correction_step)
    {
        for(std::size_t i=0; i<sys.size(); ++i)
        {
            this->old_pos_rattle_[i] = sys.position(i);
            sys.position(i) += this->dt_in_correction_ * sys.velocity(i);
        }
        correct_coordinate(sys, ff);
        correct_velocity(sys, ff);
    }

    // O step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) *= this->exp_gamma_dt_[i]; // *= exp(- gamma dt)
        sys.velocity(i) += this->noise_coeff_[i] * this->gen_R(rng);
    }
    correct_velocity(sys, ff);

    // A step
    for(std::size_t correction_step=0; correction_step<correction_iter_num_; ++correction_step)
    {
        for(std::size_t i=0; i<sys.size(); ++i)
        {
            this->old_pos_rattle_[i] = sys.position(i);
            sys.position(i) += this->dt_in_correction_ * sys.velocity(i);
        }
        correct_coordinate(sys, ff);
        correct_velocity(sys, ff);
    }
    // update neighbor list; reduce margin, reconstruct the list if needed;
    real_type largest_disp2(0.0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        coordinate_type displacement = sys.position(i) - this->old_position_[i];
        largest_disp2 = std::max(largest_disp2, math::length_sq(displacement));
        sys.position(i) = sys.adjust_position(sys.position(i));

        // reset force
        sys.force(i) = math::make_coordinate<coordinate_type>(0, 0, 0);
    }

    ff.reduce_margin(2 * std::sqrt(largest_disp2), sys);

    // B step
    ff.calc_force(sys);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    correct_velocity(sys, ff);

    remover_.remove(sys);

    for(std::size_t i=0; i<sys.size(); ++i)
    {
        this->old_position_[i] = sys.position(i);
    }

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP */
<commit_msg>fix: remove dump for debug<commit_after>#ifndef MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#define MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/RandomNumberGenerator.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/core/ForceField.hpp>
#include <mjolnir/core/SystemMotionRemover.hpp>
#include <mjolnir/core/Unit.hpp>
#include <mjolnir/util/logger.hpp>

namespace mjolnir
{

// g-BAOAB Langevin integrator developed by the following papers
// Leimkuhler B., Matthews C., Proc. R. Soc. A Math. Phys. Eng. Sci. (2016)
template<typename traitsT>
class gBAOABLangevinIntegrator
{
  public:
    using traits_type                = traitsT;
    using real_type                  = typename traits_type::real_type;
    using coordinate_type            = typename traits_type::coordinate_type;
    using indices_type               = std::array<std::size_t, 2>;
    using system_type                = System<traitsT>;
    using forcefield_type            = ForceField<traitsT>;
    using constraint_forcefield_type = typename forcefield_type::constraint_forcefield_type;
    using constraint_type            = std::pair<indices_type, real_type>;
    using constraints_type           = std::vector<constraint_type>;
    using rng_type                   = RandomNumberGenerator<traits_type>;
    using remover_type               = SystemMotionRemover<traits_type>;

  public:

    gBAOABLangevinIntegrator(const real_type dt, std::vector<real_type>&& gamma,
                             remover_type&& remover)
        : dt_(dt), halfdt_(dt / 2), gammas_(std::move(gamma)),
          exp_gamma_dt_(gammas_.size()), noise_coeff_ (gammas_.size()),
          remover_(std::move(remover)),
          old_position_(gammas_.size()),
          old_pos_rattle_(gammas_.size())
    {}
    ~gBAOABLangevinIntegrator() = default;

    void initialize(system_type& sys, forcefield_type& ff, rng_type& rng);

    real_type step(const real_type time, system_type& sys, forcefield_type& ff,
                   rng_type& rng);

    void update(const system_type& sys)
    {
        if(!sys.has_attribute("temperature"))
        {
            throw std::out_of_range("mjolnir::g-BAOABLangevinIntegrator: "
                "Langevin Integrator requires reference temperature, but "
                "`temperature` is not found in `system.attribute`.");
        }
        this->temperature_ = sys.attribute("temperature");
        this->reset_parameter(sys);
        return;
    }

    real_type delta_t() const noexcept {return dt_;}
    std::vector<real_type> const& parameters() const noexcept {return gammas_;}

  private:

    void reset_parameter(const system_type& sys) noexcept
    {
        const auto kBT = physics::constants<real_type>::kB() * this->temperature_;
        for(std::size_t i=0; i<sys.size(); ++i)
        {
            const auto gamma     = this->gammas_.at(i);
            const auto gamma_dt  = -1 * gamma * this->dt_;
            this->exp_gamma_dt_.at(i) = std::exp(gamma_dt);
            this->noise_coeff_ .at(i) = std::sqrt(
                    kBT * (1 - std::exp(2 * gamma_dt)) * sys.rmass(i));
        }
        return;
    };

    coordinate_type gen_R(rng_type& rng) noexcept
    {
        const auto x = rng.gaussian();
        const auto y = rng.gaussian();
        const auto z = rng.gaussian();
        return math::make_coordinate<coordinate_type>(x, y, z);
    }

    void correct_coordinate(system_type& sys, const forcefield_type& ff)
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        std::size_t rattle_step = 0;
        const constraint_forcefield_type& constraint_ff = ff.constraint();
        const constraints_type&           constraints = constraint_ff.constraints();

        while(rattle_step<constraint_ff.max_iteration())
        {
            bool corrected = false;
            for(std::size_t i=0; i<constraints.size(); ++i)
            {
                const auto& indices_v0 = constraints[i];
                const auto& indices    = indices_v0.first;
                auto& p1 = sys.position(indices[0]);
                auto& p2 = sys.position(indices[1]);
                auto& v1 = sys.velocity(indices[0]);
                auto& v2 = sys.velocity(indices[1]);

                const auto      dp = sys.adjust_direction(p2 - p1);
                const real_type dp2 = math::length_sq(dp);
                const real_type missmatch2 = square_v0s_[i] - dp2;

                if(correction_tolerance_ < std::abs(missmatch2))
                {
                    auto& op1 = this->old_pos_rattle_[indices[0]];
                    auto& op2 = this->old_pos_rattle_[indices[1]];

                    const auto old_dp = sys.adjust_direction(op2 - op1);
                    const real_type dot_old_new_dp = math::dot_product(old_dp, dp);
                    const real_type lambda =
                        0.5 * missmatch2 * reduced_mass_[i] / dot_old_new_dp;
                    const coordinate_type correction_force = lambda * old_dp;
                    const auto& rm1 = sys.rmass(indices[0]);
                    const auto& rm2 = sys.rmass(indices[1]);
                    const coordinate_type correction_vec1  = correction_force * rm1;
                    const coordinate_type correction_vec2  = correction_force * rm2;
                    p1 -= correction_vec1;
                    p2 += correction_vec2;
                    v1 -= correction_vec1 * r_dt_in_correction_;
                    v2 += correction_vec2 * r_dt_in_correction_;

                    corrected = true;
                }
            }

            if(!corrected) {break;}

            ++rattle_step;
        }

        if(rattle_step >= constraint_ff.max_iteration())
        {
            MJOLNIR_LOG_WARN("coordinate rattle iteration number exceeds rattle max iteration");
        }

        return;
    }

    void correct_velocity(system_type& sys, const forcefield_type& ff)
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        const constraint_forcefield_type& constraint_ff = ff.constraint();
        const constraints_type&           constraints   = constraint_ff.constraints();

        std::size_t rattle_step = 0;
        while(rattle_step<constraint_ff.max_iteration())
        {
            bool corrected = false;
            for(std::size_t i=0; i<constraints.size(); ++i)
            {
                const auto& constraint       = constraints[i];
                const auto& indices          = constraint.first;
                auto& p1  = sys.position(indices[0]);
                auto& p2  = sys.position(indices[1]);
                auto& v1  = sys.velocity(indices[0]);
                auto& v2  = sys.velocity(indices[1]);

                const auto pos_diff      = sys.adjust_direction(p2 - p1);
                const auto vel_diff      = v2 - v1;
                const real_type dot_pdvd = math::dot_product(pos_diff, vel_diff);
                const real_type lambda   = dot_pdvd * reduced_mass_[i] * r_square_v0s_[i];

                if(correction_tolerance_ < std::abs(lambda))
                {
                    const auto& rm1 = sys.rmass(indices[0]);
                    const auto& rm2 = sys.rmass(indices[1]);

                    const auto correction_vec = lambda * pos_diff;
                    v1 += correction_vec * rm1;
                    v2 -= correction_vec * rm2;
                    corrected = true;
                }
            }

            if(!corrected) {break;}

            ++rattle_step;
        }

        if(constraint_ff.max_iteration() <= rattle_step)
        {
            MJOLNIR_LOG_WARN("velocity rattle iteration number exceeds rattle max iteration.");
        }
        return;
   }

  private:
    real_type   dt_;
    real_type   halfdt_;
    std::vector<real_type>       gammas_;
    std::vector<real_type>       exp_gamma_dt_;
    std::vector<real_type>       noise_coeff_;
    std::vector<real_type>       square_v0s_;
    std::vector<real_type>       r_square_v0s_;
    std::vector<real_type>       reduced_mass_;
    remover_type remover_;

    real_type   temperature_;
    real_type   correction_tolerance_;
    real_type   correction_tolerance_dt_;
    real_type   correction_tolerance_dt_itr_;
    real_type   dt_in_correction_;
    real_type   r_dt_in_correction_;

    static constexpr std::size_t correction_iter_num_ = 1;

    std::vector<coordinate_type> old_position_;
    std::vector<coordinate_type> old_pos_rattle_;

};

template<typename traitsT>
void gBAOABLangevinIntegrator<traitsT>::initialize(
        system_type& system, forcefield_type& ff, rng_type&)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    const constraint_forcefield_type& constraint_ff = ff.constraint();
    const constraints_type&           constraints   = constraint_ff.constraints();
    const real_type                   tolerance     = constraint_ff.tolerance();
    // calculate parameters for constraint
    this->correction_tolerance_        = tolerance;
    this->correction_tolerance_dt_     = tolerance / dt_;
    this->correction_tolerance_dt_itr_ = tolerance * 2. * correction_iter_num_ / dt_;
    this->dt_in_correction_            = dt_ * 0.5 / correction_iter_num_;
    this->r_dt_in_correction_          = 1. / dt_in_correction_;

    // calculate parameters for each particles
    this->update(system);

    // calculate force
    for(std::size_t i=0; i<system.size(); ++i)
    {
        system.force(i) = math::make_coordinate<coordinate_type>(0, 0, 0);
    }
    ff.calc_force(system);

    // buffering old position
    for(std::size_t i=0; i<system.size(); ++i)
    {
        old_position_[i] = system.position(i);
    }

    square_v0s_.resize(constraints.size());
    r_square_v0s_.resize(constraints.size());
    reduced_mass_.resize(constraints.size());
    for(std::size_t i=0; i<constraints.size(); ++i)
    {
        // calculate square v0
        square_v0s_[i] = std::pow(constraints[i].second, 2);
        r_square_v0s_[i] = 1.0 / square_v0s_[i];

        // calculate inverse reduced mass
        const auto& constraint = constraints[i];
        std::size_t first_idx  = constraint.first[0];
        std::size_t second_idx = constraint.first[1];
        reduced_mass_[i] = 1.0 / (system.rmass(first_idx) + system.rmass(second_idx));
    }

    return;
}

template<typename traitsT>
typename gBAOABLangevinIntegrator<traitsT>::real_type
gBAOABLangevinIntegrator<traitsT>::step(
        const real_type time, system_type& sys, forcefield_type& ff, rng_type& rng)
{
    // B step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i)  += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    correct_velocity(sys, ff);

    // A step
    for(std::size_t correction_step=0; correction_step<correction_iter_num_; ++correction_step)
    {
        for(std::size_t i=0; i<sys.size(); ++i)
        {
            this->old_pos_rattle_[i] = sys.position(i);
            sys.position(i) += this->dt_in_correction_ * sys.velocity(i);
        }
        correct_coordinate(sys, ff);
        correct_velocity(sys, ff);
    }

    // O step
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) *= this->exp_gamma_dt_[i]; // *= exp(- gamma dt)
        sys.velocity(i) += this->noise_coeff_[i] * this->gen_R(rng);
    }
    correct_velocity(sys, ff);

    // A step
    for(std::size_t correction_step=0; correction_step<correction_iter_num_; ++correction_step)
    {
        for(std::size_t i=0; i<sys.size(); ++i)
        {
            this->old_pos_rattle_[i] = sys.position(i);
            sys.position(i) += this->dt_in_correction_ * sys.velocity(i);
        }
        correct_coordinate(sys, ff);
        correct_velocity(sys, ff);
    }
    // update neighbor list; reduce margin, reconstruct the list if needed;
    real_type largest_disp2(0.0);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        coordinate_type displacement = sys.position(i) - this->old_position_[i];
        largest_disp2 = std::max(largest_disp2, math::length_sq(displacement));
        sys.position(i) = sys.adjust_position(sys.position(i));

        // reset force
        sys.force(i) = math::make_coordinate<coordinate_type>(0, 0, 0);
    }

    ff.reduce_margin(2 * std::sqrt(largest_disp2), sys);

    // B step
    ff.calc_force(sys);
    for(std::size_t i=0; i<sys.size(); ++i)
    {
        sys.velocity(i) += this->halfdt_ * sys.rmass(i) * sys.force(i);
    }
    correct_velocity(sys, ff);

    remover_.remove(sys);

    for(std::size_t i=0; i<sys.size(); ++i)
    {
        this->old_position_[i] = sys.position(i);
    }

    return time + dt_;
}

} // mjolnir
#endif /* MJOLNIR_CORE_G_BAOAB_LANGEVIN_INTEGRATOR_HPP */
<|endoftext|>