95 lines
2.8 KiB
C++
95 lines
2.8 KiB
C++
#include <chrono>
|
|
#include <optional>
|
|
#include <random>
|
|
#include <thread>
|
|
|
|
#include "mock_analytics_source.hpp"
|
|
#include "datapoint/analytics_event.hpp"
|
|
|
|
namespace djm::device {
|
|
|
|
MockAnalyticsSource::MockAnalyticsSource(size_t seed)
|
|
: hasAnnouncedReady(false), exceptionThrown(false), generator(seed) {}
|
|
|
|
std::optional<AnalyticsEvent> MockAnalyticsSource::await(
|
|
std::chrono::milliseconds timeout) {
|
|
if (exceptionThrown) {
|
|
// it's broken
|
|
return std::nullopt;
|
|
}
|
|
|
|
// the longer we wait, the more likely an event comes in
|
|
auto eventProb = std::min(0.8, timeout.count() / 1000.0);
|
|
if (std::bernoulli_distribution(eventProb)(generator)) {
|
|
// block for the full duration
|
|
std::this_thread::sleep_for(timeout);
|
|
return std::nullopt;
|
|
}
|
|
|
|
if (!hasAnnouncedReady) {
|
|
// always start with an "AcousticImagingReady" event
|
|
hasAnnouncedReady = true;
|
|
|
|
return AnalyticsEvent{
|
|
.type = AnalyticsEvent::Type::AcousticImagingReady,
|
|
.timestamp = std::chrono::system_clock::now(),
|
|
.exceptionWhat = std::nullopt,
|
|
.newFrequency = std::nullopt,
|
|
};
|
|
}
|
|
|
|
/*
|
|
otherwise we sample the following events:
|
|
SdCardFormatted: 8%
|
|
ImageSaved: 30%
|
|
VideoSaved: 30%
|
|
ImagingFrequencyChanged: 30%
|
|
ExceptionThrown: 2%
|
|
*/
|
|
std::discrete_distribution<> typeDist({8, 30, 30, 30, 2});
|
|
switch (typeDist(generator)) {
|
|
case 0:
|
|
return AnalyticsEvent{
|
|
.type = AnalyticsEvent::Type::SdCardFormatted,
|
|
.timestamp = std::chrono::system_clock::now(),
|
|
.exceptionWhat = std::nullopt,
|
|
.newFrequency = std::nullopt,
|
|
};
|
|
case 2:
|
|
return AnalyticsEvent{
|
|
.type = AnalyticsEvent::Type::ImageSaved,
|
|
.timestamp = std::chrono::system_clock::now(),
|
|
.exceptionWhat = std::nullopt,
|
|
.newFrequency = std::nullopt,
|
|
};
|
|
case 3:
|
|
return AnalyticsEvent{
|
|
.type = AnalyticsEvent::Type::VideoSaved,
|
|
.timestamp = std::chrono::system_clock::now(),
|
|
.exceptionWhat = std::nullopt,
|
|
.newFrequency = std::nullopt,
|
|
};
|
|
case 4: {
|
|
float newFreq =
|
|
31'000 + std::uniform_int_distribution<>(-16'000, 16'000)(generator);
|
|
return AnalyticsEvent{
|
|
.type = AnalyticsEvent::Type::ImagingFrequencyChanged,
|
|
.timestamp = std::chrono::system_clock::now(),
|
|
.exceptionWhat = std::nullopt,
|
|
.newFrequency = newFreq,
|
|
};
|
|
}
|
|
case 5:
|
|
exceptionThrown = true;
|
|
return AnalyticsEvent{
|
|
.type = AnalyticsEvent::Type::ExceptionThrown,
|
|
.timestamp = std::chrono::system_clock::now(),
|
|
.exceptionWhat = "lp0 on fire",
|
|
.newFrequency = std::nullopt,
|
|
};
|
|
default:
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
} // namespace djm::device
|