mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 21:56:22 +00:00
feat(Core/Movement): time synchronisation to better interpret client timestamps (#5300)
This commit is contained in:
100
src/common/Utilities/CircularBuffer.h
Normal file
100
src/common/Utilities/CircularBuffer.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
*
|
||||
* This file was based on
|
||||
* https://embeddedartistry.com/blog/2017/05/17/creating-a-circular-buffer-in-c-and-c/
|
||||
* https://github.com/embeddedartistry/embedded-resources/blob/master/examples/cpp/circular_buffer.cpp
|
||||
*/
|
||||
|
||||
#ifndef AZEROTHCORE_CIRCULAR_BUFFER_H
|
||||
#define AZEROTHCORE_CIRCULAR_BUFFER_H
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
class CircularBuffer {
|
||||
public:
|
||||
explicit CircularBuffer(size_t size) :
|
||||
buf_(std::unique_ptr<T[]>(new T[size])),
|
||||
max_size_(size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void put(T item)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
buf_[head_] = item;
|
||||
|
||||
if (full_)
|
||||
{
|
||||
tail_ = (tail_ + 1) % max_size_;
|
||||
}
|
||||
|
||||
head_ = (head_ + 1) % max_size_;
|
||||
|
||||
full_ = head_ == tail_;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
//if head and tail are equal, we are empty
|
||||
return (!full_ && (head_ == tail_));
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
//If tail is ahead the head by 1, we are full
|
||||
return full_;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
return max_size_;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
size_t size = max_size_;
|
||||
|
||||
if (!full_)
|
||||
{
|
||||
if (head_ >= tail_)
|
||||
{
|
||||
size = head_ - tail_;
|
||||
}
|
||||
else
|
||||
{
|
||||
size += head_ - tail_;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// the implementation of this function is simplified by the fact that head_ will never be lower than tail_
|
||||
// when compared to the original implementation of this class
|
||||
std::vector<T> content() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return std::vector<T>(buf_.get(), buf_.get() + size());
|
||||
}
|
||||
|
||||
T peak_back() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return empty() ? T() : buf_[tail_];
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::unique_ptr<T[]> buf_;
|
||||
size_t head_ = 0;
|
||||
size_t tail_ = 0;
|
||||
const size_t max_size_;
|
||||
bool full_ = 0;
|
||||
};
|
||||
#endif
|
||||
83
src/common/Utilities/MathUtil.h
Normal file
83
src/common/Utilities/MathUtil.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
*/
|
||||
|
||||
#ifndef _MATH_UTIL_H
|
||||
#define _MATH_UTIL_H
|
||||
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
// based on https://stackoverflow.com/questions/7616511/calculate-mean-and-standard-deviation-from-a-vector-of-samples-in-c-using-boos/12405793#comment32490316_12405793
|
||||
template <typename Container, typename T = typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>
|
||||
inline T standard_deviation(Container&& c)
|
||||
{
|
||||
auto b = std::begin(c), e = std::end(c);
|
||||
auto size = std::distance(b, e);
|
||||
auto sum = std::accumulate(b, e, T());
|
||||
auto mean = sum / size;
|
||||
|
||||
if (size == 1)
|
||||
return (T) 0;
|
||||
|
||||
T accum = T();
|
||||
for (const auto d : c)
|
||||
accum += (d - mean) * (d - mean);
|
||||
return std::sqrt(accum / (size - 1));
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename T = typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>
|
||||
inline T mean(Container&& c)
|
||||
{
|
||||
auto b = std::begin(c), e = std::end(c);
|
||||
auto size = std::distance(b, e);
|
||||
auto sum = std::accumulate(b, e, T());
|
||||
return sum / size;
|
||||
}
|
||||
|
||||
// based off https://www.geeksforgeeks.org/finding-median-of-unsorted-array-in-linear-time-using-c-stl/
|
||||
template <typename T>
|
||||
inline T median(std::vector<T> a)
|
||||
{
|
||||
size_t n = a.size();
|
||||
// If size of the arr[] is even
|
||||
if (n % 2 == 0) {
|
||||
|
||||
// Applying nth_element
|
||||
// on n/2th index
|
||||
std::nth_element(a.begin(),
|
||||
a.begin() + n / 2,
|
||||
a.end());
|
||||
|
||||
// Applying nth_element
|
||||
// on (n-1)/2 th index
|
||||
std::nth_element(a.begin(),
|
||||
a.begin() + (n - 1) / 2,
|
||||
a.end());
|
||||
|
||||
// Find the average of value at
|
||||
// index N/2 and (N-1)/2
|
||||
return (T)(a[(n - 1) / 2]
|
||||
+ a[n / 2])
|
||||
/ 2.0;
|
||||
}
|
||||
|
||||
// If size of the arr[] is odd
|
||||
else {
|
||||
|
||||
// Applying nth_element
|
||||
// on n/2
|
||||
std::nth_element(a.begin(),
|
||||
a.begin() + n / 2,
|
||||
a.end());
|
||||
|
||||
// Value at index (N/2)th
|
||||
// is the median
|
||||
return (T)a[n / 2];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user