eis/TestProject/RNG/model/ValvePairModel.h

77 lines
2.5 KiB
C
Raw Normal View History

#pragma once
#include <TestProject/RNG/model/IModel.h>
#include <nlohmann/json.hpp>
#include <cstdlib>
#include <string>
#include <vector>
using json = nlohmann::json;
struct ValvePairModel : IModel {
IModel* action = nullptr;
std::string actionModelName;
int on_delay_ticks;
int off_delay_ticks;
int delay_jitter_ticks;
float flash_prob;
float delay_over_prob;
int delay_over_ticks;
enum State { IDLE_LOW, WAITING_RISE, HIGH, WAITING_FALL };
State state = IDLE_LOW;
int delay_counter = 0;
bool prev_action = false;
ValvePairModel(const json& params, float)
: on_delay_ticks(params.value("on_delay_ms", 200) / 20)
, off_delay_ticks(params.value("off_delay_ms", 150) / 20)
, delay_jitter_ticks(params.value("delay_jitter_ms", 0) / 20)
, flash_prob(params.value("flash_prob", 0.0f))
, delay_over_prob(params.value("delay_over_prob", 0.0f))
, delay_over_ticks(params.value("delay_over_ms", 0) / 20) {}
void linkPeers(ModelRegistry& reg) override;
bool evaluateBool(size_t t) override {
if (!action) return false;
bool action_now = action->evaluateBool(t);
switch (state) {
case IDLE_LOW:
if (!prev_action && action_now) {
bool over = ((double)rand() / RAND_MAX) < delay_over_prob;
int base = over ? delay_over_ticks : on_delay_ticks;
delay_counter = base + (delay_jitter_ticks ? rand() % (delay_jitter_ticks + 1) : 0);
state = WAITING_RISE;
}
prev_action = action_now;
break;
case WAITING_RISE:
if (delay_counter > 0) { delay_counter--; }
else { state = HIGH; }
break;
case HIGH:
if (prev_action && !action_now) {
bool over = ((double)rand() / RAND_MAX) < delay_over_prob;
int base = over ? delay_over_ticks : off_delay_ticks;
delay_counter = base + (delay_jitter_ticks ? rand() % (delay_jitter_ticks + 1) : 0);
state = WAITING_FALL;
} else if (((double)rand() / RAND_MAX) < flash_prob) {
return false;
}
prev_action = action_now;
break;
case WAITING_FALL:
if (delay_counter > 0) { delay_counter--; }
else { state = IDLE_LOW; }
break;
}
return state == HIGH || state == WAITING_FALL;
}
void reset() override { state = IDLE_LOW; prev_action = false; }
};
// linkPeers is defined in ModelRegistry.cc to avoid circular include
// (ValvePairModel needs ModelRegistry, ModelRegistry includes ValvePairModel)