feat(Core/Movement): time synchronisation to better interpret client timestamps (#5300)

This commit is contained in:
Chaouki Dhib
2021-04-23 15:53:09 +02:00
committed by GitHub
parent 970d371442
commit 2d21bfc915
11 changed files with 367 additions and 96 deletions

View 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

View 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