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

/*
 * Modified by Cloudius Systems
 * Copyright 2015 Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "core/shared_ptr.hh"
#include "core/sstring.hh"
#include "types.hh"
#include "keys.hh"
#include "utils/managed_bytes.hh"
#include <memory>
#include <random>
#include <utility>

namespace sstables {

class key_view;

}

namespace dht {

//
// Origin uses a complex class hierarchy where Token is an abstract class,
// and various subclasses use different implementations (LongToken vs.
// BigIntegerToken vs. StringToken), plus other variants to to signify the
// the beginning of the token space etc.
//
// We'll fold all of that into the token class and push all of the variations
// into its users.

class decorated_key;
class token;
class ring_position;

class token {
public:
    enum class kind {
        before_all_keys,
        key,
        after_all_keys,
    };
    kind _kind;
    // _data can be interpreted as a big endian binary fraction
    // in the range [0.0, 1.0).
    //
    // So, [] == 0.0
    //     [0x00] == 0.0
    //     [0x80] == 0.5
    //     [0x00, 0x80] == 1/512
    //     [0xff, 0x80] == 1 - 1/512
    managed_bytes _data;
    token(kind k, managed_bytes d) : _kind(std::move(k)), _data(std::move(d)) {
    }

    bool is_minimum() const {
        return _kind == kind::before_all_keys;
    }

    bool is_maximum() const {
        return _kind == kind::after_all_keys;
    }

    void serialize(bytes::iterator& out) const;
    static token deserialize(bytes_view& in);
    size_t serialized_size() const;
};

token midpoint_unsigned(const token& t1, const token& t2);
token minimum_token();
token maximum_token();
bool operator==(const token& t1, const token& t2);
bool operator<(const token& t1, const token& t2);
int tri_compare(const token& t1, const token& t2);
inline bool operator!=(const token& t1, const token& t2) { return std::rel_ops::operator!=(t1, t2); }
inline bool operator>(const token& t1, const token& t2) { return std::rel_ops::operator>(t1, t2); }
inline bool operator<=(const token& t1, const token& t2) { return std::rel_ops::operator<=(t1, t2); }
inline bool operator>=(const token& t1, const token& t2) { return std::rel_ops::operator>=(t1, t2); }
std::ostream& operator<<(std::ostream& out, const token& t);

template <typename T>
inline auto get_random_number() {
    static thread_local std::random_device rd;
    static thread_local std::default_random_engine re(rd());
    static thread_local std::uniform_int_distribution<T> dist{};
    return dist(re);
}

// Wraps partition_key with its corresponding token.
//
// Total ordering defined by comparators is compatible with Origin's ordering.
class decorated_key {
public:
    dht::token _token;
    partition_key _key;

    struct less_comparator {
        schema_ptr s;
        less_comparator(schema_ptr s);
        bool operator()(const decorated_key& k1, const decorated_key& k2) const;
        bool operator()(const decorated_key& k1, const ring_position& k2) const;
        bool operator()(const ring_position& k1, const decorated_key& k2) const;
    };

    bool equal(const schema& s, const decorated_key& other) const;

    bool less_compare(const schema& s, const decorated_key& other) const;
    bool less_compare(const schema& s, const ring_position& other) const;

    // Trichotomic comparators defining total ordering on the union of
    // decorated_key and ring_position objects.
    int tri_compare(const schema& s, const decorated_key& other) const;
    int tri_compare(const schema& s, const ring_position& other) const;

    const dht::token& token() const {
        return _token;
    }

    const partition_key& key() const {
        return _key;
    }
};

using decorated_key_opt = std::experimental::optional<decorated_key>;

class i_partitioner {
public:
    virtual ~i_partitioner() {}

    /**
     * Transform key to object representation of the on-disk format.
     *
     * @param key the raw, client-facing key
     * @return decorated version of key
     */
    decorated_key decorate_key(const schema& s, const partition_key& key) {
        return { get_token(s, key), key };
    }

    /**
     * Transform key to object representation of the on-disk format.
     *
     * @param key the raw, client-facing key
     * @return decorated version of key
     */
    decorated_key decorate_key(const schema& s, partition_key&& key) {
        auto token = get_token(s, key);
        return { std::move(token), std::move(key) };
    }

    /**
     * Calculate a token representing the approximate "middle" of the given
     * range.
     *
     * @return The approximate midpoint between left and right.
     */
    virtual token midpoint(const token& left, const token& right) const = 0;

    /**
     * @return A token smaller than all others in the range that is being partitioned.
     * Not legal to assign to a node or key.  (But legal to use in range scans.)
     */
    token get_minimum_token() {
        return dht::minimum_token();
    }

    /**
     * @return a token that can be used to route a given key
     * (This is NOT a method to create a token from its string representation;
     * for that, use tokenFactory.fromString.)
     */
    virtual token get_token(const schema& s, partition_key_view key) = 0;
    virtual token get_token(const sstables::key_view& key) = 0;

    /**
     * @return a partitioner-specific string representation of this token
     */
    virtual sstring to_sstring(const dht::token& t) const = 0;

    /**
     * @return a token from its partitioner-specific string representation
     */
    virtual dht::token from_sstring(const sstring& t) const = 0;

    /**
     * @return a randomly generated token
     */
    virtual token get_random_token() = 0;

    // FIXME: token.tokenFactory
    //virtual token.tokenFactory gettokenFactory() = 0;

    /**
     * @return True if the implementing class preserves key order in the tokens
     * it generates.
     */
    virtual bool preserves_order() = 0;

    /**
     * Calculate the deltas between tokens in the ring in order to compare
     *  relative sizes.
     *
     * @param sortedtokens a sorted List of tokens
     * @return the mapping from 'token' to 'percentage of the ring owned by that token'.
     */
    virtual std::map<token, float> describe_ownership(const std::vector<token>& sorted_tokens) = 0;

    virtual data_type get_token_validator() = 0;

    /**
     * @return name of partitioner.
     */
    virtual const sstring name() = 0;

    /**
     * Calculates the shard that handles a particular token.
     */
    virtual unsigned shard_of(const token& t) const = 0;

    /**
     * @return bytes that represent the token as required by get_token_validator().
     */
    virtual bytes token_to_bytes(const token& t) const {
        return bytes(t._data.begin(), t._data.end());
    }
protected:
    /**
     * @return < 0 if if t1's _data array is less, t2's. 0 if they are equal, and > 0 otherwise. _kind comparison should be done separately.
     */
    virtual int tri_compare(const token& t1, const token& t2);
    /**
     * @return true if t1's _data array is equal t2's. _kind comparison should be done separately.
     */
    bool is_equal(const token& t1, const token& t2) {
        return tri_compare(t1, t2) == 0;
    }
    /**
     * @return true if t1's _data array is less then t2's. _kind comparison should be done separately.
     */
    bool is_less(const token& t1, const token& t2) {
        return tri_compare(t1, t2) < 0;
    }

    friend bool operator==(const token& t1, const token& t2);
    friend bool operator<(const token& t1, const token& t2);
    friend int tri_compare(const token& t1, const token& t2);
};

//
// Represents position in the ring of partitions, where partitions are ordered
// according to decorated_key ordering (first by token, then by key value).
// Intended to be used for defining partition ranges.
//
// The 'key' part is optional. When it's absent, this object represents a position
// which is either before or after all keys sharing given token. That's determined
// by relation_to_keys().
//
// For example for the following data:
//
//   tokens: |    t1   | t2 |
//           +----+----+----+
//   keys:   | k1 | k2 | k3 |
//
// The ordering is:
//
//   ring_position(t1, token_bound::start) < ring_position(k1)
//   ring_position(k1)                     < ring_position(k2)
//   ring_position(k1)                     == decorated_key(k1)
//   ring_position(k2)                     == decorated_key(k2)
//   ring_position(k2)                     < ring_position(t1, token_bound::end)
//   ring_position(k2)                     < ring_position(k3)
//   ring_position(t1, token_bound::end)   < ring_position(t2, token_bound::start)
//
// Maps to org.apache.cassandra.db.RowPosition and its derivatives in Origin.
//
class ring_position {
public:
    enum class token_bound : int8_t { start = -1, end = 1 };
private:
    dht::token _token;
    token_bound _token_bound; // valid when !_key
    std::experimental::optional<partition_key> _key;
public:
    static ring_position starting_at(dht::token token) {
        return { std::move(token), token_bound::start };
    }

    static ring_position ending_at(dht::token token) {
        return { std::move(token), token_bound::end };
    }

    ring_position(dht::token token, token_bound bound)
        : _token(std::move(token))
        , _token_bound(bound)
    { }

    ring_position(dht::token token, partition_key key)
        : _token(std::move(token))
        , _key(std::experimental::make_optional(std::move(key)))
    { }

    ring_position(const dht::decorated_key& dk)
        : _token(dk._token)
        , _key(std::experimental::make_optional(dk._key))
    { }

    const dht::token& token() const {
        return _token;
    }

    // Valid when !has_key()
    token_bound bound() const {
        return _token_bound;
    }

    // Returns -1 if smaller than keys with the same token, +1 if greater.
    // Valid when !has_key().
    int relation_to_keys() const {
        return static_cast<int>(_token_bound);
    }

    const std::experimental::optional<partition_key>& key() const {
        return _key;
    }

    bool has_key() const {
        return bool(_key);
    }

    // Call only when has_key()
    dht::decorated_key as_decorated_key() const {
        return { _token, *_key };
    }

    bool equal(const schema&, const ring_position&) const;

    // Trichotomic comparator defining a total ordering on ring_position objects
    int tri_compare(const schema&, const ring_position&) const;

    // "less" comparator corresponding to tri_compare()
    bool less_compare(const schema&, const ring_position&) const;

    size_t serialized_size() const;
    void serialize(bytes::iterator& out) const;
    static ring_position deserialize(bytes_view& in);

    friend std::ostream& operator<<(std::ostream&, const ring_position&);
};

struct ring_position_comparator {
    const schema& s;
    ring_position_comparator(const schema& s_) : s(s_) {}
    int operator()(const ring_position& lh, const ring_position& rh) const;
};

struct token_comparator {
    // Return values are those of a trichotomic comparison.
    int operator()(const token& t1, const token& t2) const;
};

std::ostream& operator<<(std::ostream& out, const token& t);

std::ostream& operator<<(std::ostream& out, const decorated_key& t);

void set_global_partitioner(const sstring& class_name);
i_partitioner& global_partitioner();

unsigned shard_of(const token&);

} // dht

namespace std {
template<>
struct hash<dht::token> {
    size_t operator()(const dht::token& t) const {
        return (t._kind == dht::token::kind::key) ? std::hash<decltype(t._data)>()(t._data) : 0;
    }
};
}
<commit_msg>Introduce ring_position_less_comparator<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Modified by Cloudius Systems
 * Copyright 2015 Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "core/shared_ptr.hh"
#include "core/sstring.hh"
#include "types.hh"
#include "keys.hh"
#include "utils/managed_bytes.hh"
#include <memory>
#include <random>
#include <utility>

namespace sstables {

class key_view;

}

namespace dht {

//
// Origin uses a complex class hierarchy where Token is an abstract class,
// and various subclasses use different implementations (LongToken vs.
// BigIntegerToken vs. StringToken), plus other variants to to signify the
// the beginning of the token space etc.
//
// We'll fold all of that into the token class and push all of the variations
// into its users.

class decorated_key;
class token;
class ring_position;

class token {
public:
    enum class kind {
        before_all_keys,
        key,
        after_all_keys,
    };
    kind _kind;
    // _data can be interpreted as a big endian binary fraction
    // in the range [0.0, 1.0).
    //
    // So, [] == 0.0
    //     [0x00] == 0.0
    //     [0x80] == 0.5
    //     [0x00, 0x80] == 1/512
    //     [0xff, 0x80] == 1 - 1/512
    managed_bytes _data;
    token(kind k, managed_bytes d) : _kind(std::move(k)), _data(std::move(d)) {
    }

    bool is_minimum() const {
        return _kind == kind::before_all_keys;
    }

    bool is_maximum() const {
        return _kind == kind::after_all_keys;
    }

    void serialize(bytes::iterator& out) const;
    static token deserialize(bytes_view& in);
    size_t serialized_size() const;
};

token midpoint_unsigned(const token& t1, const token& t2);
token minimum_token();
token maximum_token();
bool operator==(const token& t1, const token& t2);
bool operator<(const token& t1, const token& t2);
int tri_compare(const token& t1, const token& t2);
inline bool operator!=(const token& t1, const token& t2) { return std::rel_ops::operator!=(t1, t2); }
inline bool operator>(const token& t1, const token& t2) { return std::rel_ops::operator>(t1, t2); }
inline bool operator<=(const token& t1, const token& t2) { return std::rel_ops::operator<=(t1, t2); }
inline bool operator>=(const token& t1, const token& t2) { return std::rel_ops::operator>=(t1, t2); }
std::ostream& operator<<(std::ostream& out, const token& t);

template <typename T>
inline auto get_random_number() {
    static thread_local std::random_device rd;
    static thread_local std::default_random_engine re(rd());
    static thread_local std::uniform_int_distribution<T> dist{};
    return dist(re);
}

// Wraps partition_key with its corresponding token.
//
// Total ordering defined by comparators is compatible with Origin's ordering.
class decorated_key {
public:
    dht::token _token;
    partition_key _key;

    struct less_comparator {
        schema_ptr s;
        less_comparator(schema_ptr s);
        bool operator()(const decorated_key& k1, const decorated_key& k2) const;
        bool operator()(const decorated_key& k1, const ring_position& k2) const;
        bool operator()(const ring_position& k1, const decorated_key& k2) const;
    };

    bool equal(const schema& s, const decorated_key& other) const;

    bool less_compare(const schema& s, const decorated_key& other) const;
    bool less_compare(const schema& s, const ring_position& other) const;

    // Trichotomic comparators defining total ordering on the union of
    // decorated_key and ring_position objects.
    int tri_compare(const schema& s, const decorated_key& other) const;
    int tri_compare(const schema& s, const ring_position& other) const;

    const dht::token& token() const {
        return _token;
    }

    const partition_key& key() const {
        return _key;
    }
};

using decorated_key_opt = std::experimental::optional<decorated_key>;

class i_partitioner {
public:
    virtual ~i_partitioner() {}

    /**
     * Transform key to object representation of the on-disk format.
     *
     * @param key the raw, client-facing key
     * @return decorated version of key
     */
    decorated_key decorate_key(const schema& s, const partition_key& key) {
        return { get_token(s, key), key };
    }

    /**
     * Transform key to object representation of the on-disk format.
     *
     * @param key the raw, client-facing key
     * @return decorated version of key
     */
    decorated_key decorate_key(const schema& s, partition_key&& key) {
        auto token = get_token(s, key);
        return { std::move(token), std::move(key) };
    }

    /**
     * Calculate a token representing the approximate "middle" of the given
     * range.
     *
     * @return The approximate midpoint between left and right.
     */
    virtual token midpoint(const token& left, const token& right) const = 0;

    /**
     * @return A token smaller than all others in the range that is being partitioned.
     * Not legal to assign to a node or key.  (But legal to use in range scans.)
     */
    token get_minimum_token() {
        return dht::minimum_token();
    }

    /**
     * @return a token that can be used to route a given key
     * (This is NOT a method to create a token from its string representation;
     * for that, use tokenFactory.fromString.)
     */
    virtual token get_token(const schema& s, partition_key_view key) = 0;
    virtual token get_token(const sstables::key_view& key) = 0;

    /**
     * @return a partitioner-specific string representation of this token
     */
    virtual sstring to_sstring(const dht::token& t) const = 0;

    /**
     * @return a token from its partitioner-specific string representation
     */
    virtual dht::token from_sstring(const sstring& t) const = 0;

    /**
     * @return a randomly generated token
     */
    virtual token get_random_token() = 0;

    // FIXME: token.tokenFactory
    //virtual token.tokenFactory gettokenFactory() = 0;

    /**
     * @return True if the implementing class preserves key order in the tokens
     * it generates.
     */
    virtual bool preserves_order() = 0;

    /**
     * Calculate the deltas between tokens in the ring in order to compare
     *  relative sizes.
     *
     * @param sortedtokens a sorted List of tokens
     * @return the mapping from 'token' to 'percentage of the ring owned by that token'.
     */
    virtual std::map<token, float> describe_ownership(const std::vector<token>& sorted_tokens) = 0;

    virtual data_type get_token_validator() = 0;

    /**
     * @return name of partitioner.
     */
    virtual const sstring name() = 0;

    /**
     * Calculates the shard that handles a particular token.
     */
    virtual unsigned shard_of(const token& t) const = 0;

    /**
     * @return bytes that represent the token as required by get_token_validator().
     */
    virtual bytes token_to_bytes(const token& t) const {
        return bytes(t._data.begin(), t._data.end());
    }
protected:
    /**
     * @return < 0 if if t1's _data array is less, t2's. 0 if they are equal, and > 0 otherwise. _kind comparison should be done separately.
     */
    virtual int tri_compare(const token& t1, const token& t2);
    /**
     * @return true if t1's _data array is equal t2's. _kind comparison should be done separately.
     */
    bool is_equal(const token& t1, const token& t2) {
        return tri_compare(t1, t2) == 0;
    }
    /**
     * @return true if t1's _data array is less then t2's. _kind comparison should be done separately.
     */
    bool is_less(const token& t1, const token& t2) {
        return tri_compare(t1, t2) < 0;
    }

    friend bool operator==(const token& t1, const token& t2);
    friend bool operator<(const token& t1, const token& t2);
    friend int tri_compare(const token& t1, const token& t2);
};

//
// Represents position in the ring of partitions, where partitions are ordered
// according to decorated_key ordering (first by token, then by key value).
// Intended to be used for defining partition ranges.
//
// The 'key' part is optional. When it's absent, this object represents a position
// which is either before or after all keys sharing given token. That's determined
// by relation_to_keys().
//
// For example for the following data:
//
//   tokens: |    t1   | t2 |
//           +----+----+----+
//   keys:   | k1 | k2 | k3 |
//
// The ordering is:
//
//   ring_position(t1, token_bound::start) < ring_position(k1)
//   ring_position(k1)                     < ring_position(k2)
//   ring_position(k1)                     == decorated_key(k1)
//   ring_position(k2)                     == decorated_key(k2)
//   ring_position(k2)                     < ring_position(t1, token_bound::end)
//   ring_position(k2)                     < ring_position(k3)
//   ring_position(t1, token_bound::end)   < ring_position(t2, token_bound::start)
//
// Maps to org.apache.cassandra.db.RowPosition and its derivatives in Origin.
//
class ring_position {
public:
    enum class token_bound : int8_t { start = -1, end = 1 };
private:
    dht::token _token;
    token_bound _token_bound; // valid when !_key
    std::experimental::optional<partition_key> _key;
public:
    static ring_position starting_at(dht::token token) {
        return { std::move(token), token_bound::start };
    }

    static ring_position ending_at(dht::token token) {
        return { std::move(token), token_bound::end };
    }

    ring_position(dht::token token, token_bound bound)
        : _token(std::move(token))
        , _token_bound(bound)
    { }

    ring_position(dht::token token, partition_key key)
        : _token(std::move(token))
        , _key(std::experimental::make_optional(std::move(key)))
    { }

    ring_position(const dht::decorated_key& dk)
        : _token(dk._token)
        , _key(std::experimental::make_optional(dk._key))
    { }

    const dht::token& token() const {
        return _token;
    }

    // Valid when !has_key()
    token_bound bound() const {
        return _token_bound;
    }

    // Returns -1 if smaller than keys with the same token, +1 if greater.
    // Valid when !has_key().
    int relation_to_keys() const {
        return static_cast<int>(_token_bound);
    }

    const std::experimental::optional<partition_key>& key() const {
        return _key;
    }

    bool has_key() const {
        return bool(_key);
    }

    // Call only when has_key()
    dht::decorated_key as_decorated_key() const {
        return { _token, *_key };
    }

    bool equal(const schema&, const ring_position&) const;

    // Trichotomic comparator defining a total ordering on ring_position objects
    int tri_compare(const schema&, const ring_position&) const;

    // "less" comparator corresponding to tri_compare()
    bool less_compare(const schema&, const ring_position&) const;

    size_t serialized_size() const;
    void serialize(bytes::iterator& out) const;
    static ring_position deserialize(bytes_view& in);

    friend std::ostream& operator<<(std::ostream&, const ring_position&);
};

// Trichotomic comparator for ring_position
struct ring_position_comparator {
    const schema& s;
    ring_position_comparator(const schema& s_) : s(s_) {}
    int operator()(const ring_position& lh, const ring_position& rh) const;
};

// "less" comparator for ring_position
struct ring_position_less_comparator {
    const schema& s;
    ring_position_less_comparator(const schema& s_) : s(s_) {}
    bool operator()(const ring_position& lh, const ring_position& rh) const {
        return lh.less_compare(s, rh);
    }
};

struct token_comparator {
    // Return values are those of a trichotomic comparison.
    int operator()(const token& t1, const token& t2) const;
};

std::ostream& operator<<(std::ostream& out, const token& t);

std::ostream& operator<<(std::ostream& out, const decorated_key& t);

void set_global_partitioner(const sstring& class_name);
i_partitioner& global_partitioner();

unsigned shard_of(const token&);

} // dht

namespace std {
template<>
struct hash<dht::token> {
    size_t operator()(const dht::token& t) const {
        return (t._kind == dht::token::kind::key) ? std::hash<decltype(t._data)>()(t._data) : 0;
    }
};
}
<|endoftext|>


<commit_before>#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
#include <math.h>       /* exp */

// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;

// Below is a simple example of exporting a C++ function to R. You can
// source this function into an R session using the Rcpp::sourceCpp
// function (or via the Source button on the editor toolbar)

// For more on using Rcpp click the Help button on the editor toolbar

// [[Rcpp::export]]
int nei4(NumericMatrix x, int a, int b, int col){
  int n = x.nrow(), m = x.ncol();
  int nei = 0;
  a = a-1;
  b = b-1;

  if(x(a-1,b) == col){nei++;}
  if(x(a,b-1) == col){nei++;}
  if(a != n){
    if(x(a+1,b) == col){nei++;}
  }
  if(b != m){
    if(x(a,b+1) == col){nei++;}
  }
  return nei;}

// [[Rcpp::export]]
NumericMatrix isingSampler(NumericMatrix x, int max_iter, double beta){
  int n = x.nrow(), m = x.ncol();
  int i;
  int k;
  int l;

  NumericVector rows;
  rows = Rcpp::seq(1,n);
  NumericVector cols;
  cols = Rcpp::seq(1,m);

  NumericVector pos;
  pos = Rcpp::seq(0,1);

  NumericVector permut_rows;
  NumericVector permut_cols;

  NumericVector prob(2, 0.5);

  int n0;
  int n1;

  int pos1;
  int pos2;

  double res;

  for(i = 0; i < max_iter; i++){
    permut_rows = RcppArmadillo::sample(rows,n,0);
    permut_cols = RcppArmadillo::sample(cols,m,0);

    for(k = 1; k <= n; k++){
      for(l = 1; l <= m; l++){
        n0 = nei4(x, permut_rows[k-1], permut_cols[l-1], 0);
        n1 = nei4(x, permut_rows[k-1], permut_cols[l-1], 1);
        prob[0] = exp(beta*n0);
        prob[1] = exp(beta*n1);

        pos1 = permut_rows[k];
        pos2 = permut_cols[l];

        res = RcppArmadillo::sample(pos, 1, 0, prob)[0];

        x(pos1, pos2) = res;
      }
    }
  }

  return x;

}<commit_msg>Fixed a bug<commit_after>#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>
#include <math.h>       /* exp */

// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;

// Below is a simple example of exporting a C++ function to R. You can
// source this function into an R session using the Rcpp::sourceCpp
// function (or via the Source button on the editor toolbar)

// For more on using Rcpp click the Help button on the editor toolbar

// [[Rcpp::export]]
int nei4(NumericMatrix x, int a, int b, int col){
  int n = x.nrow(), m = x.ncol();
  int nei = 0;
  a = a-1;
  b = b-1;
  if(a != 0){
  if(x(a-1,b) == col){nei++;}}
  if(b != 0){
  if(x(a,b-1) == col){nei++;}}
  if(a != (n-1)){
    if(x(a+1,b) == col){nei++;}
  }
  if(b != (m-1)){
    if(x(a,b+1) == col){nei++;}
  }
  return nei;}

// [[Rcpp::export]]
NumericMatrix isingSampler(NumericMatrix x, int max_iter, double beta){
  int n = x.nrow(), m = x.ncol();
  int i;
  int k;
  int l;

  NumericVector rows;
  rows = Rcpp::seq(1,n);
  NumericVector cols;
  cols = Rcpp::seq(1,m);

  NumericVector pos;
  pos = Rcpp::seq(0,1);

  NumericVector permut_rows;
  NumericVector permut_cols;

  NumericVector prob(2, 0.5);

  int n0;
  int n1;

  int pos1;
  int pos2;

  double res;

  for(i = 0; i < max_iter; i++){
    permut_rows = RcppArmadillo::sample(rows,n,0);
    permut_cols = RcppArmadillo::sample(cols,m,0);

    for(k = 1; k <= n; k++){
      for(l = 1; l <= m; l++){
        n0 = nei4(x, permut_rows[k-1], permut_cols[l-1], 0);
        n1 = nei4(x, permut_rows[k-1], permut_cols[l-1], 1);
        prob[0] = exp(beta*n0);
        prob[1] = exp(beta*n1);

        pos1 = permut_rows[k];
        pos2 = permut_cols[l];

        double suma = prob[0] + prob[1];
        prob[0] = prob[0]/suma;
        prob[1] = prob[1]/suma;

        res = RcppArmadillo::sample(pos, 1, 0, prob)[0];
        //res = Rcpp::Function(sample(pos,1,0,prob));
        Rcpp::Function(gc());

        x(pos1, pos2) = res;
      }
    }
  }

  return x;

}<|endoftext|>


<commit_before>#pragma once

#include <eosio/chain/types.hpp>
#include <eosio/chain/block.hpp>

namespace eosio { namespace trace_api_plugin {

   struct authorization_trace_v0 {
      chain::name account;
      chain::name permission;
   };

   struct action_trace_v0 {
      uint64_t                            global_sequence = {};
      chain::name                         receiver = {};
      chain::name                         account = {};
      chain::name                         action = {};
      std::vector<authorization_trace_v0> authorization = {};
      chain::bytes                        data = {};
   };

   struct transaction_trace_v0 {
      using status_type = chain::transaction_receipt_header::status_enum;

      chain::transaction_id_type    id = {};
      status_type                   status = {};
      std::vector<action_trace_v0>  actions = {};
   };

   struct block_trace_v0 {
      chain::block_id_type               id = {};
      uint64_t                           number = {};
      chain::block_id_type               previous_id = {};
      chain::block_timestamp_type        timestamp = chain::block_timestamp_type(0);
      chain::name                        producer = {};
      std::vector<transaction_trace_v0>  transactions = {};
   };

} }

FC_REFLECT(eosio::trace_api_plugin::authorization_trace_v0, (account)(permission))
FC_REFLECT(eosio::trace_api_plugin::action_trace_v0, (global_sequence)(receiver)(account)(action)(authorization)(data))
FC_REFLECT(eosio::trace_api_plugin::transaction_trace_v0, (id)(status)(actions))
FC_REFLECT(eosio::trace_api_plugin::block_trace_v0, (id)(number)(previous_id)(timestamp)(producer)(transactions))
<commit_msg>Add conversion from chain::transaction_trace<commit_after>#pragma once

#include <eosio/chain/trace.hpp>
#include <eosio/chain/types.hpp>
#include <eosio/chain/block.hpp>

namespace eosio { namespace trace_api_plugin {

   struct authorization_trace_v0 {
      chain::name account;
      chain::name permission;
   };

   struct action_trace_v0 {
      uint64_t                            global_sequence = {};
      chain::name                         receiver = {};
      chain::name                         account = {};
      chain::name                         action = {};
      std::vector<authorization_trace_v0> authorization = {};
      chain::bytes                        data = {};
   };

   struct transaction_trace_v0 {
      using status_type = chain::transaction_receipt_header::status_enum;

      chain::transaction_id_type    id = {};
      status_type                   status = {};
      std::vector<action_trace_v0>  actions = {};
   };

   struct block_trace_v0 {
      chain::block_id_type               id = {};
      uint64_t                           number = {};
      chain::block_id_type               previous_id = {};
      chain::block_timestamp_type        timestamp = chain::block_timestamp_type(0);
      chain::name                        producer = {};
      std::vector<transaction_trace_v0>  transactions = {};
   };

   action_trace_v0 to_action_trace_v0( const chain::action_trace& at ) {
      action_trace_v0 r;
      r.receiver = at.receiver;
      r.account = at.act.account;
      r.action = at.act.name;
      r.data = at.act.data;
      if( at.receipt ) {
         r.global_sequence = at.receipt->global_sequence;
      }
      r.authorization.reserve( at.act.authorization.size());
      for( const auto& auth : at.act.authorization ) {
         r.authorization.emplace_back( authorization_trace_v0{auth.actor, auth.permission} );
      }
      return r;
   }

   transaction_trace_v0 to_transaction_trace_v0( const chain::transaction_trace& t ) {
      transaction_trace_v0 r;
      r.id = t.id;
      if( t.receipt ) {
         r.status = t.receipt->status;
      } else {
         r.status = eosio::chain::transaction_receipt_header::status_enum::hard_fail; // not really, but better than other values
      }
      r.actions.reserve( t.action_traces.size());
      for( const auto& at : t.action_traces ) {
         r.actions.emplace_back( to_action_trace_v0( at ));
      }
      return r;
   }

} }

FC_REFLECT(eosio::trace_api_plugin::authorization_trace_v0, (account)(permission))
FC_REFLECT(eosio::trace_api_plugin::action_trace_v0, (global_sequence)(receiver)(account)(action)(authorization)(data))
FC_REFLECT(eosio::trace_api_plugin::transaction_trace_v0, (id)(status)(actions))
FC_REFLECT(eosio::trace_api_plugin::block_trace_v0, (id)(number)(previous_id)(timestamp)(producer)(transactions))
<|endoftext|>


<commit_before>// vimshell.cpp : Defines the entry point for the application.
//

#include "vimshell.h"
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
#include <shellapi.h>

bool cvtLPW2stdstring(std::string& s, const LPWSTR pw,
                      UINT codepage = CP_ACP)
{
    bool res = false;
    char* p = 0;
    int bsz;

    bsz = WideCharToMultiByte(codepage,
        0,
        pw,-1,
        0,0,
        0,0);
    if (bsz > 0) {
        p = new char[bsz];
        int rc = WideCharToMultiByte(codepage,
            0,
            pw,-1,
            p,bsz,
            0,0);
        if (rc != 0) {
            p[bsz-1] = 0;
            s = p;
            res = true;
        }
    }
    delete [] p;
    return res;
}

std::string FindAndReplace(std::string tInput, std::string tFind, std::string tReplace )
{
	size_t uPos = 0;
	size_t uFindLen = tFind.length();
	size_t uReplaceLen = tReplace.length();

	if( uFindLen == 0 )
	{
		return tInput;
	}

	while((uPos = tInput.find( tFind, uPos )) != std::string::npos)
	{
		tInput.replace( uPos, uFindLen, tReplace );
		uPos += uReplaceLen;
	}

	return tInput;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	int count;
	//MessageBox(0, lpCmdLine, 0, 0);
	LPWSTR* strings = CommandLineToArgvW(GetCommandLineW(), &count);
	std::string currentDir;

	cvtLPW2stdstring(currentDir, strings[0]);

	// Cut off the filename
	while((currentDir.length() > 0) &&
		(currentDir[currentDir.length()-1] != '/') &&
		(currentDir[currentDir.length()-1] != '\\'))
	{
		currentDir = currentDir.substr(0, currentDir.length()-1);
	}
	if(currentDir.length() > 0 && currentDir[0] == '"')
		currentDir = currentDir.substr(1);

	std::string filename = currentDir + std::string("shell.txt");

	std::ifstream fileIn(filename.c_str());
	if(!fileIn)
	{
		MessageBox(0, "Please create a file called shell.txt in the same folder you put this new vimrun.exe", 0,0);
		return 1;
	}

	std::string argumentshellcommand;
	std::string silentshellcommand;
	std::string interactiveshellcommand;

	std::getline(fileIn, argumentshellcommand);
	std::getline(fileIn, silentshellcommand);
	std::getline(fileIn, interactiveshellcommand);

	std::string args = lpCmdLine;

	while(args.length() > 0 && args[0] == ' ')
		args = args.substr(1);

	bool execSilently = false;

	if(args.length() > 3 &&
			args[0] == '-' &&
			args[1] == 's' &&
			args[2] == ' ')
	{
		args = args.substr(3);
		execSilently = true;
	}

	size_t spacepos = args.find_first_of(" ");
	args = args.substr(spacepos+1);
	spacepos = args.find_first_of(" ");
	args = args.substr(spacepos+1);

	std::string cmd;

	if(spacepos == std::string::npos)
		args = "";

	std::string argcmd = execSilently ? silentshellcommand : argumentshellcommand;

	if(args.length() == 0)
	{
		cmd = interactiveshellcommand;
	}
	else
	{
		std::string quotedPH = "#QQQQ#";
		if(argcmd.find(quotedPH) != std::string::npos)
		{
			args = FindAndReplace(args,"\"", "\\\"");
			args = FindAndReplace(args, "\\", "\\\\");
			cmd = FindAndReplace(argcmd, quotedPH, args);
		}
		else
		{
			cmd = argcmd + " " + args;
		}
	}
	//MessageBox(0,cmd.c_str(), 0,0);
	// I know, I know, baaaaad win16 function, unfortunately I could not get
	// CreateProcess working as I wanted it (actually showing me the window)
	// and also if I used CreateProcess, I would have to parse the program name
	// out of the shell.txt file to know where the parameters begint etc,
	// which is kinda difficult and not pleasant at all.
	WinExec(cmd.c_str(), SW_SHOW);
	return 0;
}
<commit_msg>Fixed some vague escaping stuff. Still far from perfect though.<commit_after>// vimshell.cpp : Defines the entry point for the application.
//

#include "vimshell.h"
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
#include <shellapi.h>

bool cvtLPW2stdstring(std::string& s, const LPWSTR pw,
                      UINT codepage = CP_ACP)
{
    bool res = false;
    char* p = 0;
    int bsz;

    bsz = WideCharToMultiByte(codepage,
        0,
        pw,-1,
        0,0,
        0,0);
    if (bsz > 0) {
        p = new char[bsz];
        int rc = WideCharToMultiByte(codepage,
            0,
            pw,-1,
            p,bsz,
            0,0);
        if (rc != 0) {
            p[bsz-1] = 0;
            s = p;
            res = true;
        }
    }
    delete [] p;
    return res;
}

std::string FindAndReplace(std::string tInput, std::string tFind, std::string tReplace )
{
	size_t uPos = 0;
	size_t uFindLen = tFind.length();
	size_t uReplaceLen = tReplace.length();

	if( uFindLen == 0 )
	{
		return tInput;
	}

	while((uPos = tInput.find( tFind, uPos )) != std::string::npos)
	{
		tInput.replace( uPos, uFindLen, tReplace );
		uPos += uReplaceLen;
	}

	return tInput;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	int count;
	//MessageBox(0, lpCmdLine, 0, 0);
	LPWSTR* strings = CommandLineToArgvW(GetCommandLineW(), &count);
	std::string currentDir;

	cvtLPW2stdstring(currentDir, strings[0]);

	// Cut off the filename
	while((currentDir.length() > 0) &&
		(currentDir[currentDir.length()-1] != '/') &&
		(currentDir[currentDir.length()-1] != '\\'))
	{
		currentDir = currentDir.substr(0, currentDir.length()-1);
	}
	if(currentDir.length() > 0 && currentDir[0] == '"')
		currentDir = currentDir.substr(1);

	std::string filename = currentDir + std::string("shell.txt");

	std::ifstream fileIn(filename.c_str());
	if(!fileIn)
	{
		MessageBox(0, "Please create a file called shell.txt in the same folder you put this new vimrun.exe", 0,0);
		return 1;
	}

	std::string argumentshellcommand;
	std::string silentshellcommand;
	std::string interactiveshellcommand;

	std::getline(fileIn, argumentshellcommand);
	std::getline(fileIn, silentshellcommand);
	std::getline(fileIn, interactiveshellcommand);

	std::string args = lpCmdLine;

	while(args.length() > 0 && args[0] == ' ')
		args = args.substr(1);

	bool execSilently = false;

	if(args.length() > 3 &&
			args[0] == '-' &&
			args[1] == 's' &&
			args[2] == ' ')
	{
		args = args.substr(3);
		execSilently = true;
	}

	size_t spacepos = args.find_first_of(" ");
	args = args.substr(spacepos+1);
	spacepos = args.find_first_of(" ");
	args = args.substr(spacepos+1);

	std::string cmd;

	if(spacepos == std::string::npos)
		args = "";

	std::string argcmd = execSilently ? silentshellcommand : argumentshellcommand;

	if(args.length() == 0)
	{
		cmd = interactiveshellcommand;
	}
	else
	{
		std::string quotedPH = "#QQQQ#";
		if(argcmd.find(quotedPH) != std::string::npos)
		{
			bool indoubles = false;
			bool insingles = false;
			for(size_t i = 0; i < args.length(); i++)
			{
				if(args[i] == '"')
					indoubles = !indoubles;
				if(args[i] == '\'')
					insingles = !insingles;

				if(!indoubles && !insingles && args[i] == '\\')
				{
					args.insert(i, "\\");
					i++;
					continue;
				}

				if(!indoubles && args[i] == '\'')
				{
					args.insert(i, "\\");
					i++;
					continue;
				}

			}
			//args = FindAndReplace(args,"'", "\\'");

		//	args = FindAndReplace(args, "\\", "\\\\");
			cmd = FindAndReplace(argcmd, quotedPH, args);
		}
		else
		{
			cmd = argcmd + " " + args;
		}
	}
	/*MessageBox(0,cmd.c_str(), 0,0);
	std::ofstream f("C:/output.txt");
	f << cmd.c_str();
	f.close();*/
	// I know, I know, baaaaad win16 function, unfortunately I could not get
	// CreateProcess working as I wanted it (actually showing me the window)
	// and also if I used CreateProcess, I would have to parse the program name
	// out of the shell.txt file to know where the parameters begint etc,
	// which is kinda difficult and not pleasant at all.
	WinExec(cmd.c_str(), SW_SHOW);
	return 0;
}
<|endoftext|>


<commit_before>/**
 * Property C Wrapper is a way so the C Modules can
 * get access to the property manager
 *
 * there will be 3 kinds of propertys
 * PropertyBool
 * PropertyString
 * PropertyNumber
 *
 * Copyright 2013 Thinstuff Technologies GmbH
 * Copyright 2013 DI (FH) Martin Haimberger <martin.haimberger@thinstuff.at>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "PropertyCWrapper.h"

#include <appcontext/ApplicationContext.h>
#include <string>

bool getPropertyBool(long sessionID, char* path, bool* value)
{
	return APP_CONTEXT.getPropertyManager()->getPropertyBool(sessionID,std::string(path), *value);
}

bool getPropertyNumber(long sessionID, char* path, long* value)
{
	return APP_CONTEXT.getPropertyManager()->getPropertyNumber(sessionID,std::string(path), *value);

}

bool getPropertyString(long sessionID, char* path, char* value, unsigned int valueLength)
{
	std::string stdvalue;
	bool retValue = APP_CONTEXT.getPropertyManager()->getPropertyString(sessionID, std::string(path), stdvalue);

	if (stdvalue.size() > valueLength)
	{
		return false;
	}
	else
	{
		memcpy(value,stdvalue.c_str(), stdvalue.size());
		return true;
	}
}

int setPropertyBool(PROPERTY_LEVEL level, long sessionID, char* path, bool value)
{

}

int setPropertyNumber(PROPERTY_LEVEL level, long sessionID, char* path, long value)
{

}

int setPropertyString(PROPERTY_LEVEL level, long sessionID, char* path, char* value)
{

}
<commit_msg>return false for string properties if not found<commit_after>/**
 * Property C Wrapper is a way so the C Modules can
 * get access to the property manager
 *
 * there will be 3 kinds of propertys
 * PropertyBool
 * PropertyString
 * PropertyNumber
 *
 * Copyright 2013 Thinstuff Technologies GmbH
 * Copyright 2013 DI (FH) Martin Haimberger <martin.haimberger@thinstuff.at>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "PropertyCWrapper.h"

#include <appcontext/ApplicationContext.h>
#include <string>

bool getPropertyBool(long sessionID, char* path, bool* value)
{
	return APP_CONTEXT.getPropertyManager()->getPropertyBool(sessionID,std::string(path), *value);
}

bool getPropertyNumber(long sessionID, char* path, long* value)
{
	return APP_CONTEXT.getPropertyManager()->getPropertyNumber(sessionID,std::string(path), *value);

}

bool getPropertyString(long sessionID, char* path, char* value, unsigned int valueLength)
{
	std::string stdvalue;
	bool retValue = APP_CONTEXT.getPropertyManager()->getPropertyString(sessionID, std::string(path), stdvalue);

	if (!retValue)
		return false;

	if (stdvalue.size() > valueLength)
	{
		return false;
	}
	else
	{
		memcpy(value,stdvalue.c_str(), stdvalue.size());
		return true;
	}
}

int setPropertyBool(PROPERTY_LEVEL level, long sessionID, char* path, bool value)
{

}

int setPropertyNumber(PROPERTY_LEVEL level, long sessionID, char* path, long value)
{

}

int setPropertyString(PROPERTY_LEVEL level, long sessionID, char* path, char* value)
{

}
<|endoftext|>


<commit_before>/*
The OpenTRV project licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the Licence is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the Licence for the
specific language governing permissions and limitations
under the Licence.

Author(s) / Copyright (s): Damon Hart-Davis 2016
*/

/*
 * Driver for PseudoSensorOccupancyTracker tests.
 */

#include <stdint.h>
#include <gtest/gtest.h>
#include <OTV0p2Base.h>
#include "OTV0P2BASE_SensorAmbientLightOccupancy.h"

// Basic operation (duration of occupancy from trigger), etc.
TEST(PseudoSensorOccupancyTracker,basics)
{
    // Set up default occupancy tracker.
    OTV0P2BASE::PseudoSensorOccupancyTracker o1;
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    o1.markAsOccupied();
    ASSERT_TRUE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());
    // Run for half the nominal time and ensure still marked as occupied.
    for(int i = 0; i < o1.OCCUPATION_TIMEOUT_M/2; ++i) { o1.read(); ASSERT_TRUE(o1.isLikelyOccupied()); }
    // Run again for about half the nominal time and ensure now not occupied.
    for(int i = 0; i < o1.OCCUPATION_TIMEOUT_M/2 + 1; ++i) { o1.read(); }
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());

    // Put in holiday mode; show marked very vacant.
    o1.setHolidayMode();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    // Show that markAsOccupied() brings status back to occupied.
    o1.markAsOccupied();
    ASSERT_TRUE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());

    // Put in holiday mode; show marked very vacant.
    o1.setHolidayMode();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    // Show that markAsPossiblyOccupied() brings status back to occupied.
    o1.markAsPossiblyOccupied();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());

    // Put in holiday mode; show marked very vacant.
    o1.setHolidayMode();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    // Show that markAsJustPossiblyOccupied() DOES NOT status back to occupied.
    o1.markAsJustPossiblyOccupied();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());

    // Show that markAsJustPossiblyOccupied() does indicate occupancy when not very torpid.
    o1.reset();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    o1.markAsJustPossiblyOccupied();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());
}
<commit_msg>improved comment<commit_after>/*
The OpenTRV project licenses this file to you
under the Apache Licence, Version 2.0 (the "Licence");
you may not use this file except in compliance
with the Licence. You may obtain a copy of the Licence at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the Licence is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the Licence for the
specific language governing permissions and limitations
under the Licence.

Author(s) / Copyright (s): Damon Hart-Davis 2016
*/

/*
 * Driver for PseudoSensorOccupancyTracker tests.
 */

#include <stdint.h>
#include <gtest/gtest.h>
#include <OTV0p2Base.h>
#include "OTV0P2BASE_SensorAmbientLightOccupancy.h"

// Basic operation (duration of occupancy from trigger), etc.
TEST(PseudoSensorOccupancyTracker,basics)
{
    // Set up default occupancy tracker.
    OTV0P2BASE::PseudoSensorOccupancyTracker o1;
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    o1.markAsOccupied();
    ASSERT_TRUE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());
    // Run for half the nominal time and ensure still marked as occupied.
    for(int i = 0; i < o1.OCCUPATION_TIMEOUT_M/2; ++i) { o1.read(); ASSERT_TRUE(o1.isLikelyOccupied()); }
    // Run again for about half the nominal time and ensure now not occupied.
    for(int i = 0; i < o1.OCCUPATION_TIMEOUT_M/2 + 1; ++i) { o1.read(); }
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());

    // Put in holiday mode; show marked very vacant.
    o1.setHolidayMode();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    // Show that markAsOccupied() brings status back to occupied.
    o1.markAsOccupied();
    ASSERT_TRUE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());

    // Put in holiday mode; show marked very vacant.
    o1.setHolidayMode();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    // Show that markAsPossiblyOccupied() brings status back to occupied.
    o1.markAsPossiblyOccupied();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());

    // Put in holiday mode; show marked very vacant.
    o1.setHolidayMode();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    // Show that markAsJustPossiblyOccupied() DOES NOT status back to occupied.
    o1.markAsJustPossiblyOccupied();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());

    // Show that markAsJustPossiblyOccupied() does indicate occupancy when system not very torpid.
    o1.reset();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_FALSE(o1.isLikelyOccupied());
    ASSERT_TRUE(o1.isLikelyUnoccupied());
    o1.markAsJustPossiblyOccupied();
    ASSERT_FALSE(o1.isLikelyRecentlyOccupied());
    ASSERT_TRUE(o1.isLikelyOccupied());
    ASSERT_FALSE(o1.isLikelyUnoccupied());
}
<|endoftext|>


<commit_before>/***********************************************************************
    created:    Aug 22 2014
    author:     Luca Ebach <lucaebach@gmail.com>
                (based on original code by Tomas Lindquist Olsen)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "ScrollablePane.h"

#include "CEGUI/System.h"
#include "CEGUI/SchemeManager.h"
#include "CEGUI/WindowManager.h"
#include "CEGUI/FontManager.h"
#include "CEGUI/ImageManager.h"
#include "CEGUI/InputAggregator.h"
#include "CEGUI/InputEventReceiver.h"
#include "CEGUI/Font.h"
#include "CEGUI/Window.h"
#include "CEGUI/CoordConverter.h"
#include "CEGUI/GUIContext.h"

#include "CEGUI/widgets/ScrollablePane.h"
#include "CEGUI/widgets/ScrolledContainer.h"

#include "SampleBase.h"

ScrollablePaneSample::ScrollablePaneSample()
{
    Sample::d_name = "ScrollablePaneDeme";
    Sample::d_credits = "Tomas Lindquist Olsen";
    Sample::d_description =
        "The ScrollbarPane sample uses the WindowsLook, which gives it a look similar "
        "to old Windows applications. The background consists of a ScrollablePane to "
        "which windows can be added, using the menu bar. The items on the pane can be "
        "moved freely and the pane can be scrolled with the scrollbars.";
    Sample::d_summary =
        "The background window is of target type \"CEGUI/ScrollablePane\". "
        "The WindowsLook skin is used for all the windows.";
}

bool ScrollablePaneSample::initialise(CEGUI::GUIContext* guiContext)
{
    using namespace CEGUI;

    d_guiContext = guiContext;
    d_usedFiles = CEGUI::String(__FILE__);

    d_inputAggregator = new SampleInputAggregator(d_guiContext);

    // this sample will use WindowsLook
    SchemeManager::getSingleton().createFromFile("WindowsLook.scheme");

    // load the default font
    d_font = &FontManager::getSingleton().createFromFile("DejaVuSans-12-NoScale.font");
    d_guiContext->setDefaultFont(d_font);

    // set the cursor
    d_system = System::getSingletonPtr();
    d_guiContext->getCursor().setDefaultImage("WindowsLook/MouseArrow");

    // set the default tooltip type
    d_guiContext->setDefaultTooltipType("WindowsLook/Tooltip");

    // We need the window manager to set up the test interface :)
    d_wm = WindowManager::getSingletonPtr();

    // create a root window
    // this will be a static, to give a nice app'ish background
    d_root = d_wm->createWindow("WindowsLook/Static");
    d_root->setProperty("FrameEnabled", "false");
    d_root->setSize(CEGUI::USize(cegui_reldim(1.0f), cegui_reldim(1.0f)));
    d_root->setProperty("BackgroundColours", "tl:FFBFBFBF tr:FFBFBFBF bl:FFBFBFBF br:FFBFBFBF");
    d_root->subscribeEvent(Window::EventSemanticEvent,
        Event::Subscriber(&ScrollablePaneSample::semanticEventHandler, this));

    d_guiContext->setRootWindow(d_root);

    // create a menubar.
    // this will fit in the top of the screen and have options for the Sample
    UDim bar_bottom(0,d_font->getLineSpacing(1.5f));

    Window* bar = d_wm->createWindow("WindowsLook/Menubar");
    bar->setArea(UDim(0,0),UDim(0,0),UDim(1,0),bar_bottom);
    d_root->addChild(bar);

    // fill out the menubar
    createMenu(bar);

    // create a scrollable pane for our Sample content
    d_pane = static_cast<ScrollablePane*>(d_wm->createWindow("WindowsLook/ScrollablePane"));
    d_pane->setArea(URect(UDim(0,0),bar_bottom,UDim(1,0),UDim(1,0)));
    // this scrollable pane will be a kind of virtual desktop in the sense that it's bigger than
    // the screen. 3000 x 3000 pixels
    d_pane->setContentPaneAutoSized(false);
    d_pane->setContentPaneArea(CEGUI::Rectf(0, 0, 5000, 5000));
    d_root->addChild(d_pane);

    // add a dialog to this pane so we have something to drag around :)
    Window* dlg = d_wm->createWindow("WindowsLook/FrameWindow");
    dlg->setMinSize(USize(UDim(0,250),UDim(0,100)));
    dlg->setSize(USize(UDim(0,250),UDim(0,100)));
    dlg->setText("Drag me around");
    d_pane->addChild(dlg);

    return true;
}

/*************************************************************************/
void ScrollablePaneSample::createMenu(CEGUI::Window* bar)
{
    using namespace CEGUI;

    // file menu item
    Window* file = d_wm->createWindow("WindowsLook/MenuItem");
    file->setText("File");
    bar->addChild(file);

    // file popup
    Window* popup = d_wm->createWindow("WindowsLook/PopupMenu");
    file->addChild(popup);

    // quit item in file menu
    Window* item = d_wm->createWindow("WindowsLook/MenuItem");
    item->setText("Quit");
    item->subscribeEvent("Clicked", Event::Subscriber(&ScrollablePaneSample::fileQuit, this));
    popup->addChild(item);

    // Sample menu item
    Window* Sample = d_wm->createWindow("WindowsLook/MenuItem");
    Sample->setText("Sample");
    bar->addChild(Sample);

    // Sample popup
    popup = d_wm->createWindow("WindowsLook/PopupMenu");
    Sample->addChild(popup);

    // Sample -> new window
    item = d_wm->createWindow("WindowsLook/MenuItem");
    item->setText("New dialog");
    item->setTooltipText("Hotkey: Space");
    item->subscribeEvent("Clicked", Event::Subscriber(&ScrollablePaneSample::SampleNewDialog, this));
    popup->addChild(item);
}

/************************************************************************/
void ScrollablePaneSample::deinitialise()
{
    // everything we did is cleaned up by CEGUI
    delete d_inputAggregator;
}

/************************************************************************/
bool ScrollablePaneSample::SampleNewDialog(const CEGUI::EventArgs&)
{
    using namespace CEGUI;

    // add a dialog to this pane so we have some more stuff to drag around :)
    Window* dlg = d_wm->createWindow("WindowsLook/FrameWindow");
    dlg->setMinSize(USize(UDim(0,200),UDim(0,100)));
    dlg->setSize(USize(UDim(0,200),UDim(0,100)));
    dlg->setText("Drag me around too!");

    // we put this in the center of the viewport into the scrollable pane
    UVector2 uni_center(UDim(0.5f,0), UDim(0.5f,0));
    // URGENT FIXME!
    //Vector2f center = CoordConverter::windowToScreen(*d_root, uni_center);
    //Vector2f target = CoordConverter::screenToWindow(*d_pane->getContentPane(), center);
    //dlg->setPosition(UVector2(UDim(0,target.d_x-100), UDim(0,target.d_y-50)));

    d_pane->addChild(dlg);

    return true;
}

bool ScrollablePaneSample::semanticEventHandler(const CEGUI::EventArgs& e)
{
    const CEGUI::SemanticEventArgs& args = static_cast<const CEGUI::SemanticEventArgs&>(e);
    if (args.d_semanticValue == SpawnNewDialog)
    {
        // this handler does not use the event args at all so this is fine :)
        // though maybe a bit hack-ish...
        SampleNewDialog(e);
        return true;
    }

    return false;
}<commit_msg>Renamed ScrollablePaneDeme to ScrollablePaneDemo<commit_after>/***********************************************************************
    created:    Aug 22 2014
    author:     Luca Ebach <lucaebach@gmail.com>
                (based on original code by Tomas Lindquist Olsen)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "ScrollablePane.h"

#include "CEGUI/System.h"
#include "CEGUI/SchemeManager.h"
#include "CEGUI/WindowManager.h"
#include "CEGUI/FontManager.h"
#include "CEGUI/ImageManager.h"
#include "CEGUI/InputAggregator.h"
#include "CEGUI/InputEventReceiver.h"
#include "CEGUI/Font.h"
#include "CEGUI/Window.h"
#include "CEGUI/CoordConverter.h"
#include "CEGUI/GUIContext.h"

#include "CEGUI/widgets/ScrollablePane.h"
#include "CEGUI/widgets/ScrolledContainer.h"

#include "SampleBase.h"

ScrollablePaneSample::ScrollablePaneSample()
{
    Sample::d_name = "ScrollablePaneDemo";
    Sample::d_credits = "Tomas Lindquist Olsen";
    Sample::d_description =
        "The ScrollbarPane sample uses the WindowsLook, which gives it a look similar "
        "to old Windows applications. The background consists of a ScrollablePane to "
        "which windows can be added, using the menu bar. The items on the pane can be "
        "moved freely and the pane can be scrolled with the scrollbars.";
    Sample::d_summary =
        "The background window is of target type \"CEGUI/ScrollablePane\". "
        "The WindowsLook skin is used for all the windows.";
}

bool ScrollablePaneSample::initialise(CEGUI::GUIContext* guiContext)
{
    using namespace CEGUI;

    d_guiContext = guiContext;
    d_usedFiles = CEGUI::String(__FILE__);

    d_inputAggregator = new SampleInputAggregator(d_guiContext);

    // this sample will use WindowsLook
    SchemeManager::getSingleton().createFromFile("WindowsLook.scheme");

    // load the default font
    d_font = &FontManager::getSingleton().createFromFile("DejaVuSans-12-NoScale.font");
    d_guiContext->setDefaultFont(d_font);

    // set the cursor
    d_system = System::getSingletonPtr();
    d_guiContext->getCursor().setDefaultImage("WindowsLook/MouseArrow");

    // set the default tooltip type
    d_guiContext->setDefaultTooltipType("WindowsLook/Tooltip");

    // We need the window manager to set up the test interface :)
    d_wm = WindowManager::getSingletonPtr();

    // create a root window
    // this will be a static, to give a nice app'ish background
    d_root = d_wm->createWindow("WindowsLook/Static");
    d_root->setProperty("FrameEnabled", "false");
    d_root->setSize(CEGUI::USize(cegui_reldim(1.0f), cegui_reldim(1.0f)));
    d_root->setProperty("BackgroundColours", "tl:FFBFBFBF tr:FFBFBFBF bl:FFBFBFBF br:FFBFBFBF");
    d_root->subscribeEvent(Window::EventSemanticEvent,
        Event::Subscriber(&ScrollablePaneSample::semanticEventHandler, this));

    d_guiContext->setRootWindow(d_root);

    // create a menubar.
    // this will fit in the top of the screen and have options for the Sample
    UDim bar_bottom(0,d_font->getLineSpacing(1.5f));

    Window* bar = d_wm->createWindow("WindowsLook/Menubar");
    bar->setArea(UDim(0,0),UDim(0,0),UDim(1,0),bar_bottom);
    d_root->addChild(bar);

    // fill out the menubar
    createMenu(bar);

    // create a scrollable pane for our Sample content
    d_pane = static_cast<ScrollablePane*>(d_wm->createWindow("WindowsLook/ScrollablePane"));
    d_pane->setArea(URect(UDim(0,0),bar_bottom,UDim(1,0),UDim(1,0)));
    // this scrollable pane will be a kind of virtual desktop in the sense that it's bigger than
    // the screen. 3000 x 3000 pixels
    d_pane->setContentPaneAutoSized(false);
    d_pane->setContentPaneArea(CEGUI::Rectf(0, 0, 5000, 5000));
    d_root->addChild(d_pane);

    // add a dialog to this pane so we have something to drag around :)
    Window* dlg = d_wm->createWindow("WindowsLook/FrameWindow");
    dlg->setMinSize(USize(UDim(0,250),UDim(0,100)));
    dlg->setSize(USize(UDim(0,250),UDim(0,100)));
    dlg->setText("Drag me around");
    d_pane->addChild(dlg);

    return true;
}

/*************************************************************************/
void ScrollablePaneSample::createMenu(CEGUI::Window* bar)
{
    using namespace CEGUI;

    // file menu item
    Window* file = d_wm->createWindow("WindowsLook/MenuItem");
    file->setText("File");
    bar->addChild(file);

    // file popup
    Window* popup = d_wm->createWindow("WindowsLook/PopupMenu");
    file->addChild(popup);

    // quit item in file menu
    Window* item = d_wm->createWindow("WindowsLook/MenuItem");
    item->setText("Quit");
    item->subscribeEvent("Clicked", Event::Subscriber(&ScrollablePaneSample::fileQuit, this));
    popup->addChild(item);

    // Sample menu item
    Window* Sample = d_wm->createWindow("WindowsLook/MenuItem");
    Sample->setText("Sample");
    bar->addChild(Sample);

    // Sample popup
    popup = d_wm->createWindow("WindowsLook/PopupMenu");
    Sample->addChild(popup);

    // Sample -> new window
    item = d_wm->createWindow("WindowsLook/MenuItem");
    item->setText("New dialog");
    item->setTooltipText("Hotkey: Space");
    item->subscribeEvent("Clicked", Event::Subscriber(&ScrollablePaneSample::SampleNewDialog, this));
    popup->addChild(item);
}

/************************************************************************/
void ScrollablePaneSample::deinitialise()
{
    // everything we did is cleaned up by CEGUI
    delete d_inputAggregator;
}

/************************************************************************/
bool ScrollablePaneSample::SampleNewDialog(const CEGUI::EventArgs&)
{
    using namespace CEGUI;

    // add a dialog to this pane so we have some more stuff to drag around :)
    Window* dlg = d_wm->createWindow("WindowsLook/FrameWindow");
    dlg->setMinSize(USize(UDim(0,200),UDim(0,100)));
    dlg->setSize(USize(UDim(0,200),UDim(0,100)));
    dlg->setText("Drag me around too!");

    // we put this in the center of the viewport into the scrollable pane
    UVector2 uni_center(UDim(0.5f,0), UDim(0.5f,0));
    // URGENT FIXME!
    //Vector2f center = CoordConverter::windowToScreen(*d_root, uni_center);
    //Vector2f target = CoordConverter::screenToWindow(*d_pane->getContentPane(), center);
    //dlg->setPosition(UVector2(UDim(0,target.d_x-100), UDim(0,target.d_y-50)));

    d_pane->addChild(dlg);

    return true;
}

bool ScrollablePaneSample::semanticEventHandler(const CEGUI::EventArgs& e)
{
    const CEGUI::SemanticEventArgs& args = static_cast<const CEGUI::SemanticEventArgs&>(e);
    if (args.d_semanticValue == SpawnNewDialog)
    {
        // this handler does not use the event args at all so this is fine :)
        // though maybe a bit hack-ish...
        SampleNewDialog(e);
        return true;
    }

    return false;
}
<|endoftext|>


<commit_before>#include <catch.hpp>

#include <limits>
#include "VTypes.h"

using namespace std;
using namespace UniSetTypes;
using namespace VTypes;

TEST_CASE("VTypes: I2","[vtypes][I2]")
{
	SECTION("Default constructor")
	{
		I2 v;
		REQUIRE( (int)v == 0 );
	}
	SECTION("'int' constructor")
	{
		I2 v(100);
		REQUIRE( (int)v == 100 );

		I2 v2(-1000000);
		REQUIRE( (int)v2 == -1000000 );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		I2 v1(data,2);
		REQUIRE( (int)v1 == -65536 );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		I2 v2(data3,3);
		REQUIRE( (int)v2 == -65536 );
	}
}

TEST_CASE("VTypes: I2r","[vtypes][I2r]")
{
	SECTION("Default constructor")
	{
		I2r v;
		REQUIRE( (int)v == 0 );
	}
	SECTION("'int' constructor")
	{
		I2r v(100);
		REQUIRE( (int)v == 100 );

		I2r v1(-1000000);
		REQUIRE( (int)v1 == -1000000 );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		I2r v1(data,2);
		REQUIRE( (int)v1 == 65535 );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		I2r v2(data3,3);
		REQUIRE( (int)v2 == 65535 );

		I2r tmp(-100000);
		ModbusRTU::ModbusData d2[2];
		d2[0] = tmp.raw.v[1];
		d2[1] = tmp.raw.v[0];
		I2r v3(d2,2);
		REQUIRE( (int)v3 == -100000 );

	}
}

TEST_CASE("VTypes: U2","[vtypes][U2]")
{
	SECTION("Default constructor")
	{
		U2 v;
		REQUIRE( (unsigned int)v == 0 );
	}
	SECTION("'unsigned int' constructor")
	{
		{
			U2 v( numeric_limits<unsigned int>::max() );
			REQUIRE( (unsigned int)v == numeric_limits<unsigned int>::max() );
			REQUIRE( v.raw.v[0] == 0xffff );
			REQUIRE( v.raw.v[1] == 0xffff );
		}

		{
			U2 v(-1);
			REQUIRE( (unsigned int)v == 4294967295 );
		}
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		U2 v1(data,2);
		REQUIRE( (unsigned int)v1 == 0xffff0000 );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		U2 v2(data3,3);
		REQUIRE( (unsigned int)v2 == 0xffff0000 );
	}
}

TEST_CASE("VTypes: U2r","[vtypes][U2r]")
{
	SECTION("Default constructor")
	{
		U2r v;
		REQUIRE( (unsigned int)v == 0 );
	}
	SECTION("'unsigned int' constructor")
	{
		U2r v( numeric_limits<unsigned int>::max() );
		REQUIRE( (unsigned int)v == numeric_limits<unsigned int>::max() );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		U2r v1(data,2);
		REQUIRE( (unsigned int)v1 == 0x0000ffff );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		U2r v2(data3,3);
		REQUIRE( (unsigned int)v2 == 0x0000ffff );
	}
}

TEST_CASE("VTypes: F2","[vtypes][F2]")
{
	SECTION("Default constructor")
	{
		F2 v;
		REQUIRE( (float)v == 0 );
	}
	SECTION("'float' constructor")
	{
		F2 v( numeric_limits<float>::max() );
		REQUIRE( (float)v == numeric_limits<float>::max() );
	}
	SECTION("Modbus constructor")
	{
		float f=1.5;
		ModbusRTU::ModbusData data[2];
		memcpy(data,&f,sizeof(data));
		F2 v1(data,2);
		REQUIRE( (float)v1 == f );
		REQUIRE( (long)v1 == 2 );
		REQUIRE( (int)v1 == 2 );

		ModbusRTU::ModbusData data3[3];
		memset(data3,0,sizeof(data3));
		memcpy(data3,&f,2*sizeof(ModbusRTU::ModbusData));
		F2 v2(data3,3);
		REQUIRE( (float)v2 == f );
	}
}

TEST_CASE("VTypes: F2r","[vtypes][F2r]")
{
	SECTION("Default constructor")
	{
		F2r v;
		REQUIRE( (float)v == 0 );
	}
	SECTION("'float' constructor")
	{
		F2r v( numeric_limits<float>::max() );
		REQUIRE( (float)v == numeric_limits<float>::max() );
	}
	SECTION("Modbus constructor")
	{
		float f=1.5;
		ModbusRTU::ModbusData data[2];
		memcpy(data,&f,sizeof(data));
		std::swap(data[0],data[1]);
		F2r v1(data,2);
		REQUIRE( (float)v1 == f );
		REQUIRE( (long)v1 == 2 );
		REQUIRE( (int)v1 == 2 );

		ModbusRTU::ModbusData data3[3];
		memset(data3,0,sizeof(data3));
		memcpy(data3,&f,2*sizeof(ModbusRTU::ModbusData));
		std::swap(data3[0],data3[1]);
		F2r v2(data3,3);
		REQUIRE( (float)v2 == f );
	}
}

TEST_CASE("VTypes: F4","[vtypes][F4]")
{
	SECTION("Default constructor")
	{
		F4 v;
		REQUIRE( (float)v == 0 );
	}
	SECTION("'float' constructor")
	{
		{
			F4 v( numeric_limits<float>::max() );
			REQUIRE( (float)v == numeric_limits<float>::max() );
		}
		{

			F4 v( numeric_limits<float>::min() );
			REQUIRE( (float)v == numeric_limits<float>::min() );
		}
	}
	SECTION("Modbus constructor")
	{
		{
			float f = numeric_limits<float>::max();
			ModbusRTU::ModbusData data[4];
			memcpy(data,&f,sizeof(data));
			F4 v1(data,4);
			REQUIRE( (float)v1 == f );
		}
		{
			float f = numeric_limits<float>::max();
			ModbusRTU::ModbusData data5[5];
			memset(data5,0,sizeof(data5));
			memcpy(data5,&f,4*sizeof(ModbusRTU::ModbusData));
			F4 v2(data5,5);
			REQUIRE( (float)v2 == f );
		}
		{
			float f = numeric_limits<float>::min();
			ModbusRTU::ModbusData data[4];
			memcpy(data,&f,sizeof(data));
			F4 v1(data,4);
			REQUIRE( (float)v1 == f );
		}
	}
}

TEST_CASE("VTypes: Byte","[vtypes][byte]")
{
	SECTION("Default constructor")
	{
		Byte v;
		REQUIRE( (char)v == 0 );
	}
	SECTION("'2 byte' constructor")
	{
		Byte v(132,255);
		REQUIRE( v[0] == 132 );
		REQUIRE( v[1] == 255 );
	}
	SECTION("'long' constructor")
	{
		long l=0xff;
		Byte v(l);
		REQUIRE( (unsigned char)v == 0xff );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData d = 255;
		Byte v(d);
		REQUIRE( (unsigned char)v == 255 );
	}
}

TEST_CASE("VTypes: Unsigned","[vtypes][unsigned]")
{
	SECTION("Default constructor")
	{
		Unsigned v;
		REQUIRE( v == 0 );
	}
	SECTION("'long' constructor")
	{
		long l=0xffff;
		Unsigned v(l);
		REQUIRE( (unsigned short)v == 0xffff );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData d = 65535;
		Unsigned v(d);
		REQUIRE( (unsigned short)v == 65535 );
	}
}

TEST_CASE("VTypes: Signed","[vtypes][signed]")
{
	SECTION("Default constructor")
	{
		Signed v;
		REQUIRE( v == 0 );
	}
	SECTION("'long' constructor")
	{
		long l= -32766;
		Signed v(l);
		REQUIRE( (signed short)v == l );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData d = 65535;
		Signed v(d);
		REQUIRE( (signed short)v == (signed short)d );
	}
}
<commit_msg>Исправил ошибки в тестах VTypes.<commit_after>#include <catch.hpp>

#include <limits>
#include "VTypes.h"

using namespace std;
using namespace UniSetTypes;
using namespace VTypes;

TEST_CASE("VTypes: I2","[vtypes][I2]")
{
	SECTION("Default constructor")
	{
		I2 v;
		REQUIRE( (int)v == 0 );
	}
	SECTION("'int' constructor")
	{
		I2 v(100);
		REQUIRE( (int)v == 100 );

		I2 v2(-1000000);
		REQUIRE( (int)v2 == -1000000 );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		I2 v1(data,2);
		REQUIRE( (int)v1 == -65536 );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		I2 v2(data3,3);
		REQUIRE( (int)v2 == -65536 );
	}
}

TEST_CASE("VTypes: I2r","[vtypes][I2r]")
{
	SECTION("Default constructor")
	{
		I2r v;
		REQUIRE( (int)v == 0 );
	}
	SECTION("'int' constructor")
	{
		I2r v(100);
		REQUIRE( (int)v == 100 );

		I2r v1(-1000000);
		REQUIRE( (int)v1 == -1000000 );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		I2r v1(data,2);
		REQUIRE( (int)v1 == 65535 );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		I2r v2(data3,3);
		REQUIRE( (int)v2 == 65535 );

		I2r tmp(-100000);
		ModbusRTU::ModbusData d2[2];
		d2[0] = tmp.raw.v[1];
		d2[1] = tmp.raw.v[0];
		I2r v3(d2,2);
		REQUIRE( (int)v3 == -100000 );

	}
}

TEST_CASE("VTypes: U2","[vtypes][U2]")
{
	SECTION("Default constructor")
	{
		U2 v;
		REQUIRE( (unsigned int)v == 0 );
	}
	SECTION("'unsigned int' constructor")
	{
		{
			U2 v( numeric_limits<unsigned int>::max() );
			REQUIRE( (unsigned int)v == numeric_limits<unsigned int>::max() );
			REQUIRE( v.raw.v[0] == 0xffff );
			REQUIRE( v.raw.v[1] == 0xffff );
		}

		{
			U2 v(-1);
			REQUIRE( (unsigned int)v == 4294967295 );
		}
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		U2 v1(data,2);
		REQUIRE( (unsigned int)v1 == 0xffff0000 );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		U2 v2(data3,3);
		REQUIRE( (unsigned int)v2 == 0xffff0000 );
	}
}

TEST_CASE("VTypes: U2r","[vtypes][U2r]")
{
	SECTION("Default constructor")
	{
		U2r v;
		REQUIRE( (unsigned int)v == 0 );
	}
	SECTION("'unsigned int' constructor")
	{
		U2r v( numeric_limits<unsigned int>::max() );
		REQUIRE( (unsigned int)v == numeric_limits<unsigned int>::max() );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData data[2] = {0,0xFFFF};
		U2r v1(data,2);
		REQUIRE( (unsigned int)v1 == 0x0000ffff );

		ModbusRTU::ModbusData data3[3] = {0,0xFFFF,0xFFFF};
		U2r v2(data3,3);
		REQUIRE( (unsigned int)v2 == 0x0000ffff );
	}
}

TEST_CASE("VTypes: F2","[vtypes][F2]")
{
	SECTION("Default constructor")
	{
		F2 v;
		REQUIRE( (float)v == 0 );
	}
	SECTION("'float' constructor")
	{
		F2 v( numeric_limits<float>::max() );
		REQUIRE( (float)v == numeric_limits<float>::max() );
	}
	SECTION("Modbus constructor")
	{
		float f=1.5;
		ModbusRTU::ModbusData data[2];
		memcpy(data,&f,sizeof(data));
		F2 v1(data,2);
		REQUIRE( (float)v1 == f );
		REQUIRE( (long)v1 == 2 );
		REQUIRE( (int)v1 == 2 );

		ModbusRTU::ModbusData data3[3];
		memset(data3,0,sizeof(data3));
		memcpy(data3,&f,2*sizeof(ModbusRTU::ModbusData));
		F2 v2(data3,3);
		REQUIRE( (float)v2 == f );
	}
}

TEST_CASE("VTypes: F2r","[vtypes][F2r]")
{
	SECTION("Default constructor")
	{
		F2r v;
		REQUIRE( (float)v == 0 );
	}
	SECTION("'float' constructor")
	{
		F2r v( numeric_limits<float>::max() );
		REQUIRE( (float)v == numeric_limits<float>::max() );
	}
	SECTION("Modbus constructor")
	{
		float f=1.5;
		ModbusRTU::ModbusData data[2];
		memcpy(data,&f,sizeof(data));
		std::swap(data[0],data[1]);
		F2r v1(data,2);
		REQUIRE( (float)v1 == f );
		REQUIRE( (long)v1 == 2 );
		REQUIRE( (int)v1 == 2 );

		ModbusRTU::ModbusData data3[3];
		memset(data3,0,sizeof(data3));
		memcpy(data3,&f,2*sizeof(ModbusRTU::ModbusData));
		std::swap(data3[0],data3[1]);
		F2r v2(data3,3);
		REQUIRE( (float)v2 == f );
	}
}

TEST_CASE("VTypes: F4","[vtypes][F4]")
{
	SECTION("Default constructor")
	{
		F4 v;
		REQUIRE( (float)v == 0 );
	}
	SECTION("'float' constructor")
	{
		{
			F4 v( numeric_limits<float>::max() );
			REQUIRE( (float)v == numeric_limits<float>::max() );
		}
		{

			F4 v( numeric_limits<float>::min() );
			REQUIRE( (float)v == numeric_limits<float>::min() );
		}
	}
	SECTION("Modbus constructor")
	{
		{
			float f = numeric_limits<float>::max();
			ModbusRTU::ModbusData data[4];
			memcpy(data,&f,sizeof(data));
			F4 v1(data,4);
			REQUIRE( (float)v1 == f );
		}
		{
			float f = numeric_limits<float>::max();
			ModbusRTU::ModbusData data5[5];
			memset(data5,0,sizeof(data5));
			memcpy(data5,&f,4*sizeof(ModbusRTU::ModbusData));
			F4 v2(data5,5);
			REQUIRE( (float)v2 == f );
		}
		{
			float f = numeric_limits<float>::min();
			ModbusRTU::ModbusData data[4];
			memcpy(data,&f,sizeof(data));
			F4 v1(data,4);
			REQUIRE( (float)v1 == f );
		}
	}
}

TEST_CASE("VTypes: Byte","[vtypes][byte]")
{
	SECTION("Default constructor")
	{
		Byte v;
		REQUIRE( v[0] == 0 );
	}
	SECTION("'2 byte' constructor")
	{
		Byte v(132,255);
		REQUIRE( v[0] == 132 );
		REQUIRE( v[1] == 255 );
	}
	SECTION("'long' constructor")
	{
		long l=0xff;
		Byte v(l);
		REQUIRE( (long)v == 0xff );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData d = 255;
		Byte v(d);
		REQUIRE( (unsigned char)v[0] == 255 );
	}
}

TEST_CASE("VTypes: Unsigned","[vtypes][unsigned]")
{
	SECTION("Default constructor")
	{
		Unsigned v;
		REQUIRE( v == 0 );
	}
	SECTION("'long' constructor")
	{
		long l=0xffff;
		Unsigned v(l);
		REQUIRE( (unsigned short)v == 0xffff );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData d = 65535;
		Unsigned v(d);
		REQUIRE( (unsigned short)v == 65535 );
	}
}

TEST_CASE("VTypes: Signed","[vtypes][signed]")
{
	SECTION("Default constructor")
	{
		Signed v;
		REQUIRE( v == 0 );
	}
	SECTION("'long' constructor")
	{
		long l= -32766;
		Signed v(l);
		REQUIRE( (signed short)v == l );
	}
	SECTION("Modbus constructor")
	{
		ModbusRTU::ModbusData d = 65535;
		Signed v(d);
		REQUIRE( (signed short)v == (signed short)d );
	}
}
<|endoftext|>


<commit_before>/**
 * File        : AStar.cc
 * Description : Implementation of A* algorithm using a specified "world"
 *               from the worlds folder.
 */

#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <chrono>

#include <boost/lexical_cast.hpp>

#include "algorithms/tools/PathTile.h"
#include "algorithms/tools/PriorityQueue.h"
#include "common/Results.h"

using namespace pathFind;

const std::string WORLD_DIR = "worlds";
const std::string WORLD_EXT = ".world";

const std::string ALG_NAME = "bidirectional";

int main (int args, char* argv[])
{
    // Program should be started with 5 command line parameter
    // that specifies the name of the world file to read from,
    // the start x, start y, end x, and end y
    if (args != 6 )
    {
        std::cout << "Incorrect inputs. Usage: <filename> <start x> <start y> <end x> <end y>" << std::endl;
        return EXIT_FAILURE;
    }

    // Parse the world file
    std::stringstream filename;
    filename << WORLD_DIR << "/" << argv[1] << WORLD_EXT;

    std::ifstream worldFile (filename.str (),
            std::ifstream::in | std::ifstream::binary);

    if (!worldFile)
    {
        std::cout << "World file doesn't exist." << std::endl;
        return EXIT_FAILURE;
    }
    pathFind::World world;

    worldFile >> world;

    // Parse the start and end points
    uint startX, startY, endX, endY;
    try
    {
        startX = boost::lexical_cast<uint> (argv[2]);
        startY = boost::lexical_cast<uint> (argv[3]);
        endX = boost::lexical_cast<uint> (argv[4]);
        endY = boost::lexical_cast<uint> (argv[5]);
    } catch (boost::bad_lexical_cast &e)
    {
        std::cout << "Start and end points failed to convert to numeric types" << std::endl;
        return EXIT_FAILURE;
    }

    auto t1 = std::chrono::high_resolution_clock::now();

    // Priority Queue with A* heuristic function added
    PriorityQueue forwardOpenTiles (world, [endX, endY] (uint x, uint y)
        {
            return  (x < endX ? endX - x : x - endX) +
                    (y < endY ? endY - y : y - endY);
        });

    PriorityQueue reverseOpenTiles (world, [startX, startY] (uint x, uint y)
        {
            return  (x < startX ? startX - x : x - startX) +
                    (y < startY ? startY - y : y - startY);
        });

    // Ensure that start and end points are valid
    if (!forwardOpenTiles.isValid (startX, startY))
    {
        std::cout << "Start point either is a wall or isn't out of the world bounds" << std::endl;
        return EXIT_FAILURE;
    }
    // Check each neighbor
    if (!reverseOpenTiles.isValid (endX, endY))
    {
        std::cout << "End point either is a wall or isn't out of the world bounds" << std::endl;
        return EXIT_FAILURE;
    }

    // A* algorithm
    forwardOpenTiles.changeBestCost (startX, startY, 0);
    reverseOpenTiles.changeBestCost (endX, endY, 0);

    std::unordered_map<uint, PathTile> expandedTiles;
    PathTile fTile = forwardOpenTiles.top();
    PathTile rTile = reverseOpenTiles.top();
    while ((fTile.xy ().x != endX || fTile.xy ().y != endY) &&
            (rTile.xy ().x != startX || rTile.xy ().y != startY))
    {
        // forward search
        forwardOpenTiles.pop ();
        expandedTiles[fTile.getTile ().id] = fTile;
        // Check each neighbor
        forwardOpenTiles.tryUpdateBestCost (fTile.xy ().x + 1, fTile.xy ().y, fTile);
        forwardOpenTiles.tryUpdateBestCost (fTile.xy ().x, fTile.xy ().y + 1, fTile);
        forwardOpenTiles.tryUpdateBestCost (fTile.xy ().x - 1, fTile.xy ().y, fTile);
        forwardOpenTiles.tryUpdateBestCost (fTile.xy ().x, fTile.xy ().y - 1, fTile);

        fTile = forwardOpenTiles.top ();

        auto overlapTile = expandedTiles.find(fTile.getTile ().id);
        if (overlapTile != expandedTiles.end ())
        {
            // Best path found
            rTile = overlapTile->second;
            break;
        }

        // reverse search
        reverseOpenTiles.pop ();
        expandedTiles [rTile.getTile ().id] = rTile;
        // Check each neighbor
        reverseOpenTiles.tryUpdateBestCost (rTile.xy ().x + 1, rTile.xy ().y, rTile);
        reverseOpenTiles.tryUpdateBestCost (rTile.xy ().x, rTile.xy ().y + 1, rTile);
        reverseOpenTiles.tryUpdateBestCost (rTile.xy ().x - 1, rTile.xy ().y, rTile);
        reverseOpenTiles.tryUpdateBestCost (rTile.xy ().x, rTile.xy ().y - 1, rTile);

        rTile = forwardOpenTiles.top ();

        overlapTile = expandedTiles.find(rTile.getTile ().id);
        if (overlapTile != expandedTiles.end ())
        {
            fTile = overlapTile->second;
            // Best path found
            break;
        }
    }

    auto t2 = std::chrono::high_resolution_clock::now();

    // Parse reverse results
    std::vector <Point> reversePath;
    while (rTile.xy ().x != endX || rTile.xy ().y != endY)
    {
        reversePath.emplace_back (rTile.xy ());
        rTile = expandedTiles[(rTile.bestTile ().y * world.getWidth ()) + rTile.bestTile ().x];
    }
    reversePath.emplace_back (rTile.xy ());

    std::vector<Point> finalPath (reversePath.rbegin (), reversePath.rend ());
    while (fTile.xy ().x != startX || fTile.xy ().y != startY)
    {
        fTile = expandedTiles[(fTile.bestTile ().y * world.getWidth()) + fTile.bestTile ().x];
        finalPath.emplace_back(fTile.xy ());
    }

    writeResults (finalPath, argv[1], ALG_NAME,
            std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count());

    return EXIT_SUCCESS;
}
<commit_msg>Updated bidirectional to use the new pathfinding technique to boost performance.<commit_after>/**
 * File        : AStar.cc
 * Description : Implementation of A* algorithm using a specified "world"
 *               from the worlds folder.
 */

#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <chrono>

#include <boost/lexical_cast.hpp>

#include "algorithms/tools/PathTile.h"
#include "algorithms/tools/PriorityQueue.h"
#include "common/Results.h"

using namespace pathFind;

const std::string WORLD_DIR = "worlds";
const std::string WORLD_EXT = ".world";

const std::string ALG_NAME = "bidirectional";

int main (int args, char* argv[])
{
    // Program should be started with 5 command line parameter
    // that specifies the name of the world file to read from,
    // the start x, start y, end x, and end y
    if (args != 6 )
    {
        std::cout << "Incorrect inputs. Usage: <filename> <start x> <start y> <end x> <end y>" << std::endl;
        return EXIT_FAILURE;
    }

    // Parse the world file
    std::stringstream filename;
    filename << WORLD_DIR << "/" << argv[1] << WORLD_EXT;

    std::ifstream worldFile (filename.str (),
            std::ifstream::in | std::ifstream::binary);

    if (!worldFile)
    {
        std::cout << "World file doesn't exist." << std::endl;
        return EXIT_FAILURE;
    }
    pathFind::World world;

    worldFile >> world;

    // Parse the start and end points
    uint startX, startY, endX, endY;
    try
    {
        startX = boost::lexical_cast<uint> (argv[2]);
        startY = boost::lexical_cast<uint> (argv[3]);
        endX = boost::lexical_cast<uint> (argv[4]);
        endY = boost::lexical_cast<uint> (argv[5]);
    } catch (boost::bad_lexical_cast &e)
    {
        std::cout << "Start and end points failed to convert to numeric types" << std::endl;
        return EXIT_FAILURE;
    }

    auto t1 = std::chrono::high_resolution_clock::now();

    // Priority Queue with A* heuristic function added
    PriorityQueue forwardOpenTiles (world.getWidth (), world.getHeight (), [endX, endY] (uint x, uint y)
        {
            return  (x < endX ? endX - x : x - endX) +
                    (y < endY ? endY - y : y - endY);
        });

    PriorityQueue reverseOpenTiles (world.getWidth (), world.getHeight (), [startX, startY] (uint x, uint y)
        {
            return  (x < startX ? startX - x : x - startX) +
                    (y < startY ? startY - y : y - startY);
        });

    // A* algorithm
    forwardOpenTiles.push (world (startX, startY), {startX, startY}, 0);
    reverseOpenTiles.changeBestCost (endX, endY, 0);

    std::unordered_map<uint, PathTile> expandedTiles;
    PathTile fTile = forwardOpenTiles.top();
    PathTile rTile = reverseOpenTiles.top();
    while ((fTile.xy ().x != endX || fTile.xy ().y != endY) &&
            (rTile.xy ().x != startX || rTile.xy ().y != startY))
    {
        // forward search
        forwardOpenTiles.pop ();
        expandedTiles[fTile.getTile ().id] = fTile;
        // Check each neighbor
        Point adjPoint {fTile.xy ().x + 1, fTile.xy ().y}; // east
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                forwardOpenTiles.tryUpdateBestCost (worldTile, adjPoint, fTile);
            }
        }

        adjPoint = {fTile.xy ().x, fTile.xy ().y + 1}; // south
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                forwardOpenTiles.tryUpdateBestCost (worldTile, adjPoint, fTile);
            }
        }

        adjPoint = {fTile.xy ().x - 1, fTile.xy ().y}; // west
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                forwardOpenTiles.tryUpdateBestCost (worldTile, adjPoint, fTile);
            }
        }

        adjPoint = {fTile.xy ().x, fTile.xy ().y - 1}; // north
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                forwardOpenTiles.tryUpdateBestCost (worldTile, adjPoint, fTile);
            }
        }

        fTile = forwardOpenTiles.top ();

        auto overlapTile = expandedTiles.find(fTile.getTile ().id);
        if (overlapTile != expandedTiles.end ())
        {
            // Best path found
            rTile = overlapTile->second;
            break;
        }

        // reverse search
        reverseOpenTiles.pop ();
        expandedTiles [rTile.getTile ().id] = rTile;
        // Check each neighbor
        adjPoint = {rTile.xy ().x + 1, rTile.xy ().y}; // east
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                reverseOpenTiles.tryUpdateBestCost (worldTile, adjPoint, rTile);
            }
        }

        adjPoint = {rTile.xy ().x, rTile.xy ().y + 1}; // south
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                reverseOpenTiles.tryUpdateBestCost (worldTile, adjPoint, rTile);
            }
        }

        adjPoint = {rTile.xy ().x - 1, rTile.xy ().y}; // west
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                reverseOpenTiles.tryUpdateBestCost (worldTile, adjPoint, rTile);
            }
        }

        adjPoint = {rTile.xy ().x, rTile.xy ().y - 1}; // north
        if (adjPoint.x < world.getWidth() && adjPoint.y < world.getHeight ())
        {
            World::tile_t worldTile = world (adjPoint.x, adjPoint.y);
            if (worldTile.cost != 0 &&
                expandedTiles.find (worldTile.id) == expandedTiles.end ())
            {
                reverseOpenTiles.tryUpdateBestCost (worldTile, adjPoint, rTile);
            }
        }

        rTile = forwardOpenTiles.top ();

        overlapTile = expandedTiles.find(rTile.getTile ().id);
        if (overlapTile != expandedTiles.end ())
        {
            fTile = overlapTile->second;
            // Best path found
            break;
        }
    }

    auto t2 = std::chrono::high_resolution_clock::now();

    // Parse reverse results
    std::vector <Point> reversePath;
    while (rTile.xy ().x != endX || rTile.xy ().y != endY)
    {
        reversePath.emplace_back (rTile.xy ());
        rTile = expandedTiles[(rTile.bestTile ().y * world.getWidth ()) + rTile.bestTile ().x];
    }
    reversePath.emplace_back (rTile.xy ());

    std::vector<Point> finalPath (reversePath.rbegin (), reversePath.rend ());
    while (fTile.xy ().x != startX || fTile.xy ().y != startY)
    {
        fTile = expandedTiles[(fTile.bestTile ().y * world.getWidth()) + fTile.bestTile ().x];
        finalPath.emplace_back(fTile.xy ());
    }

    writeResults (finalPath, argv[1], ALG_NAME,
            std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count());

    return EXIT_SUCCESS;
}
<|endoftext|>