blob: d92fdf38dd331e87218f81925a69d2195d4caf34 [file] [log] [blame]
#include "collection_function.hpp"
#include <cmath>
namespace details
{
class FunctionSingle : public CollectionFunction
{
public:
ReadingItem calculate(const std::vector<ReadingItem>& readings,
uint64_t) const override
{
return readings.back();
}
ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
uint64_t timestamp) const override
{
readings.assign({readings.back()});
return readings.back();
}
};
class FunctionMinimum : public CollectionFunction
{
public:
ReadingItem calculate(const std::vector<ReadingItem>& readings,
uint64_t) const override
{
return *std::min_element(
readings.begin(), readings.end(),
[](const auto& left, const auto& right) {
return std::make_tuple(!std::isfinite(left.second),
left.second) <
std::make_tuple(!std::isfinite(right.second),
right.second);
});
}
ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
uint64_t timestamp) const override
{
readings.assign({ReadingItem(calculate(readings, timestamp))});
return readings.back();
}
};
class FunctionMaximum : public CollectionFunction
{
public:
ReadingItem calculate(const std::vector<ReadingItem>& readings,
uint64_t) const override
{
return *std::max_element(
readings.begin(), readings.end(),
[](const auto& left, const auto& right) {
return std::make_tuple(std::isfinite(left.second),
left.second) <
std::make_tuple(std::isfinite(right.second),
right.second);
});
}
ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
uint64_t timestamp) const override
{
readings.assign({ReadingItem(calculate(readings, timestamp))});
return readings.back();
}
};
class FunctionAverage : public CollectionFunction
{
public:
ReadingItem calculate(const std::vector<ReadingItem>& readings,
uint64_t timestamp) const override
{
auto valueSum = 0.0;
auto timeSum = uint64_t{0};
for (auto it = readings.begin(); it != std::prev(readings.end()); ++it)
{
if (std::isfinite(it->second))
{
const auto kt = std::next(it);
const auto duration = kt->first - it->first;
valueSum += it->second * duration;
timeSum += duration;
}
}
const auto duration = timestamp - readings.back().first;
valueSum += readings.back().second * duration;
timeSum += duration;
return ReadingItem{timestamp, valueSum / timeSum};
}
ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
uint64_t timestamp) const override
{
auto result = calculate(readings, timestamp);
if (std::isfinite(result.second))
{
readings.assign({ReadingItem(readings.front().first, result.second),
ReadingItem(timestamp, readings.back().second)});
}
return result;
}
};
class FunctionSummation : public CollectionFunction
{
public:
ReadingItem calculate(const std::vector<ReadingItem>& readings,
uint64_t timestamp) const override
{
auto valueSum = 0.0;
for (auto it = readings.begin(); it != std::prev(readings.end()); ++it)
{
if (std::isfinite(it->second))
{
const auto kt = std::next(it);
const auto duration = kt->first - it->first;
valueSum += it->second * duration;
}
}
const auto duration = timestamp - readings.back().first;
valueSum += readings.back().second * duration;
return ReadingItem{timestamp, valueSum};
}
ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
uint64_t timestamp) const override
{
auto result = calculate(readings, timestamp);
if (std::isfinite(result.second) && timestamp > 0u)
{
readings.assign({ReadingItem(timestamp - 1u, result.second),
ReadingItem(timestamp, readings.back().second)});
}
return result;
}
};
std::shared_ptr<CollectionFunction>
makeCollectionFunction(OperationType operationType)
{
using namespace std::string_literals;
switch (operationType)
{
case OperationType::single:
return std::make_shared<FunctionSingle>();
case OperationType::min:
return std::make_shared<FunctionMinimum>();
case OperationType::max:
return std::make_shared<FunctionMaximum>();
case OperationType::avg:
return std::make_shared<FunctionAverage>();
case OperationType::sum:
return std::make_shared<FunctionSummation>();
default:
throw std::runtime_error("op: "s +
utils::enumToString(operationType) +
" is not supported"s);
}
}
} // namespace details