<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012   Mohammed Nafees   <nafees.technocool@gmail.com>
// Copyright 2012   Dennis Nienhüser  <earthwings@gentoo.org>
// Copyright 2012   Illya Kovalevskyy <illya.kovalevskyy@gmail.com>
//

#include "MapInfoDialog.h"
#include "MarbleWidget.h"
#include "PopupItem.h"

#include <QtGui/QMouseEvent>
#include <QtGui/QApplication>
#include <QtGui/QAction>

namespace Marble
{

MapInfoDialog::MapInfoDialog(QObject *parent) :
    QObject( parent ),
    m_popupItem( new PopupItem )
{
    connect( m_popupItem, SIGNAL(dirty()), this, SIGNAL(repaintNeeded()) );
    connect( m_popupItem, SIGNAL(hide()), this, SLOT(hidePopupItem()) );
}

MapInfoDialog::~MapInfoDialog()
{
}

QStringList MapInfoDialog::renderPosition() const
{
    return QStringList( "ALWAYS_ON_TOP" );
}

QString MapInfoDialog::renderPolicy() const
{
    return "ALWAYS";
}

bool MapInfoDialog::render( GeoPainter *painter, ViewportParams *viewport,
                                const QString&, GeoSceneLayer* )
{
    if ( visible() ) {
        m_popupItem->paintEvent( painter, viewport );
    }
    return true;
}

bool MapInfoDialog::eventFilter( QObject *object, QEvent *e )
{
    return m_popupItem && visible() && m_popupItem->eventFilter( object, e );
}

qreal MapInfoDialog::zValue() const
{
    return 4711.23;
}

bool MapInfoDialog::visible() const
{
    return m_popupItem->visible();
}

void MapInfoDialog::setVisible( bool visible )
{
    m_popupItem->setVisible( visible );
}

void MapInfoDialog::setCoordinates(const GeoDataCoordinates &coordinates , Qt::Alignment alignment)
{
    if ( m_popupItem ) {
        m_popupItem->setCoordinate( coordinates );
        m_popupItem->setAlignment( alignment );
    }
}

void MapInfoDialog::setUrl( const QUrl &url )
{
    if ( m_popupItem ) {
        m_popupItem->setUrl( url );
    }
}

void MapInfoDialog::setContent( const QString &html )
{
    if ( m_popupItem ) {
        m_popupItem->setContent( html );
    }
}

void MapInfoDialog::setBackgroundColor(const QColor &color)
{
    if(color.isValid()) {
        m_popupItem->setBackgroundColor(color);
    }
}

void MapInfoDialog::setTextColor(const QColor &color)
{
    if(color.isValid()) {
        m_popupItem->setTextColor(color);
    }
}

void MapInfoDialog::setSize( const QSizeF &size )
{
    if ( m_popupItem ) {
        m_popupItem->setSize( size );
    }
}

void MapInfoDialog::setPosition( const QPointF &position )
{
    /** @todo Implement */
    Q_UNUSED( position );
}

void MapInfoDialog::hidePopupItem()
{
    setVisible( false );
}

}

#include "MapInfoDialog.moc"
<commit_msg>Repaint when content changes.<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2012   Mohammed Nafees   <nafees.technocool@gmail.com>
// Copyright 2012   Dennis Nienhüser  <earthwings@gentoo.org>
// Copyright 2012   Illya Kovalevskyy <illya.kovalevskyy@gmail.com>
//

#include "MapInfoDialog.h"
#include "MarbleWidget.h"
#include "PopupItem.h"

#include <QtGui/QMouseEvent>
#include <QtGui/QApplication>
#include <QtGui/QAction>

namespace Marble
{

MapInfoDialog::MapInfoDialog(QObject *parent) :
    QObject( parent ),
    m_popupItem( new PopupItem )
{
    connect( m_popupItem, SIGNAL(dirty()), this, SIGNAL(repaintNeeded()) );
    connect( m_popupItem, SIGNAL(hide()), this, SLOT(hidePopupItem()) );
}

MapInfoDialog::~MapInfoDialog()
{
}

QStringList MapInfoDialog::renderPosition() const
{
    return QStringList( "ALWAYS_ON_TOP" );
}

QString MapInfoDialog::renderPolicy() const
{
    return "ALWAYS";
}

bool MapInfoDialog::render( GeoPainter *painter, ViewportParams *viewport,
                                const QString&, GeoSceneLayer* )
{
    if ( visible() ) {
        m_popupItem->paintEvent( painter, viewport );
    }
    return true;
}

bool MapInfoDialog::eventFilter( QObject *object, QEvent *e )
{
    return m_popupItem && visible() && m_popupItem->eventFilter( object, e );
}

qreal MapInfoDialog::zValue() const
{
    return 4711.23;
}

bool MapInfoDialog::visible() const
{
    return m_popupItem->visible();
}

void MapInfoDialog::setVisible( bool visible )
{
    m_popupItem->setVisible( visible );
}

void MapInfoDialog::setCoordinates(const GeoDataCoordinates &coordinates , Qt::Alignment alignment)
{
    if ( m_popupItem ) {
        m_popupItem->setCoordinate( coordinates );
        m_popupItem->setAlignment( alignment );
    }
}

void MapInfoDialog::setUrl( const QUrl &url )
{
    if ( m_popupItem ) {
        m_popupItem->setUrl( url );
    }
}

void MapInfoDialog::setContent( const QString &html )
{
    if ( m_popupItem ) {
        m_popupItem->setContent( html );
        emit repaintNeeded();
    }
}

void MapInfoDialog::setBackgroundColor(const QColor &color)
{
    if(color.isValid()) {
        m_popupItem->setBackgroundColor(color);
    }
}

void MapInfoDialog::setTextColor(const QColor &color)
{
    if(color.isValid()) {
        m_popupItem->setTextColor(color);
    }
}

void MapInfoDialog::setSize( const QSizeF &size )
{
    if ( m_popupItem ) {
        m_popupItem->setSize( size );
    }
}

void MapInfoDialog::setPosition( const QPointF &position )
{
    /** @todo Implement */
    Q_UNUSED( position );
}

void MapInfoDialog::hidePopupItem()
{
    setVisible( false );
}

}

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


<commit_before>#include <rusql/rusql.hpp>
#include <boost/thread.hpp>
#include "test.hpp"
#include "database_test.hpp"

int main(int argc, char *argv[]) {
	auto db = get_database(argc, argv);
	test_init(6);
	db->execute("CREATE TABLE rusqltest (`value` INT(2) NOT NULL)");
	db->execute("INSERT INTO rusqltest VALUES (20)");

	auto statement = db->prepare("SELECT value FROM rusqltest");

	statement.execute();

	boost::thread thread([&db]() {
		auto thread_handle = db->get_thread_handle();
		db->execute("UPDATE rusqltest SET value=30");
	});
	thread.join();

	uint64_t value = 10;
	statement.bind_results(value);
	test(statement.fetch(), "one result");
	test(value == 20, "value was correct (" + std::to_string(value) + ")");
	test(!statement.fetch(), "exactly one result");

	statement.execute();
	statement.bind_results(value);
	test(statement.fetch(), "one result");
	test(value == 30, "value was correct (" + std::to_string(value) + ")");
	test(!statement.fetch(), "exactly one result");

	db->execute("DROP TABLE rusqltest");
}
<commit_msg>Add level of indentation<commit_after>#include <rusql/rusql.hpp>
#include <boost/thread.hpp>
#include "test.hpp"
#include "database_test.hpp"

int main(int argc, char *argv[]) {
	auto db = get_database(argc, argv);
	test_init(6);
	db->execute("CREATE TABLE rusqltest (`value` INT(2) NOT NULL)");
	db->execute("INSERT INTO rusqltest VALUES (20)");

	{
		auto statement = db->prepare("SELECT value FROM rusqltest");

		statement.execute();

		boost::thread thread([&db]() {
			auto thread_handle = db->get_thread_handle();
			db->execute("UPDATE rusqltest SET value=30");
		});
		thread.join();

		uint64_t value = 10;
		statement.bind_results(value);
		test(statement.fetch(), "one result");
		test(value == 20, "value was correct (" + std::to_string(value) + ")");
		test(!statement.fetch(), "exactly one result");

		statement.execute();
		statement.bind_results(value);
		test(statement.fetch(), "one result");
		test(value == 30, "value was correct (" + std::to_string(value) + ")");
		test(!statement.fetch(), "exactly one result");
	}

	db->execute("DROP TABLE rusqltest");
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <metaverse/network/hosts.hpp>
#include <metaverse/macros_define.hpp>

#include <algorithm>
#include <cstddef>
#include <string>
#include <vector>
#include <metaverse/bitcoin.hpp>
#include <metaverse/bitcoin/utility/path.hpp>
#include <metaverse/bitcoin/math/limits.hpp>
#include <metaverse/network/settings.hpp>
#include <metaverse/network/channel.hpp>

namespace libbitcoin {
namespace network {

uint32_t timer_interval = 60 * 5; // 5 minutes

hosts::hosts(threadpool& pool, const settings& settings)
    : seed_count(settings.seeds.size())
    , host_pool_capacity_(std::max(settings.host_pool_capacity, 1u))
    , buffer_(host_pool_capacity_)
    , backup_(host_pool_capacity_)
    , inactive_(host_pool_capacity_ * 2)
    , seeds_()
    , stopped_(true)
    , file_path_(default_data_path() / settings.hosts_file)
    , disabled_(settings.host_pool_capacity == 0)
    , pool_(pool)
    , self_(settings.self)
{
}

// private
hosts::iterator hosts::find(const address& host)
{
    return find(buffer_, host);
}

hosts::iterator hosts::find(list& buffer, const address& host)
{
    const auto found = [&host](const address & entry)
    {
        return entry.port == host.port && entry.ip == host.ip;
    };
    return std::find_if(buffer.begin(), buffer.end(), found);
}

size_t hosts::count() const
{
    ///////////////////////////////////////////////////////////////////////////
    // Critical Section
    shared_lock lock(mutex_);

    return buffer_.size();
    ///////////////////////////////////////////////////////////////////////////
}

code hosts::fetch_seed(address& out, const config::authority::list& excluded_list)
{
    return fetch(seeds_, out, excluded_list);
}

code hosts::fetch(address& out, const config::authority::list& excluded_list)
{
    return fetch(buffer_, out, excluded_list);
}

template <typename T>
code hosts::fetch(T& buffer, address& out, const config::authority::list& excluded_list)
{
    if (disabled_) {
        return error::not_found;
    }

    // Critical Section
    shared_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    if (buffer.empty()) {
        return error::not_found;
    }

    auto match = [&excluded_list](address& addr) {
        auto auth = config::authority(addr);
        return std::find(excluded_list.begin(), excluded_list.end(), auth) == excluded_list.end();
    };

    std::vector<address> vec;
    std::copy_if(buffer.begin(), buffer.end(), std::back_inserter(vec), match);

    if (vec.empty()) {
        return error::not_found;
    }

    const auto index = pseudo_random(0, vec.size() - 1);
    out = vec[static_cast<size_t>(index)];

    return error::success;
}

hosts::address::list hosts::copy_seeds()
{
    if (disabled_)
        return address::list();

    shared_lock lock{mutex_};
    return seeds_;
}

hosts::address::list hosts::copy()
{
    if (disabled_)
        return address::list();

    shared_lock lock{mutex_};

    if (stopped_ || buffer_.empty())
        return address::list();

    // not copy all, but just 10% ~ 20% , at least one
    const auto out_count = std::max<size_t>(1,
        std::min<size_t>(1000, buffer_.size()) / pseudo_random(5, 10));

    const auto limit = buffer_.size();
    auto index = pseudo_random(0, limit - 1);

    address::list copy(out_count);

    for (size_t count = 0; count < out_count; ++count)
        copy.push_back(buffer_[index++ % limit]);

    pseudo_random::shuffle(copy);
    return copy;
}

bool hosts::store_cache(bool succeed_clear_buffer)
{
    if (!buffer_.empty()) {
        bc::ofstream file(file_path_.string());
        const auto file_error = file.bad();

        if (file_error) {
            log::error(LOG_NETWORK) << "hosts file (" << file_path_.string() << ") open failed" ;
            return false;
        }

        log::debug(LOG_NETWORK)
                << "sync hosts to file(" << file_path_.string()
                << "), inactive size is " << inactive_.size()
                << ", buffer size is " << buffer_.size();

        for (const auto& entry : buffer_) {
            // TODO: create full space-delimited network_address serialization.
            // Use to/from string format as opposed to wire serialization.
            if (!(channel::blacklisted(entry) || channel::manualbanned(entry))) {
                file << config::authority(entry) << std::endl;
            }
        }

        if (succeed_clear_buffer) {
            buffer_.clear();
        }
    }
    else {
        if (boost::filesystem::exists(file_path_.string())) {
            boost::filesystem::remove_all(file_path_.string());
        }
    }

    return true;
}

void hosts::handle_timer(const code& ec)
{
    if (disabled_) {
        return;
    }

    if (ec.value() != error::success) {
        return;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return;
    }

    upgrade_to_unique_lock unq_lock(lock);

    if (!store_cache()) {
        return;
    }

    snap_timer_->start(std::bind(&hosts::handle_timer, shared_from_this(), std::placeholders::_1));
}

// load
code hosts::start()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (!stopped_) {
        return error::operation_failed;
    }

    upgrade_to_unique_lock unq_lock(lock);
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    snap_timer_ = std::make_shared<deadline>(pool_, asio::seconds(timer_interval));
    snap_timer_->start(std::bind(&hosts::handle_timer, shared_from_this(), std::placeholders::_1));

    stopped_ = false;

    bc::ifstream file(file_path_.string());
    const auto file_error = file.bad();
    if (!file_error) {
        std::string line;
        while (std::getline(file, line)) {
            config::authority host(line);

            if (host.port() != 0) {
                auto network_address = host.to_network_address();
                if (network_address.is_routable()) {
                    buffer_.push_back(network_address);
                    if (buffer_.full()) {
                        break;
                    }
                }
                else {
                    log::debug(LOG_NETWORK) << "host start is not routable,"
                        << config::authority{network_address};
                }
            }
        }
    }

    if (file_error) {
        log::debug(LOG_NETWORK)
                << "Failed to save hosts file.";
        return error::file_system;
    }

    return error::success;
}

// load
code hosts::stop()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::success;
    }

    upgrade_to_unique_lock unq_lock(lock);

    // stop timer
    snap_timer_->stop();

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    stopped_ = true;

    if (!store_cache(true)) {
        return error::file_system;
    }

    return error::success;
}

code hosts::clear()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    if (!buffer_.empty()) {
        std::swap(backup_, buffer_);
        buffer_.clear();
    }

    return error::success;
}

code hosts::after_reseeding()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    //re-seeding failed and recover the buffer with backup one
    if (buffer_.size() <= seed_count) {
        log::debug(LOG_NETWORK)
                << "Reseeding finished, buffer size: " << buffer_.size()
                << ", less than seed count: " << seed_count
                << ", roll back the hosts cache.";

        if (!buffer_.full()) {
            for (auto& host : backup_) {
                if (find(host) == buffer_.end()) {
                    buffer_.push_back(host);

                    if (buffer_.full()) {
                        break;
                    }
                }
            }
        }
    }
    else {
        // filter inactive hosts
        for (auto &host : inactive_) {
            auto iter = find(host);
            if (iter != buffer_.end()) {
                buffer_.erase(iter);
            }
        }
    }

    // clear the backup
    backup_.clear();

    log::debug(LOG_NETWORK)
            << "Reseeding finished, buffer size: " << buffer_.size();

    return error::success;
}

code hosts::remove(const address& host)
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    auto it = find(host);
    if (it != buffer_.end()) {
        buffer_.erase(it);
    }

    if (find(inactive_, host) == inactive_.end()) {
        inactive_.push_back(host);
    }

    return error::success;
}

code hosts::store_seed(const address& host)
{
    // don't store blacklist and banned address
    if (channel::blacklisted(host) || channel::manualbanned(host)) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    auto iter = std::find_if(seeds_.begin(), seeds_.end(),
        [&host](const address& item){
            return host.ip == item.ip && host.port == item.port;
        });

    if (iter == seeds_.end()) {
        constexpr size_t max_seeds = 8;
        constexpr size_t half_pos = max_seeds >> 1;
        upgrade_to_unique_lock unq_lock(lock);
        if (seeds_.size() == max_seeds) { // full
            std::copy(seeds_.begin()+half_pos+1, seeds_.end(), seeds_.begin()+half_pos);
            seeds_.back() = host;
        }
        else {
            seeds_.push_back(host);
        }
#ifdef PRIVATE_CHAIN
        log::info(LOG_NETWORK) << "store seed " << config::authority(host).to_string();
#endif
    }

    return error::success;
}

code hosts::remove_seed(const address& host)
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    auto iter = std::find_if(seeds_.begin(), seeds_.end(),
        [&host](const address& item){
            return host.ip == item.ip && host.port == item.port;
        });

    if (iter != seeds_.end()) {
        upgrade_to_unique_lock unq_lock(lock);
        seeds_.erase(iter);

#ifdef PRIVATE_CHAIN
        log::info(LOG_NETWORK) << "remove seed " << config::authority(host).to_string();
#endif
    }

    return error::success;
}

code hosts::store(const address& host)
{
    if (disabled_) {
        return error::success;
    }

    if (!host.is_routable()) {
        // We don't treat invalid address as an error, just log it.
        return error::success;
    }

    // don't store self address
    auto authority = config::authority{host};
    if (authority == self_ || authority.port() == 0) {
        return error::success;
    }

    // don't store blacklist and banned address
    if (channel::blacklisted(host) || channel::manualbanned(host)) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    if (find(host) == buffer_.end()) {
        buffer_.push_back(host);
    }

    auto iter = find(inactive_, host);
    if (iter != inactive_.end()) {
        inactive_.erase(iter);
    }

    return error::success;
}

// The handler is invoked once all calls to do_store are completed.
// We disperse here to allow other addresses messages to interleave hosts.
void hosts::store(const address::list& hosts, result_handler handler)
{
    if (disabled_ || hosts.empty()) {
        handler(error::success);
        return;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        handler(error::service_stopped);
        return;
    }

    // Accept between 1 and all of this peer's addresses up to capacity.
    const auto capacity = host_pool_capacity_;
    size_t host_size = hosts.size();
    const size_t usable = std::min(host_size, capacity);
    const size_t random = static_cast<size_t>(pseudo_random(1, usable));

    // But always accept at least the amount we are short if available.
    const size_t gap = capacity - buffer_.size();
    const size_t accept = std::max(gap, random);

    // Convert minimum desired to step for iteration, no less than 1.
    const auto step = std::max(usable / accept, size_t(1));
    size_t accepted = 0;

    upgrade_to_unique_lock unq_lock(lock);
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    for (size_t index = 0; index < usable; index = ceiling_add(index, step)) {
        const auto& host = hosts[index];

        // Do not treat invalid address as an error, just log it.
        if (!host.is_valid()) {
            log::debug(LOG_NETWORK)
                    << "Invalid host address from peer.";
            continue;
        }

        if (channel::blacklisted(host) || channel::manualbanned(host)) {
            continue;
        }

        // Do not allow duplicates in the host cache.
        if (find(host) == buffer_.end()
                && find(inactive_, host) == inactive_.end()) {
            ++accepted;
            buffer_.push_back(host);
        }
    }

    log::debug(LOG_NETWORK)
            << "Accepted (" << accepted << " of " << hosts.size()
            << ") host addresses from peer."
            << " inactive size is " << inactive_.size()
            << ", buffer size is " << buffer_.size();

    handler(error::success);
}

} // namespace network
} // namespace libbitcoin
<commit_msg>fix mutex lock.<commit_after>/**
 * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS)
 * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <metaverse/network/hosts.hpp>
#include <metaverse/macros_define.hpp>

#include <algorithm>
#include <cstddef>
#include <string>
#include <vector>
#include <metaverse/bitcoin.hpp>
#include <metaverse/bitcoin/utility/path.hpp>
#include <metaverse/bitcoin/math/limits.hpp>
#include <metaverse/network/settings.hpp>
#include <metaverse/network/channel.hpp>

namespace libbitcoin {
namespace network {

uint32_t timer_interval = 60 * 5; // 5 minutes

hosts::hosts(threadpool& pool, const settings& settings)
    : seed_count(settings.seeds.size())
    , host_pool_capacity_(std::max(settings.host_pool_capacity, 1u))
    , buffer_(host_pool_capacity_)
    , backup_(host_pool_capacity_)
    , inactive_(host_pool_capacity_ * 2)
    , seeds_()
    , stopped_(true)
    , file_path_(default_data_path() / settings.hosts_file)
    , disabled_(settings.host_pool_capacity == 0)
    , pool_(pool)
    , self_(settings.self)
{
}

// private
hosts::iterator hosts::find(const address& host)
{
    return find(buffer_, host);
}

hosts::iterator hosts::find(list& buffer, const address& host)
{
    const auto found = [&host](const address & entry)
    {
        return entry.port == host.port && entry.ip == host.ip;
    };
    return std::find_if(buffer.begin(), buffer.end(), found);
}

size_t hosts::count() const
{
    ///////////////////////////////////////////////////////////////////////////
    // Critical Section
    shared_lock lock(mutex_);

    return buffer_.size();
    ///////////////////////////////////////////////////////////////////////////
}

code hosts::fetch_seed(address& out, const config::authority::list& excluded_list)
{
    return fetch(seeds_, out, excluded_list);
}

code hosts::fetch(address& out, const config::authority::list& excluded_list)
{
    return fetch(buffer_, out, excluded_list);
}

template <typename T>
code hosts::fetch(T& buffer, address& out, const config::authority::list& excluded_list)
{
    if (disabled_) {
        return error::not_found;
    }

    // Critical Section
    shared_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    if (buffer.empty()) {
        return error::not_found;
    }

    auto match = [&excluded_list](address& addr) {
        auto auth = config::authority(addr);
        return std::find(excluded_list.begin(), excluded_list.end(), auth) == excluded_list.end();
    };

    std::vector<address> vec;
    std::copy_if(buffer.begin(), buffer.end(), std::back_inserter(vec), match);

    if (vec.empty()) {
        return error::not_found;
    }

    const auto index = pseudo_random(0, vec.size() - 1);
    out = vec[static_cast<size_t>(index)];

    return error::success;
}

hosts::address::list hosts::copy_seeds()
{
    if (disabled_)
        return address::list();

    shared_lock lock{mutex_};
    return seeds_;
}

hosts::address::list hosts::copy()
{
    if (disabled_)
        return address::list();

    shared_lock lock{mutex_};

    if (stopped_ || buffer_.empty())
        return address::list();

    // not copy all, but just 10% ~ 20% , at least one
    const auto out_count = std::max<size_t>(1,
        std::min<size_t>(1000, buffer_.size()) / pseudo_random(5, 10));

    const auto limit = buffer_.size();
    auto index = pseudo_random(0, limit - 1);

    address::list copy(out_count);

    for (size_t count = 0; count < out_count; ++count)
        copy.push_back(buffer_[index++ % limit]);

    pseudo_random::shuffle(copy);
    return copy;
}

bool hosts::store_cache(bool succeed_clear_buffer)
{
    if (!buffer_.empty()) {
        bc::ofstream file(file_path_.string());
        const auto file_error = file.bad();

        if (file_error) {
            log::error(LOG_NETWORK) << "hosts file (" << file_path_.string() << ") open failed" ;
            return false;
        }

        log::debug(LOG_NETWORK)
                << "sync hosts to file(" << file_path_.string()
                << "), inactive size is " << inactive_.size()
                << ", buffer size is " << buffer_.size();

        for (const auto& entry : buffer_) {
            // TODO: create full space-delimited network_address serialization.
            // Use to/from string format as opposed to wire serialization.
            if (!(channel::blacklisted(entry) || channel::manualbanned(entry))) {
                file << config::authority(entry) << std::endl;
            }
        }

        if (succeed_clear_buffer) {
            buffer_.clear();
        }
    }
    else {
        if (boost::filesystem::exists(file_path_.string())) {
            boost::filesystem::remove_all(file_path_.string());
        }
    }

    return true;
}

void hosts::handle_timer(const code& ec)
{
    if (disabled_) {
        return;
    }

    if (ec.value() != error::success) {
        return;
    }

    {
        // Critical Section
        upgrade_lock lock(mutex_);

        if (stopped_) {
            return;
        }

        upgrade_to_unique_lock unq_lock(lock);

        if (!store_cache()) {
            return;
        }
    }

    snap_timer_->start(std::bind(&hosts::handle_timer, shared_from_this(), std::placeholders::_1));
}

// load
code hosts::start()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (!stopped_) {
        return error::operation_failed;
    }

    upgrade_to_unique_lock unq_lock(lock);
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    snap_timer_ = std::make_shared<deadline>(pool_, asio::seconds(timer_interval));
    snap_timer_->start(std::bind(&hosts::handle_timer, shared_from_this(), std::placeholders::_1));

    stopped_ = false;

    bc::ifstream file(file_path_.string());
    const auto file_error = file.bad();
    if (!file_error) {
        std::string line;
        while (std::getline(file, line)) {
            config::authority host(line);

            if (host.port() != 0) {
                auto network_address = host.to_network_address();
                if (network_address.is_routable()) {
                    buffer_.push_back(network_address);
                    if (buffer_.full()) {
                        break;
                    }
                }
                else {
                    log::debug(LOG_NETWORK) << "host start is not routable,"
                        << config::authority{network_address};
                }
            }
        }
    }

    if (file_error) {
        log::debug(LOG_NETWORK)
                << "Failed to save hosts file.";
        return error::file_system;
    }

    return error::success;
}

// load
code hosts::stop()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::success;
    }

    upgrade_to_unique_lock unq_lock(lock);

    // stop timer
    snap_timer_->stop();

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    stopped_ = true;

    if (!store_cache(true)) {
        return error::file_system;
    }

    return error::success;
}

code hosts::clear()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    if (!buffer_.empty()) {
        std::swap(backup_, buffer_);
        buffer_.clear();
    }

    return error::success;
}

code hosts::after_reseeding()
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    //re-seeding failed and recover the buffer with backup one
    if (buffer_.size() <= seed_count) {
        log::debug(LOG_NETWORK)
                << "Reseeding finished, buffer size: " << buffer_.size()
                << ", less than seed count: " << seed_count
                << ", roll back the hosts cache.";

        if (!buffer_.full()) {
            for (auto& host : backup_) {
                if (find(host) == buffer_.end()) {
                    buffer_.push_back(host);

                    if (buffer_.full()) {
                        break;
                    }
                }
            }
        }
    }
    else {
        // filter inactive hosts
        for (auto &host : inactive_) {
            auto iter = find(host);
            if (iter != buffer_.end()) {
                buffer_.erase(iter);
            }
        }
    }

    // clear the backup
    backup_.clear();

    log::debug(LOG_NETWORK)
            << "Reseeding finished, buffer size: " << buffer_.size();

    return error::success;
}

code hosts::remove(const address& host)
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    auto it = find(host);
    if (it != buffer_.end()) {
        buffer_.erase(it);
    }

    if (find(inactive_, host) == inactive_.end()) {
        inactive_.push_back(host);
    }

    return error::success;
}

code hosts::store_seed(const address& host)
{
    // don't store blacklist and banned address
    if (channel::blacklisted(host) || channel::manualbanned(host)) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    auto iter = std::find_if(seeds_.begin(), seeds_.end(),
        [&host](const address& item){
            return host.ip == item.ip && host.port == item.port;
        });

    if (iter == seeds_.end()) {
        constexpr size_t max_seeds = 8;
        constexpr size_t half_pos = max_seeds >> 1;
        upgrade_to_unique_lock unq_lock(lock);
        if (seeds_.size() == max_seeds) { // full
            std::copy(seeds_.begin()+half_pos+1, seeds_.end(), seeds_.begin()+half_pos);
            seeds_.back() = host;
        }
        else {
            seeds_.push_back(host);
        }
#ifdef PRIVATE_CHAIN
        log::info(LOG_NETWORK) << "store seed " << config::authority(host).to_string();
#endif
    }

    return error::success;
}

code hosts::remove_seed(const address& host)
{
    if (disabled_) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    auto iter = std::find_if(seeds_.begin(), seeds_.end(),
        [&host](const address& item){
            return host.ip == item.ip && host.port == item.port;
        });

    if (iter != seeds_.end()) {
        upgrade_to_unique_lock unq_lock(lock);
        seeds_.erase(iter);

#ifdef PRIVATE_CHAIN
        log::info(LOG_NETWORK) << "remove seed " << config::authority(host).to_string();
#endif
    }

    return error::success;
}

code hosts::store(const address& host)
{
    if (disabled_) {
        return error::success;
    }

    if (!host.is_routable()) {
        // We don't treat invalid address as an error, just log it.
        return error::success;
    }

    // don't store self address
    auto authority = config::authority{host};
    if (authority == self_ || authority.port() == 0) {
        return error::success;
    }

    // don't store blacklist and banned address
    if (channel::blacklisted(host) || channel::manualbanned(host)) {
        return error::success;
    }

    // Critical Section
    upgrade_lock lock(mutex_);

    if (stopped_) {
        return error::service_stopped;
    }

    upgrade_to_unique_lock unq_lock(lock);

    if (find(host) == buffer_.end()) {
        buffer_.push_back(host);
    }

    auto iter = find(inactive_, host);
    if (iter != inactive_.end()) {
        inactive_.erase(iter);
    }

    return error::success;
}

// The handler is invoked once all calls to do_store are completed.
// We disperse here to allow other addresses messages to interleave hosts.
void hosts::store(const address::list& hosts, result_handler handler)
{
    if (disabled_ || hosts.empty()) {
        handler(error::success);
        return;
    }

    // Critical Section
    mutex_.lock_upgrade();

    if (stopped_) {
        mutex_.unlock_upgrade();

        handler(error::service_stopped);
        return;
    }

    // Accept between 1 and all of this peer's addresses up to capacity.
    const auto capacity = host_pool_capacity_;
    size_t host_size = hosts.size();
    const size_t usable = std::min(host_size, capacity);
    const size_t random = static_cast<size_t>(pseudo_random(1, usable));

    // But always accept at least the amount we are short if available.
    const size_t gap = capacity - buffer_.size();
    const size_t accept = std::max(gap, random);

    // Convert minimum desired to step for iteration, no less than 1.
    const auto step = std::max(usable / accept, size_t(1));
    size_t accepted = 0;

    mutex_.unlock_upgrade_and_lock();
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    for (size_t index = 0; index < usable; index = ceiling_add(index, step)) {
        const auto& host = hosts[index];

        // Do not treat invalid address as an error, just log it.
        if (!host.is_valid()) {
            log::debug(LOG_NETWORK)
                    << "Invalid host address from peer.";
            continue;
        }

        if (channel::blacklisted(host) || channel::manualbanned(host)) {
            continue;
        }

        // Do not allow duplicates in the host cache.
        if (find(host) == buffer_.end()
                && find(inactive_, host) == inactive_.end()) {
            ++accepted;
            buffer_.push_back(host);
        }
    }

    log::debug(LOG_NETWORK)
            << "Accepted (" << accepted << " of " << hosts.size()
            << ") host addresses from peer."
            << " inactive size is " << inactive_.size()
            << ", buffer size is " << buffer_.size();

    mutex_.unlock();

    handler(error::success);
}

} // namespace network
} // namespace libbitcoin
<|endoftext|>


<commit_before>#include <iostream> //cout
#include <string>
#include "qmc.h"
#include <gmc.h> 	//LaGenMatComplex
#include <laslv.h>  //LUFactorizeIP, LaLUInverseIP, etc.
#include <blas3pp.h>
#include <random>   //random_device, mt19937
#include <cstdlib>	//rand, srand
#include <math.h>

using namespace std;

/* ---- WORKING ---- */
/* Randomisation */
int random_spin(){
    random_device rd;
    mt19937 gen(rd());
    std::uniform_int_distribution<> dist(0, 1);
    return dist(gen)*2 - 1;
}
float random_probability(){
    random_device rd;
    mt19937 gen(rd());
    std::uniform_real_distribution<> dist(0, 1);
    return dist(gen);
}

/* Testing */
void test_spin_generation(){
    for(int i = 0; i < 5; i++){
        cout.width(10);
        cout << random_spin();
    }
    cout << endl;
}
void test_probability_generation(){
    for(int i = 0; i < 5; i++){
        cout.width(5);
        cout << random_probability();
    }
    cout << endl;
}

/* ---- TESTING ----*/
/* Output */
void print_sites(const int array[], const int array_size){
    for(int i = 0; i < array_size; i++){
        cout.width(7);
        cout << array[i];
    }
    cout << endl;
}

/* Randomisation */

/* Generation */
void generate_lattice_array(const int array_size, int array[]){
    for(int i = 0; i < array_size; i++){
        array[i] = random_spin();
    }
}

/* Testing */
void test_generate_lattice_array(){
    int array_size = 5, array[5];
    generate_lattice_array(array_size, array);
    print_sites(array, array_size);
}

void test_sweep(){
    /* Plan */
    /* [ ] Input */
        // [ ] lattice_size - int
        // [ ] time_slices  - int
        // [ ] iterations   - int
        // [ ] lattice      - LaGenMatComplex
        // [ ] U            - float

    /* [ ] Processing */
        // [ ] generate a lattice of spins
        // [ ] sweep the lattice

    /* [ ] Output */
        // [ ] average spins
        // [ ] acceptance probabilities

    // int lattice_size = 5, time_slices = 4;
    // int matrix_size = lattice_size * time_slices;

}
void test_increasing_U(){
    /* Plan */

    /* [ ] Input */
        // [ ] matrix_size  - int
        // [ ] iterations   - int
        // [ ] lattice      - LaGenMatComplex
        // [ ] U            - float

    /* [ ] Processing */
        // [ ] for n increasing values of U
            // [ ] generate a lattice of spins
            // [ ] sweep the lattice

    /* [ ] Output */
        // [ ] acceptance probabilities
}

/* --- Main QMC Program --- */
int main(){
    test_generate_lattice_array();
}
<commit_msg>generate_lattice_array - testing<commit_after>#include <iostream> //cout
#include <string>
#include "qmc.h"
#include <gmc.h> 	//LaGenMatComplex
#include <laslv.h>  //LUFactorizeIP, LaLUInverseIP, etc.
#include <blas3pp.h>
#include <random>   //random_device, mt19937
#include <cstdlib>	//rand, srand
#include <math.h>

using namespace std;

/* ---- WORKING ---- */
/* Randomisation */
int random_spin(){
    random_device rd;
    mt19937 gen(rd());
    std::uniform_int_distribution<> dist(0, 1);
    return dist(gen)*2 - 1;
}
float random_probability(){
    random_device rd;
    mt19937 gen(rd());
    std::uniform_real_distribution<> dist(0, 1);
    return dist(gen);
}

/* Testing */
void test_spin_generation(){
    for(int i = 0; i < 5; i++){
        cout.width(10);
        cout << random_spin();
    }
    cout << endl;
}
void test_probability_generation(){
    for(int i = 0; i < 5; i++){
        cout.width(5);
        cout << random_probability();
    }
    cout << endl;
}

/* ---- TESTING ----*/
/* Output */
void print_sites(const int array[], const int array_size){
    for(int i = 0; i < array_size; i++){
        cout.width(7);
        cout << array[i];
    }
    cout << endl;
}

/* Randomisation */

/* Generation */
void generate_lattice_array(const int array_size, int array[]){
    for(int i = 0; i < array_size; i++){
        array[i] = random_spin();
    }
}

/* Testing */
void test_generate_lattice_array(){
    int array_size = 10, array[array_size];
    generate_lattice_array(array_size, array);
    print_sites(array, array_size);
}

void test_sweep(){
    /* Plan */
    /* [ ] Input */
        // [ ] lattice_size - int
        // [ ] time_slices  - int
        // [ ] iterations   - int
        // [ ] lattice      - LaGenMatComplex
        // [ ] U            - float

    /* [ ] Processing */
        // [ ] generate a lattice of spins
        // [ ] sweep the lattice

    /* [ ] Output */
        // [ ] average spins
        // [ ] acceptance probabilities

    // int lattice_size = 5, time_slices = 4;
    // int matrix_size = lattice_size * time_slices;

}
void test_increasing_U(){
    /* Plan */

    /* [ ] Input */
        // [ ] matrix_size  - int
        // [ ] iterations   - int
        // [ ] lattice      - LaGenMatComplex
        // [ ] U            - float

    /* [ ] Processing */
        // [ ] for n increasing values of U
            // [ ] generate a lattice of spins
            // [ ] sweep the lattice

    /* [ ] Output */
        // [ ] acceptance probabilities
}

/* --- Main QMC Program --- */
int main(){
    test_generate_lattice_array();
}
<|endoftext|>


<commit_before>//===-- Valgrind.cpp - Implement Valgrind communication ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Defines Valgrind communication methods, if HAVE_VALGRIND_VALGRIND_H is
//  defined.  If we have valgrind.h but valgrind isn't running, its macros are
//  no-ops.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Valgrind.h"
#include "llvm/Config/config.h"

#if HAVE_VALGRIND_VALGRIND_H
#include <valgrind/valgrind.h>

static bool InitNotUnderValgrind() {
  return !RUNNING_ON_VALGRIND;
}

// This bool is negated from what we'd expect because code may run before it
// gets initialized.  If that happens, it will appear to be 0 (false), and we
// want that to cause the rest of the code in this file to run the
// Valgrind-provided macros.
static const bool NotUnderValgrind = InitNotUnderValgrind();

bool llvm::sys::RunningOnValgrind() {
  if (NotUnderValgrind)
    return false;
  return RUNNING_ON_VALGRIND;
}

void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
  if (NotUnderValgrind)
    return;

  VALGRIND_DISCARD_TRANSLATIONS(Addr, Len);
}

#else  // !HAVE_VALGRIND_VALGRIND_H

bool llvm::sys::RunningOnValgrind() {
  return false;
}

void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
}

#endif  // !HAVE_VALGRIND_VALGRIND_H
<commit_msg>Add a missing include of cstddef needed for size_t.<commit_after>//===-- Valgrind.cpp - Implement Valgrind communication ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Defines Valgrind communication methods, if HAVE_VALGRIND_VALGRIND_H is
//  defined.  If we have valgrind.h but valgrind isn't running, its macros are
//  no-ops.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/Valgrind.h"
#include "llvm/Config/config.h"
#include <cstddef>

#if HAVE_VALGRIND_VALGRIND_H
#include <valgrind/valgrind.h>

static bool InitNotUnderValgrind() {
  return !RUNNING_ON_VALGRIND;
}

// This bool is negated from what we'd expect because code may run before it
// gets initialized.  If that happens, it will appear to be 0 (false), and we
// want that to cause the rest of the code in this file to run the
// Valgrind-provided macros.
static const bool NotUnderValgrind = InitNotUnderValgrind();

bool llvm::sys::RunningOnValgrind() {
  if (NotUnderValgrind)
    return false;
  return RUNNING_ON_VALGRIND;
}

void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
  if (NotUnderValgrind)
    return;

  VALGRIND_DISCARD_TRANSLATIONS(Addr, Len);
}

#else  // !HAVE_VALGRIND_VALGRIND_H

bool llvm::sys::RunningOnValgrind() {
  return false;
}

void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
}

#endif  // !HAVE_VALGRIND_VALGRIND_H
<|endoftext|>


<commit_before>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"

#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

using namespace MathLib;

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}

	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f,1.0f,0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);

}
CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}
int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
void CActorBase::Update(float ifps)
{
	if (!m_nEnable)
	{
		return;
	}

}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"

#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

using namespace MathLib;

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}

	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f,1.0f,0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);

}
CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}
int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
void CActorBase::Update(float ifps)
{
	if (!m_nEnable)
	{
		return;
	}
	// impulse
	vec3 impulse = vec3_zero;

	// ortho basis
	vec3 tangent, binormal;
	OrthoBasis(m_vUp, tangent, binormal);
}<|endoftext|>


<commit_before>#include "table.hpp"

#include <iomanip>

namespace opossum {

table::table(const size_t chunk_size) : _chunk_size(chunk_size) {
	_chunks.push_back(chunk());
}

void table::add_column(std::string &&name, std::string type) {
	_column_names.push_back(name);
	_column_types.push_back(type);
	for(auto &chunk : _chunks) {
		chunk.add_column(type);
	}
	// TODO default values for existing rows?
}

void table::append(std::initializer_list<all_type_variant> values) {
	if(_chunk_size > 0 && _chunks.back().size() == _chunk_size) {
		_chunks.emplace_back();

		// TODO add columns to new chunk - only once we know how to deal with different types (HANA?)
	}

	_chunks.back().append(values);
}

size_t table::col_count() const {
	return _column_types.size();
}

std::vector<int> table::column_string_widths(int max) const {
	std::vector<int> widths(col_count());
	for(size_t col = 0; col < col_count(); ++col) {
		widths[col] = to_string(_column_names[col]).size();
	}
	for(auto &&chunk : _chunks) {
		auto widths2 = chunk.column_string_widths(max);
		for(size_t col = 0; col < col_count(); ++col) {
			widths[col] = std::max(widths[col], widths2[col]);
		}
	}
	return widths;
}

void table::print(std::ostream &out) const {
	auto widths = column_string_widths(20);

	for(size_t col = 0; col < col_count(); ++col) {
		out << "|" << std::setw(widths[col]) << _column_names[col] << std::setw(0) << "|";
	}
	out << std::endl;

	size_t chunk_id = 0;
	for(auto &&chunk : _chunks) {
		out << "=== chunk " << chunk_id << " === " << std::endl;
		chunk_id++;
		chunk.print(out, widths);
	}
}

}<commit_msg>Added row_count() to opossum::table<commit_after>#include "table.hpp"

#include <iomanip>

namespace opossum {

table::table(const size_t chunk_size) : _chunk_size(chunk_size) {
	_chunks.push_back(chunk());
}

void table::add_column(std::string &&name, std::string type) {
	_column_names.push_back(name);
	_column_types.push_back(type);
	for(auto &chunk : _chunks) {
		chunk.add_column(type);
	}
	// TODO default values for existing rows?
}

void table::append(std::initializer_list<all_type_variant> values) {
	if(_chunk_size > 0 && _chunks.back().size() == _chunk_size) {
		_chunks.emplace_back();

		// TODO add columns to new chunk - only once we know how to deal with different types (HANA?)
	}

	_chunks.back().append(values);
}

size_t table::col_count() const {
	return _column_types.size();
}

size_t table::row_count() const {
	size_t ret = 0;
	for (auto &&chunk : _chunks) {
		ret += chunk.size();
	}
	return ret;
}

std::vector<int> table::column_string_widths(int max) const {
	std::vector<int> widths(col_count());
	for(size_t col = 0; col < col_count(); ++col) {
		widths[col] = to_string(_column_names[col]).size();
	}
	for(auto &&chunk : _chunks) {
		auto widths2 = chunk.column_string_widths(max);
		for(size_t col = 0; col < col_count(); ++col) {
			widths[col] = std::max(widths[col], widths2[col]);
		}
	}
	return widths;
}

void table::print(std::ostream &out) const {
	auto widths = column_string_widths(20);

	for(size_t col = 0; col < col_count(); ++col) {
		out << "|" << std::setw(widths[col]) << _column_names[col] << std::setw(0);
	}
	out << "|" << std::endl;

	size_t chunk_id = 0;
	for(auto &&chunk : _chunks) {
		out << "=== chunk " << chunk_id << " === " << std::endl;
		chunk_id++;
		chunk.print(out, widths);
	}
}

}<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifdef _WIN32
#pragma warning( 4:4786)
#endif

// interface header
#include "commands.h"

// implementation-specific system headers
#include <string>
#include <cstdio>
#include <cstring>

// implementation-specific bzflag headers
#include "global.h"
#include "Address.h"

// implementation-specific bzfs-specific headers
#include "VotingArbiter.h"
#include "Permissions.h"
#include "CmdLineOptions.h"
#include "PlayerInfo.h"

// FIXME -- need to pull communication out of bzfs.cxx...
extern void sendMessage(int playerIndex, PlayerId targetPlayer, const char *message, bool fullBuffer);
extern bool hasPerm(int playerIndex, PlayerAccessInfo::AccessPerm right);
extern PlayerInfo *player;
extern CmdLineOptions *clOptions;
extern uint16_t curMaxPlayers;
extern int NotConnected;

void handlePollCmd(int t, const char *message)
{
  char reply[MessageLen];

  /* make sure player has permission to request a poll */
  if (!hasPerm(t, PlayerAccessInfo::poll)) {
    sprintf(reply,"%s, you are presently not authorized to run /poll", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* make sure that there is a poll arbiter */
  if (BZDB->isEmpty("poll")) {
    sprintf(reply, "ERROR: the poll arbiter has disappeared (this should never happen)");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  // only need to do this once
  static VotingArbiter *arbiter = (VotingArbiter *)BZDB->getPointer("poll");

  /* make sure that there is not a poll active already */
  if (arbiter->knowsPoll()) {
    sprintf(reply,"A poll to %s %s is presently in progress", arbiter->getPollAction().c_str(), arbiter->getPollPlayer().c_str());
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"Unable to start a new poll until the current one is over");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  // get available voter count
  unsigned short int available = 0;
  for (int i=0; i < curMaxPlayers; i++) {
    // anyone on the server (even observers) are eligible to vote
    if (player[i].fd != NotConnected) {
      available++;
    }
  }

  // make sure there are enough players to even make a poll (don't count the pollee)
  if (available - 1 < clOptions->votesRequired) {
    sprintf(reply,"Unable to initiate a new poll.  There are not enough players.");
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"There needs to be at least %d other %s and only %d %s available.",
	    clOptions->votesRequired,
	    clOptions->votesRequired - 1 == 1 ? "player" : "players",
	    available - 1,
	    available - 1 == 1 ? "is" : "are");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  std::string pollCmd = &message[5];
  std::string cmd;
  std::string nick;

  unsigned int endPos;
  unsigned int startPos = pollCmd.find_first_not_of(" \t");
  if (startPos != std::string::npos) {
    endPos = pollCmd.find_first_of(" \t", startPos);
    if (endPos == std::string::npos)
      endPos = pollCmd.length();

    cmd = pollCmd.substr(startPos,endPos-startPos);
    pollCmd = pollCmd.substr(endPos);
  }
  else {
    sprintf(reply,"Invalid poll syntax: /poll (kick|ban|vote|veto) playername");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  if ((cmd == "ban") || (cmd == "kick")) {

    startPos = pollCmd.find_first_not_of(" \t");
    if (startPos != std::string::npos) {
      std::string votePlayer = pollCmd.substr(startPos);
      if (votePlayer.length() == 0) {
	sprintf(reply,"%s, no player was specified for the %s vote", player[t].callSign, cmd.c_str());
	sendMessage(ServerPlayer, t, reply, true);
	sprintf(reply,"Usage: /poll %s [playername]", cmd.c_str());
	sendMessage(ServerPlayer, t, reply, true);
	return;
      }

      /* make sure the requested player is actually here */
      bool foundPlayer=false;
      std::string playerIP = "";
      for (int v = 0; v < curMaxPlayers; v++) {
	if (votePlayer == player[v].callSign) {
	  playerIP = player[v].peer.getDotNotation().c_str();
	  foundPlayer=true;
	  break;
	}
      }

      if (!foundPlayer) {
	/* wrong name? */
	sprintf(reply, "The player specified for a %s vote is not here", cmd.c_str());
	sendMessage(ServerPlayer, t, reply, true);
	sprintf(reply,"Usage: /poll %s [playername]", cmd.c_str());
	sendMessage(ServerPlayer, t, reply, true);
	return;
      }

      /* create and announce the new poll */
      if (cmd == "ban") {
	if (arbiter->pollToBan(votePlayer.c_str(), player[t].callSign, playerIP) == false) {
	  sprintf(reply,"You are not able to request a ban poll right now, %s", player[t].callSign);
	  sendMessage(ServerPlayer, t, reply, true);
	} else {
	  sprintf(reply,"A poll to temporarily ban %s has been requested by %s", votePlayer.c_str(), player[t].callSign);
	  sendMessage(ServerPlayer, AllPlayers, reply, true);
	}
      } else {
	if (arbiter->pollToKick(votePlayer.c_str(), player[t].callSign) == false) {
	  sprintf(reply,"You are not able to request a kick poll right now, %s", player[t].callSign);
	  sendMessage(ServerPlayer, t, reply, true);
	} else {
	  sprintf(reply,"A poll to %s %s has been requested by %s", cmd.c_str(), votePlayer.c_str(), player[t].callSign);
	  sendMessage(ServerPlayer, AllPlayers, reply, true);
	}
      }

      // set the number of available voters
      arbiter->setAvailableVoters(available);

      // keep track of who is allowed to vote
      for (int j=0; j < curMaxPlayers; j++) {
	// anyone on the server (even observers) are eligible to vote
	if (player[j].fd != NotConnected) {
	  arbiter->grantSuffrage(player[j].callSign);
	}
      }

      // automatically place a vote for the player requesting the poll
      arbiter->voteYes(player[t].callSign);
    }
    else {
      sprintf(reply,"Invalid poll syntax: /poll %s playername", cmd.c_str());
      sendMessage(ServerPlayer, t, reply, true);
      return;
    }
  } else if (cmd == "vote") {

    if (!hasPerm(t, PlayerAccessInfo::vote)) {
      sprintf(reply,"%s, you do not presently have permission to vote (must /identify first)", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
      return;
    }

    /* !!! needs to be handled by the /vote command  */
    sprintf(reply,"%s, your vote has been recorded -- unimplemented", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);

  } else if (cmd == "veto") {

    if (!hasPerm(t, PlayerAccessInfo::veto)) {
      sprintf(reply,"%s, you do not have permission to veto the poll", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
    }

    /* !!! needs to be handled by the /veto command  */
    sprintf(reply,"%s, you have aborted the poll -- unimplemented", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);

  } else {

    sprintf(reply,"Invalid option to the poll command");
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"Usage: /poll ban|kick [playername]");
    sendMessage(ServerPlayer, t, reply, true);
  } /* end handling of poll subcommands */

  return;
}

void handleVoteCmd(int t, const char *message)
{
  char reply[MessageLen];

  if (!hasPerm(t, PlayerAccessInfo::vote)) {
    /* permission denied for /vote */
    sprintf(reply,"%s, you are presently not authorized to run /vote", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* make sure that there is a poll arbiter */
  if (BZDB->isEmpty("poll")) {
    sprintf(reply, "ERROR: the poll arbiter has disappeared (this should never happen)");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  // only need to get this once
  static VotingArbiter *arbiter = (VotingArbiter *)BZDB->getPointer("poll");

  /* make sure that there is a poll to vote upon */
  if ((arbiter != NULL) && !arbiter->knowsPoll()) {
    sprintf(reply,"A poll is not presently in progress.  There is nothing to vote on");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* find the start of the vote answer */

  std::string answer;
  std::string voteCmd = &message[5];

  unsigned int startPos = voteCmd.find_first_not_of(" \t");
  if (startPos != std::string::npos) {
    unsigned int endPos = voteCmd.find_first_of(" \t", startPos);
    if (endPos == std::string::npos)
      endPos = voteCmd.length();
    answer = voteCmd.substr(startPos, endPos-startPos);
  }

  /* XXX answer arrays should be static const but it'll do for now */
  static const unsigned int yesCount = 8;
  char yesAnswers[8][5];
  sprintf(yesAnswers[0], "y");
  sprintf(yesAnswers[1], "1");
  sprintf(yesAnswers[2], "yes");
  sprintf(yesAnswers[3], "yea");
  sprintf(yesAnswers[4], "si");
  sprintf(yesAnswers[5], "ja");
  sprintf(yesAnswers[6], "oui");
  sprintf(yesAnswers[7], "sim");

  static const unsigned int noCount = 7;
  char noAnswers[7][5];
  sprintf(noAnswers[0], "n");
  sprintf(noAnswers[1], "0");
  sprintf(noAnswers[2], "no");
  sprintf(noAnswers[3], "nay");
  sprintf(noAnswers[4], "nein");
  sprintf(noAnswers[5], "non");
  sprintf(noAnswers[6], "nao");

  // see if the vote response is a valid yes or no answer
  int vote=-1;
  for (unsigned int v = 0; v < (noCount > yesCount ? noCount : yesCount); v++) {
    if (v < yesCount) {
      if (answer == yesAnswers[v]) {
	vote = 1;
	break;
      }
    }
    if (v < noCount) {
      if (answer == noAnswers[v]) {
	vote = 0;
	break;
      }
    }
  }

  // cast the vote or complain
  bool cast = false;
  if (vote == 0) {
    if ((cast = arbiter->voteNo(player[t].callSign)) == true) {
      /* player voted no */
      sprintf(reply,"%s, your vote in opposition of the %s has been recorded", player[t].callSign, arbiter->getPollAction().c_str());
      sendMessage(ServerPlayer, t, reply, true);
    }
  } else if (vote == 1) {
    if ((cast = arbiter->voteYes(player[t].callSign)) == true) {
      /* player voted yes */
      sprintf(reply,"%s, your vote in favor of the %s has been recorded", player[t].callSign, arbiter->getPollAction().c_str());
      sendMessage(ServerPlayer, t, reply, true);
    }
  } else {
    if (answer.length() == 0) {
      sprintf(reply,"%s, you did not provide a vote answer", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
      sprintf(reply,"Usage: /vote yes|no|y|n|1|0|yea|nay|si|ja|nein|oui|non|sim|nao");
      sendMessage(ServerPlayer, t, reply, true);
    } else {
      sprintf(reply,"%s, you did not vote in favor or in opposition", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
      sprintf(reply,"Usage: /vote yes|no|y|n|1|0|yea|nay|si|ja|nein|oui|non|sim|nao");
      sendMessage(ServerPlayer, t, reply, true);
    }
    return;
  }

  if (!cast) {
    /* player was unable to cast their vote; probably already voted */
    sprintf(reply,"%s, you have already voted on the poll to %s %s", player[t].callSign, arbiter->getPollAction().c_str(), arbiter->getPollPlayer().c_str());
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  return;
}

void handleVetoCmd(int t, const char * /*message*/)
{
  char reply[MessageLen];
  if (!hasPerm(t, PlayerAccessInfo::veto)) {
    /* permission denied for /veto */
    sprintf(reply,"%s, you are presently not authorized to run /veto", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* make sure that there is a poll arbiter */
  if (BZDB->isEmpty("poll")) {
    sprintf(reply, "ERROR: the poll arbiter has disappeared (this should never happen)");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  // only need to do this once
  static VotingArbiter *arbiter = (VotingArbiter *)BZDB->getPointer("poll");

  /* make sure there is an unexpired poll */
  if ((arbiter != NULL) && !arbiter->knowsPoll()) {
    sprintf(reply, "%s, there is presently no active poll to veto", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* poof */
  arbiter->forgetPoll();

  sprintf(reply,"%s, you have cancelled the poll to %s %s", player[t].callSign, arbiter->getPollAction().c_str(), arbiter->getPollPlayer().c_str());
  sendMessage(ServerPlayer, t, reply, true);

  sprintf(reply,"The poll was cancelled by %s", player[t].callSign);
  sendMessage(ServerPlayer, AllPlayers, reply, true);

  return;
}

// ex: shiftwidth=2 tabstop=8
<commit_msg>readded optional quoting, better whitespace checking, and stdified the vote strings<commit_after>/* bzflag
 * Copyright (c) 1993 - 2003 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifdef _WIN32
#pragma warning( 4:4786)
#endif

// interface header
#include "commands.h"

// implementation-specific system headers
#include <string>
#include <cstdio>
#include <cstring>

// implementation-specific bzflag headers
#include "global.h"
#include "Address.h"

// implementation-specific bzfs-specific headers
#include "VotingArbiter.h"
#include "Permissions.h"
#include "CmdLineOptions.h"
#include "PlayerInfo.h"

// FIXME -- need to pull communication out of bzfs.cxx...
extern void sendMessage(int playerIndex, PlayerId targetPlayer, const char *message, bool fullBuffer);
extern bool hasPerm(int playerIndex, PlayerAccessInfo::AccessPerm right);
extern PlayerInfo player[MaxPlayers];
extern CmdLineOptions *clOptions;
extern uint16_t curMaxPlayers;
extern int NotConnected;

void handlePollCmd(int t, const char *message)
{
  char reply[MessageLen] = {0};

  DEBUG2("Entered poll command handler (MessageLen is %d)\n", MessageLen);

  /* make sure player has permission to request a poll */
  if (!hasPerm(t, PlayerAccessInfo::poll)) {
    sprintf(reply,"%s, you are presently not authorized to run /poll", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  DEBUG2("Player has permission\n");

  /* make sure that there is a poll arbiter */
  if (BZDB->isEmpty("poll")) {
    sprintf(reply, "ERROR: the poll arbiter has disappeared (this should never happen)");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  DEBUG2("BZDB poll value is not empty\n");

  // only need to do this once
  static VotingArbiter *arbiter = (VotingArbiter *)BZDB->getPointer("poll");

  DEBUG2("Arbiter was acquired with address 0x%x\n", (unsigned int)arbiter);

  /* make sure that there is not a poll active already */
  if (arbiter->knowsPoll()) {
    sprintf(reply,"A poll to %s %s is presently in progress", arbiter->getPollAction().c_str(), arbiter->getPollPlayer().c_str());
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"Unable to start a new poll until the current one is over");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  DEBUG2("The arbiter says there is not another poll active\n");

  // get available voter count
  unsigned short int available = 0;
  for (int i=0; i < curMaxPlayers; i++) {
    // anyone on the server (even observers) are eligible to vote
    if (player[i].fd != NotConnected) {
      available++;
    }
  }

  DEBUG2("There are %d available players for %d votes required\n", available, clOptions->votesRequired);

  /* make sure there are enough players to even make a poll that has a chance
   * of succeeding (not counting the person being acted upon)
   */
  if (available - 1 < clOptions->votesRequired) {
    sprintf(reply,"Unable to initiate a new poll.  There are not enough players.");
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"There needs to be at least %d other %s and only %d %s available.",
	    clOptions->votesRequired,
	    clOptions->votesRequired - 1 == 1 ? "player" : "players",
	    available - 1,
	    available - 1 == 1 ? "is" : "are");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  std::string arguments = &message[5];
  std::string cmd = "";

  DEBUG2("The arguments string is [%s]\n", arguments.c_str());

  /* find the start of the command */
  size_t startPosition = 0;
  while ((startPosition < arguments.size()) &&
	 (isWhitespace(arguments[startPosition]))) {
    startPosition++;
  }

  DEBUG2("Start position is %d\n", (int)startPosition);

  /* find the end of the command */
  size_t endPosition = startPosition + 1;
  while ((endPosition < arguments.size()) &&
	 (!isWhitespace(arguments[endPosition]))) {
    endPosition++;
  }

  DEBUG2("End position is %d\n", (int)endPosition);

  /* stash the command ('kick', etc) in lowercase to simplify comparison */
  if ((startPosition != arguments.size()) &&
      (endPosition > startPosition)) {
    for (size_t i = startPosition; i < endPosition; i++) {
      cmd += tolower(arguments[i]);
    }
  }

  DEBUG2("Command is %s\n", cmd.c_str());

  /* handle subcommands */

  if ((cmd == "ban") || (cmd == "kick")) {

    std::string nick;

    arguments = arguments.substr(endPosition);

    DEBUG2("Command arguments rguments is [%s]\n", arguments.c_str());

    /* find the start of the player name */
    startPosition = 0;
    while ((startPosition < arguments.size()) &&
	   (isWhitespace(arguments[startPosition]))) {
      startPosition++;
    }
    // do not include a starting quote, if given
    if ( arguments[startPosition] == '"' ) {
      startPosition++;
    }

    DEBUG2("Start position for player name is %d\n", (int)startPosition);

    /* find the end of the player name */
    endPosition = arguments.size() - 1;
    while ((endPosition > 0) &&
	   (isWhitespace(arguments[endPosition]))) {
      endPosition--;
    }
    // do not include a trailing quote, if given
    if ( arguments[endPosition] == '"' ) {
      endPosition--;
    }

    DEBUG2("End position for player name is %d\n", (int)endPosition);

    nick = arguments.substr(startPosition, endPosition - startPosition + 1);

    DEBUG2("Player specified to vote upon is [%s]\n", nick.c_str());

    if (nick.length() == 0) {
      sprintf(reply,"%s, no player was specified for the [%s] vote", player[t].callSign, cmd.c_str());
      sendMessage(ServerPlayer, t, reply, true);
      sprintf(reply,"Usage: /poll %s playername", cmd.c_str());
      sendMessage(ServerPlayer, t, reply, true);
      return;
    }

    /* make sure the requested player is actually here */
    bool foundPlayer=false;
    std::string playerIP = "";
    for (int v = 0; v < curMaxPlayers; v++) {
      if (strncasecmp(nick.c_str(), player[v].callSign, 256) == 0) {
	playerIP = player[v].peer.getDotNotation().c_str();
	foundPlayer=true;
	break;
      }
    }

    if (!foundPlayer) {
      /* wrong name? */
      sprintf(reply, "The player specified for a %s vote is not here", cmd.c_str());
      sendMessage(ServerPlayer, t, reply, true);
      return;
    }

    /* create and announce the new poll */
    if (cmd == "ban") {
      if (arbiter->pollToBan(nick.c_str(), player[t].callSign, playerIP) == false) {
	sprintf(reply,"You are not able to request a ban poll right now, %s", player[t].callSign);
	sendMessage(ServerPlayer, t, reply, true);
	return;
      } else {
	sprintf(reply,"A poll to temporarily ban %s has been requested by %s", nick.c_str(), player[t].callSign);
	sendMessage(ServerPlayer, AllPlayers, reply, true);
      }
    } else {
      if (arbiter->pollToKick(nick.c_str(), player[t].callSign) == false) {
	sprintf(reply,"You are not able to request a kick poll right now, %s", player[t].callSign);
	sendMessage(ServerPlayer, t, reply, true);
	return;
      } else {
	sprintf(reply,"A poll to %s %s has been requested by %s", cmd.c_str(), nick.c_str(), player[t].callSign);
	sendMessage(ServerPlayer, AllPlayers, reply, true);
      }
    }

    // set the number of available voters
    arbiter->setAvailableVoters(available);

    // keep track of who is allowed to vote
    for (int j=0; j < curMaxPlayers; j++) {
      // anyone on the server (even observers) are eligible to vote
      if (player[j].fd != NotConnected) {
	arbiter->grantSuffrage(player[j].callSign);
      }
    }

    // automatically place a vote for the player requesting the poll
    arbiter->voteYes(player[t].callSign);

  } else if (cmd == "vote") {

    if (!hasPerm(t, PlayerAccessInfo::vote)) {
      sprintf(reply,"%s, you do not presently have permission to vote (must /identify first)", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
      return;
    }

    /* !!! needs to be handled by the /vote command  */
    sprintf(reply,"%s, your vote has been recorded -- unimplemented", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);

  } else if (cmd == "veto") {

    if (!hasPerm(t, PlayerAccessInfo::veto)) {
      sprintf(reply,"%s, you do not have permission to veto the poll", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
    }

    /* !!! needs to be handled by the /veto command  */
    sprintf(reply,"%s, you have aborted the poll -- unimplemented", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);

  } else {

    sprintf(reply,"Invalid option to the poll command");
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"Usage: /poll ban|kick playername");
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"    or /poll vote yes|no");
    sendMessage(ServerPlayer, t, reply, true);
    sprintf(reply,"    or /poll veto");
    sendMessage(ServerPlayer, t, reply, true);
  } /* end handling of poll subcommands */

  return;
}

void handleVoteCmd(int t, const char *message)
{
  char reply[MessageLen] = {0};

  if (!hasPerm(t, PlayerAccessInfo::vote)) {
    /* permission denied for /vote */
    sprintf(reply,"%s, you are presently not authorized to run /vote", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* make sure that there is a poll arbiter */
  if (BZDB->isEmpty("poll")) {
    sprintf(reply, "ERROR: the poll arbiter has disappeared (this should never happen)");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  // only need to get this once
  static VotingArbiter *arbiter = (VotingArbiter *)BZDB->getPointer("poll");

  /* make sure that there is a poll to vote upon */
  if ((arbiter != NULL) && !arbiter->knowsPoll()) {
    sprintf(reply,"A poll is not presently in progress.  There is nothing to vote on");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  std::string voteCmd = &message[5];
  std::string answer;

  /* find the start of the vote answer */
  size_t startPosition = 0;
  while ((startPosition < voteCmd.size()) &&
	 (isWhitespace(voteCmd[startPosition]))) {
    startPosition++;
  }

  /* stash the answer ('yes', 'no', etc) in lowercase to simplify comparison */
  for (size_t i = startPosition;  i < voteCmd.size() && !isWhitespace(voteCmd[i]); i++) {
    answer += tolower(voteCmd[i]);
  }

  std::vector<std::string> yesAnswers;
  yesAnswers.push_back("y");
  yesAnswers.push_back("1");
  yesAnswers.push_back("yes");
  yesAnswers.push_back("yea");
  yesAnswers.push_back("si");
  yesAnswers.push_back("ja");
  yesAnswers.push_back("oui");
  yesAnswers.push_back("sim");

  std::vector<std::string> noAnswers;
  noAnswers.push_back("n");
  noAnswers.push_back("0");
  noAnswers.push_back("no");
  noAnswers.push_back("nay");
  noAnswers.push_back("nein");
  noAnswers.push_back("non");
  noAnswers.push_back("nao");

  // see if the vote response is a valid yes or no answer
  int vote=-1;
  unsigned int maxAnswerCount = noAnswers.size() > yesAnswers.size() ? noAnswers.size() : yesAnswers.size();
  for (unsigned int v = 0; v < maxAnswerCount; v++) {
    if (v < yesAnswers.size()) {
      if (answer == yesAnswers[v]) {
	vote = 1;
	break;
      }
    }
    if (v < noAnswers.size()) {
      if (answer == noAnswers[v]) {
	vote = 0;
	break;
      }
    }
  }

  // cast the vote or complain
  bool cast = false;
  if (vote == 0) {
    if ((cast = arbiter->voteNo(player[t].callSign)) == true) {
      /* player voted no */
      sprintf(reply,"%s, your vote in opposition of the %s has been recorded", player[t].callSign, arbiter->getPollAction().c_str());
      sendMessage(ServerPlayer, t, reply, true);
    }
  } else if (vote == 1) {
    if ((cast = arbiter->voteYes(player[t].callSign)) == true) {
      /* player voted yes */
      sprintf(reply,"%s, your vote in favor of the %s has been recorded", player[t].callSign, arbiter->getPollAction().c_str());
      sendMessage(ServerPlayer, t, reply, true);
    }
  } else {
    if (answer.length() == 0) {
      sprintf(reply,"%s, you did not provide a vote answer", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
    } else {
      sprintf(reply,"%s, you did not vote in favor or in opposition", player[t].callSign);
      sendMessage(ServerPlayer, t, reply, true);
    }
    sprintf(reply,"Usage: /vote yes|no|y|n|1|0|yea|nay|si|ja|nein|oui|non|sim|nao");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  if (!cast) {
    /* player was unable to cast their vote; probably already voted */
    sprintf(reply,"%s, you have already voted on the poll to %s %s", player[t].callSign, arbiter->getPollAction().c_str(), arbiter->getPollPlayer().c_str());
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  return;
}

void handleVetoCmd(int t, const char * /*message*/)
{
  char reply[MessageLen] = {0};

  if (!hasPerm(t, PlayerAccessInfo::veto)) {
    /* permission denied for /veto */
    sprintf(reply,"%s, you are presently not authorized to run /veto", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* make sure that there is a poll arbiter */
  if (BZDB->isEmpty("poll")) {
    sprintf(reply, "ERROR: the poll arbiter has disappeared (this should never happen)");
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  // only need to do this once
  static VotingArbiter *arbiter = (VotingArbiter *)BZDB->getPointer("poll");

  /* make sure there is an unexpired poll */
  if ((arbiter != NULL) && !arbiter->knowsPoll()) {
    sprintf(reply, "%s, there is presently no active poll to veto", player[t].callSign);
    sendMessage(ServerPlayer, t, reply, true);
    return;
  }

  /* poof */
  arbiter->forgetPoll();

  sprintf(reply,"%s, you have cancelled the poll to %s %s", player[t].callSign, arbiter->getPollAction().c_str(), arbiter->getPollPlayer().c_str());
  sendMessage(ServerPlayer, t, reply, true);

  sprintf(reply,"The poll was cancelled by %s", player[t].callSign);
  sendMessage(ServerPlayer, AllPlayers, reply, true);

  return;
}

// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"

#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

using namespace MathLib;

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}

	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f,1.0f,0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);

}
CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}
int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
void CActorBase::Update(float ifps)
{
	if (!m_nEnable)
	{
		return;
	}
	// impulse
	vec3 impulse = vec3_zero;

	// ortho basis
	vec3 tangent, binormal;
	OrthoBasis(m_vUp, tangent, binormal);
	// current basis
	vec3 x = quat(m_vUp, -m_fPhiAngle) * binormal;
	vec3 y = Normalize(Cross(m_vUp, x));
	vec3 z = Normalize(Cross(x, y));
	// handle states
	Update_States(1, ifps);

	// old velocity
	float x_velocity = Dot(x, m_vVelocity);
	float y_velocity = Dot(y, m_vVelocity);
	float z_velocity = Dot(z, m_vVelocity);

	// movement
	if (m_pStates[STATE_FORWARD]) impulse += x;
	if (m_pStates[STATE_BACKWARD]) impulse -= x;
	if (m_pStates[STATE_MOVE_LEFT]) impulse += y;
	if (m_pStates[STATE_MOVE_RIGHT]) impulse -= y;
	impulse.normalize();
	// velocity
	if (m_pStates[STATE_RUN]) impulse *= m_fMaxVelocity;
	else impulse *= m_fMinVelocity;

	// jump
	if (m_pStates[STATE_JUMP] == STATE_BEGIN)
	{
		impulse += z * CMathCore::Sqrt(2.0f * 9.8f * m_fJumping) / (m_fAcceleration * ifps);
	}

	// rotate velocity
	if (GetGround())
	{
		m_vVelocity = x * x_velocity + y * y_velocity + z * z_velocity;
	}
	// time
	float time = ifps * g_Engine.pPhysics->GetScale();
	// target velocity
	float target_velocity = Length(vec2(Dot(x, impulse), Dot(y, impulse)));

	// penetration tolerance
	float penetration = g_Engine.pPhysics->GetPenetrationTolerance();
	float penetration_2 = penetration * 2.0f;

	// frozen linear velocity
	float frozen_velocity = g_Engine.pPhysics->GetFrozenLinearVelocity();

	// friction
	float friction = 0.0f;
	if (target_velocity < EPSILON)
	{
		friction = m_fFriction;
	}

	// clear collision flags
	if (GetCollision())
	{
		m_nGround = 0;
		m_nCeiling = 0;
	}

	// movement
	do
	{
		// adaptive time step
		float ifps = Min(time, ACTOR_BASE_IFPS);
		time -= ifps;
		// save old velocity
		float old_velocity = Length(vec2(Dot(x, m_vVelocity), Dot(y, m_vVelocity)));

		// integrate velocity
		m_vVelocity += impulse * (m_fAcceleration * ifps);
		m_vVelocity += g_Engine.pPhysics->GetGravity() * ifps;

		// damping
		float current_velocity = Length(vec2(Dot(x, m_vVelocity), Dot(y, m_vVelocity)));
		if (target_velocity < EPSILON || current_velocity > target_velocity)
		{
			m_vVelocity = (x * Dot(x, m_vVelocity) + y * Dot(y, m_vVelocity)) * CMathCore::Exp(-m_fDamping * ifps) + z * Dot(z, m_vVelocity);
		}

		// clamp maximum velocity
		current_velocity = Length(vec2(Dot(x, m_vVelocity), Dot(y, m_vVelocity)));

		if (current_velocity > old_velocity)
		{
			if (current_velocity > target_velocity)
			{
				m_vVelocity = (x * Dot(x, m_vVelocity) + y * Dot(y, m_vVelocity)) * target_velocity / current_velocity + z * Dot(z, m_vVelocity);
			}
		}
		// integrate position
		//m_vPosition += Vec3(m_vVelocity * ifps);
		if (GetCollision())
		{
			// get collision
			vec3 tangent, binormal;
			const Vec3 *caps = m_pShape->GetCaps();
			for (int i = 0; i < ACTOR_BASE_COLLISIONS; i++)
			{
				m_pDummy->SetTransform(Get_Body_Transform());
				m_pShape->GetCollision(m_vecContacts, 0.0f);

				if (m_vecContacts.Size() == 0) break;
				float inum_contacts = 1.0f / CMathCore::Itof(m_vecContacts.Size());
				for (int j = 0; j < m_vecContacts.Size(); j++)
				{
					const CShape::Contact &c = m_vecContacts[j];

					vec3 normalCollision = c.normal;
					if (is_frozen && c.depth < penetration_2)
					{
						m_vPosition += Vec3(z * (Max(c.depth - penetration, 0.0f) * inum_contacts * Dot(z, normalCollision)));
					}
					else
					{
						m_vPosition += Vec3(normalCollision * (Max(c.depth - penetration, 0.0f) * inum_contacts));
						is_frozen = 0;
					}
					float normal_velocity = Dot(normalCollision, m_vVelocity);
					if (normal_velocity < 0.0f)
					{
						m_vVelocity -= normalCollision * normal_velocity;
					}
					if (friction > EPSILON)
					{
						OrthoBasis(c.normal, tangent, binormal);
						float tangent_velocity = Dot(tangent, m_vVelocity);
						float binormal_velocity = Dot(binormal, m_vVelocity);
						if (CMathCore::Abs(tangent_velocity) > EPSILON || CMathCore::Abs(binormal_velocity) > EPSILON)
						{

						}

					}

				}

			}
		}
	}

}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"

#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

using namespace MathLib;

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/

CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//б		άƽϵУֱYķX֮ļн
	m_fThetaAngle = 0.0f;			//λǣ뵱ǰ˳ʱ߹ĽǶ

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}

	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f,1.0f,0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);

}
CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}
int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
void CActorBase::Update(float ifps)
{
	if (!m_nEnable)
	{
		return;
	}
	// impulse
	vec3 impulse = vec3_zero;

	// ortho basis
	vec3 tangent, binormal;
	OrthoBasis(m_vUp, tangent, binormal);
	// current basis
	vec3 x = quat(m_vUp, -m_fPhiAngle) * binormal;
	vec3 y = Normalize(Cross(m_vUp, x));
	vec3 z = Normalize(Cross(x, y));
	// handle states
	Update_States(1, ifps);

	// old velocity
	float x_velocity = Dot(x, m_vVelocity);
	float y_velocity = Dot(y, m_vVelocity);
	float z_velocity = Dot(z, m_vVelocity);

	// movement
	if (m_pStates[STATE_FORWARD]) impulse += x;
	if (m_pStates[STATE_BACKWARD]) impulse -= x;
	if (m_pStates[STATE_MOVE_LEFT]) impulse += y;
	if (m_pStates[STATE_MOVE_RIGHT]) impulse -= y;
	impulse.normalize();
	// velocity
	if (m_pStates[STATE_RUN]) impulse *= m_fMaxVelocity;
	else impulse *= m_fMinVelocity;

	// jump
	if (m_pStates[STATE_JUMP] == STATE_BEGIN)
	{
		impulse += z * CMathCore::Sqrt(2.0f * 9.8f * m_fJumping) / (m_fAcceleration * ifps);
	}

	// rotate velocity
	if (GetGround())
	{
		m_vVelocity = x * x_velocity + y * y_velocity + z * z_velocity;
	}
	// time
	float time = ifps * g_Engine.pPhysics->GetScale();
	// target velocity
	float target_velocity = Length(vec2(Dot(x, impulse), Dot(y, impulse)));

	// penetration tolerance
	float penetration = g_Engine.pPhysics->GetPenetrationTolerance();
	float penetration_2 = penetration * 2.0f;

	// frozen linear velocity
	float frozen_velocity = g_Engine.pPhysics->GetFrozenLinearVelocity();

	// friction
	float friction = 0.0f;
	if (target_velocity < EPSILON)
	{
		friction = m_fFriction;
	}

	// clear collision flags
	if (GetCollision())
	{
		m_nGround = 0;
		m_nCeiling = 0;
	}

	// movement
	do
	{
		// adaptive time step
		float ifps = Min(time, ACTOR_BASE_IFPS);
		time -= ifps;
		// save old velocity
		float old_velocity = Length(vec2(Dot(x, m_vVelocity), Dot(y, m_vVelocity)));

		// integrate velocity
		m_vVelocity += impulse * (m_fAcceleration * ifps);
		m_vVelocity += g_Engine.pPhysics->GetGravity() * ifps;

		// damping
		float current_velocity = Length(vec2(Dot(x, m_vVelocity), Dot(y, m_vVelocity)));
		if (target_velocity < EPSILON || current_velocity > target_velocity)
		{
			m_vVelocity = (x * Dot(x, m_vVelocity) + y * Dot(y, m_vVelocity)) * CMathCore::Exp(-m_fDamping * ifps) + z * Dot(z, m_vVelocity);
		}

		// clamp maximum velocity
		current_velocity = Length(vec2(Dot(x, m_vVelocity), Dot(y, m_vVelocity)));

		if (current_velocity > old_velocity)
		{
			if (current_velocity > target_velocity)
			{
				m_vVelocity = (x * Dot(x, m_vVelocity) + y * Dot(y, m_vVelocity)) * target_velocity / current_velocity + z * Dot(z, m_vVelocity);
			}
		}
		// integrate position
		//m_vPosition += Vec3(m_vVelocity * ifps);
		if (GetCollision())
		{
			// get collision
			vec3 tangent, binormal;
			const Vec3 *caps = m_pShape->GetCaps();
			for (int i = 0; i < ACTOR_BASE_COLLISIONS; i++)
			{
				m_pDummy->SetTransform(Get_Body_Transform());
				m_pShape->GetCollision(m_vecContacts, 0.0f);

				if (m_vecContacts.Size() == 0) break;
				float inum_contacts = 1.0f / CMathCore::Itof(m_vecContacts.Size());
				for (int j = 0; j < m_vecContacts.Size(); j++)
				{
					const CShape::Contact &c = m_vecContacts[j];

					vec3 normalCollision = c.normal;
					if (is_frozen && c.depth < penetration_2)
					{
						m_vPosition += Vec3(z * (Max(c.depth - penetration, 0.0f) * inum_contacts * Dot(z, normalCollision)));
					}
					else
					{
						m_vPosition += Vec3(normalCollision * (Max(c.depth - penetration, 0.0f) * inum_contacts));
						is_frozen = 0;
					}
					float normal_velocity = Dot(normalCollision, m_vVelocity);
					if (normal_velocity < 0.0f)
					{
						m_vVelocity -= normalCollision * normal_velocity;
					}
					if (friction > EPSILON)
					{
						OrthoBasis(c.normal, tangent, binormal);
						float tangent_velocity = Dot(tangent, m_vVelocity);
						float binormal_velocity = Dot(binormal, m_vVelocity);
						if (CMathCore::Abs(tangent_velocity) > EPSILON || CMathCore::Abs(binormal_velocity) > EPSILON)
						{
							float friction_velocity = Clamp(Max(-normal_velocity, 0.0f) * friction * CMathCore::RSqrt(tangent_velocity * tangent_velocity + binormal_velocity * binormal_velocity), -1.0f, 1.0f);
							m_vVelocity -= tangent * tangent_velocity * friction_velocity;
							m_vVelocity -= binormal * binormal_velocity * friction_velocity;

						}

					}

				}

			}
		}
	}

}<|endoftext|>


<commit_before>#pragma once
#include "TimingTags.hpp"
#include "timing_graph_fwd.hpp"
#include "tatum_linear_map.hpp"

namespace tatum { namespace detail {

/** \class CommonAnalysisOps
 *
 * The operations for CommonAnalysisVisitor to perform setup analysis.
 * The setup analysis operations define that maximum edge delays are used, and that the
 * maixmum arrival time (and minimum required times) are propagated through the timing graph.
 *
 * \see HoldAnalysisOps
 * \see CommonAnalysisVisitor
 */
class CommonAnalysisOps {
    public:
        CommonAnalysisOps(size_t num_tags)
            : data_tags_(num_tags, NUM_DATA_TAGS_RESERVE)
            , clock_launch_tags_(num_tags, NUM_CLK_TAGS_RESERVE)
            , clock_capture_tags_(num_tags, NUM_CLK_TAGS_RESERVE) {}

        TimingTags& get_data_tags(const NodeId node_id) { return data_tags_[node_id]; }
        TimingTags& get_launch_clock_tags(const NodeId node_id) { return clock_launch_tags_[node_id]; }
        TimingTags& get_capture_clock_tags(const NodeId node_id) { return clock_capture_tags_[node_id]; }
        const TimingTags& get_data_tags(const NodeId node_id) const { return data_tags_[node_id]; }
        const TimingTags& get_launch_clock_tags(const NodeId node_id) const { return clock_launch_tags_[node_id]; }
        const TimingTags& get_capture_clock_tags(const NodeId node_id) const { return clock_capture_tags_[node_id]; }

        void reset() {
            data_tags_.clear();
            clock_launch_tags_.clear();
            clock_capture_tags_.clear();
        }

    private:
        constexpr static size_t NUM_DATA_TAGS_RESERVE = 1;
        constexpr static size_t NUM_CLK_TAGS_RESERVE = 0;
        tatum::util::linear_map<NodeId,TimingTags> data_tags_;
        tatum::util::linear_map<NodeId,TimingTags> clock_launch_tags_;
        tatum::util::linear_map<NodeId,TimingTags> clock_capture_tags_;
};

}} //namespace

<commit_msg>Fix reseting bug<commit_after>#pragma once
#include "TimingTags.hpp"
#include "timing_graph_fwd.hpp"
#include "tatum_linear_map.hpp"

namespace tatum { namespace detail {

/** \class CommonAnalysisOps
 *
 * The operations for CommonAnalysisVisitor to perform setup analysis.
 * The setup analysis operations define that maximum edge delays are used, and that the
 * maixmum arrival time (and minimum required times) are propagated through the timing graph.
 *
 * \see HoldAnalysisOps
 * \see CommonAnalysisVisitor
 */
class CommonAnalysisOps {
    public:
        CommonAnalysisOps(size_t num_tags)
            : data_tags_(num_tags, NUM_DATA_TAGS_RESERVE)
            , clock_launch_tags_(num_tags, NUM_CLOCK_TAGS_RESERVE)
            , clock_capture_tags_(num_tags, NUM_CLOCK_TAGS_RESERVE) {}

        TimingTags& get_data_tags(const NodeId node_id) { return data_tags_[node_id]; }
        TimingTags& get_launch_clock_tags(const NodeId node_id) { return clock_launch_tags_[node_id]; }
        TimingTags& get_capture_clock_tags(const NodeId node_id) { return clock_capture_tags_[node_id]; }
        const TimingTags& get_data_tags(const NodeId node_id) const { return data_tags_[node_id]; }
        const TimingTags& get_launch_clock_tags(const NodeId node_id) const { return clock_launch_tags_[node_id]; }
        const TimingTags& get_capture_clock_tags(const NodeId node_id) const { return clock_capture_tags_[node_id]; }

        void reset() {
            data_tags_ = tatum::util::linear_map<NodeId,TimingTags>(data_tags_.size(), NUM_DATA_TAGS_RESERVE);
            clock_launch_tags_ = tatum::util::linear_map<NodeId,TimingTags>(clock_launch_tags_.size(), NUM_CLOCK_TAGS_RESERVE);
            clock_capture_tags_ = tatum::util::linear_map<NodeId,TimingTags>(clock_capture_tags_.size(), NUM_CLOCK_TAGS_RESERVE);
        }

    private:
        constexpr static size_t NUM_DATA_TAGS_RESERVE = 1;
        constexpr static size_t NUM_CLOCK_TAGS_RESERVE = 0;
        tatum::util::linear_map<NodeId,TimingTags> data_tags_;
        tatum::util::linear_map<NodeId,TimingTags> clock_launch_tags_;
        tatum::util::linear_map<NodeId,TimingTags> clock_capture_tags_;
};

}} //namespace

<|endoftext|>