telemetry/demo/mocks/mock_analytics_source.cpp
2025-09-24 19:52:20 +00:00

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