#include #include #include #include #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 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