# RNG 参数化随机数生成 — 实现计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 将 RNG 从硬编码信号映射重构为 JSON 配置驱动的参数化模型架构,支持 9 种模拟量模式 + 4 种布尔量模式。 **Architecture:** 每个模型实现 `IModel` 接口,`ModelRegistry` 负责加载 `rng_models.json` 并根据 `tables[1]` 创建实例。`Generator::wtite_in_shm` 中去掉所有硬编码 if-else,改为遍历 signals 调用 `model->evaluate()`。 **Tech Stack:** C++20, nlohmann_json (vcpkg), 现有 RandT.h / read_csv.hpp **Build note:** 该项目在 Linux (CentOS 7, GCC 10/devtoolset-10) 编译,当前 Windows 环境仅用于代码编辑。 --- ### Task 1: 创建 JSON 配置文件 **Files:** - Create: `TestProject/RNG/json/rng_models.json` - [ ] **Step 1: 创建 rng_models.json** ```json { "models": { "constant_zero": { "mode": "constant", "params": {} }, "normal_tiny": { "mode": "normal", "params": { "sigma": 0.01 } }, "normal_med": { "mode": "normal", "params": { "sigma": 0.5 } }, "linear_slow": { "mode": "linear", "params": { "k": 0.001 } }, "linear_fast": { "mode": "linear", "params": { "k": 0.05 } }, "sine_ecc1": { "mode": "sine", "params": { "A": 5.0, "omega": 0.314, "phi": 0 } }, "sine_ecc2": { "mode": "sine", "params": { "A": 3.0, "omega": 0.628, "phi": 1.57 } }, "spike_sharp": { "mode": "spike", "params": { "amplitude": 50, "probability": 0.05 } }, "spike_mild": { "mode": "spike", "params": { "amplitude": 10, "probability": 0.15 } }, "drift_slow": { "mode": "drift", "params": { "drift_rate": 0.0001 } }, "drift_fast": { "mode": "drift", "params": { "drift_rate": 0.005 } }, "toggle_2s": { "mode": "bool_toggle", "params": { "period_ms": 2000 } }, "toggle_5s": { "mode": "bool_toggle", "params": { "period_ms": 5000 } }, "toggle_10s": { "mode": "bool_toggle", "params": { "period_ms": 10000 } }, "valve_px_std": { "mode": "valve_pair", "params": { "on_delay_ms": 200, "off_delay_ms": 150, "delay_jitter_ms": 20, "flash_prob": 0.02, "delay_over_prob": 0.0001, "delay_over_ms": 4000 } }, "valve_px_fast": { "mode": "valve_pair", "params": { "on_delay_ms": 80, "off_delay_ms": 60, "delay_jitter_ms": 10, "flash_prob": 0.01, "delay_over_prob": 0, "delay_over_ms": 0 } } } } ``` - [ ] **Step 2: Commit** ```bash git add TestProject/RNG/json/rng_models.json git commit -m "feat: add rng_models.json with model templates" ``` --- ### Task 2: 创建 IModel 基类接口 **Files:** - Create: `TestProject/RNG/model/IModel.h` - [ ] **Step 1: 编写 IModel.h** ```cpp #pragma once #include class ModelRegistry; class IModel { public: virtual ~IModel() = default; virtual float evaluate(size_t t_index) { return 0.0f; } virtual bool evaluateBool(size_t t_index) { return false; } virtual void linkPeers(ModelRegistry& reg) {} virtual void reset() {} }; ``` - [ ] **Step 2: Commit** ```bash git add TestProject/RNG/model/IModel.h git commit -m "feat: add IModel base interface" ``` --- ### Task 3: 实现模拟量模型(Constant, Normal, Linear, Sine, Uniform, Spike, Drift) **Files:** - Create: `TestProject/RNG/model/ConstantModel.h` - Create: `TestProject/RNG/model/NormalModel.h` - Create: `TestProject/RNG/model/LinearModel.h` - Create: `TestProject/RNG/model/SineModel.h` - Create: `TestProject/RNG/model/UniformModel.h` - Create: `TestProject/RNG/model/SpikeModel.h` - Create: `TestProject/RNG/model/DriftModel.h` - [ ] **Step 1: 编写 ConstantModel.h 和 NormalModel.h** ```cpp // ConstantModel.h #pragma once #include #include using json = nlohmann::json; struct ConstantModel : IModel { float c; ConstantModel(const json& params, float defaultVal) : c(defaultVal) {} float evaluate(size_t) override { return c; } }; ``` ```cpp // NormalModel.h #pragma once #include #include #include using json = nlohmann::json; struct NormalModel : IModel { float mean, sigma; NormalModel(const json& params, float defaultVal) : mean(defaultVal), sigma(params.value("sigma", 0.01f)) {} float evaluate(size_t) override { return RandT::GuassRand(mean, sigma); } }; ``` - [ ] **Step 2: 编写 LinearModel.h** ```cpp #pragma once #include #include using json = nlohmann::json; struct LinearModel : IModel { float k, b; LinearModel(const json& params, float defaultVal) : k(params.value("k", 0.0f)), b(defaultVal) {} float evaluate(size_t t) override { return k * t + b; } }; ``` - [ ] **Step 3: 编写 SineModel.h** ```cpp #pragma once #include #include #include using json = nlohmann::json; struct SineModel : IModel { float A, omega, phi, offset; SineModel(const json& params, float defaultVal) : A(params.value("A", 1.0f)), omega(params.value("omega", 1.0f)), phi(params.value("phi", 0.0f)), offset(defaultVal) {} float evaluate(size_t t) override { return A * sinf(omega * t + phi) + offset; } }; ``` - [ ] **Step 4: 编写 UniformModel.h** ```cpp #pragma once #include #include #include using json = nlohmann::json; struct UniformModel : IModel { float center, delta; UniformModel(const json& params, float defaultVal) : center(defaultVal), delta(params.value("delta", 0.01f)) {} float evaluate(size_t) override { return RandT::RandT(center - delta, center + delta); } }; ``` - [ ] **Step 5: 编写 SpikeModel.h** ```cpp #pragma once #include #include #include using json = nlohmann::json; struct SpikeModel : IModel { float base, amplitude, probability; SpikeModel(const json& params, float defaultVal) : base(defaultVal) , amplitude(params.value("amplitude", 1.0f)) , probability(params.value("probability", 0.01f)) {} float evaluate(size_t) override { if ((double)rand() / RAND_MAX < probability) { return base + ((rand() % 2) ? amplitude : -amplitude); } return base; } }; ``` - [ ] **Step 6: 编写 DriftModel.h** ```cpp #pragma once #include #include using json = nlohmann::json; struct DriftModel : IModel { float base, drift_rate; DriftModel(const json& params, float defaultVal) : base(defaultVal), drift_rate(params.value("drift_rate", 0.0f)) {} float evaluate(size_t t) override { return base + drift_rate * t; } }; ``` - [ ] **Step 7: Commit** ```bash git add TestProject/RNG/model/NormalModel.h TestProject/RNG/model/LinearModel.h \ TestProject/RNG/model/SineModel.h TestProject/RNG/model/UniformModel.h \ TestProject/RNG/model/SpikeModel.h TestProject/RNG/model/DriftModel.h git commit -m "feat: add 7 analog signal models (constant, normal, linear, sine, uniform, spike, drift)" ``` --- ### Task 4: 实现 CsvReplayModel **Files:** - Create: `TestProject/RNG/model/CsvReplayModel.h` - [ ] **Step 1: 编写 CsvReplayModel.h** ```cpp #pragma once #include #include #include #include using json = nlohmann::json; struct CsvReplayModel : IModel { ReadCSV::DoubleData data; int column; CsvReplayModel(const json& params, float) : data(params["file"].get()) , column(params["column"].get()) {} float evaluate(size_t t) override { return data(t, column); } }; ``` - [ ] **Step 2: Commit** ```bash git add TestProject/RNG/model/CsvReplayModel.h git commit -m "feat: add CsvReplayModel for CSV data replay" ``` --- ### Task 5: 实现布尔量模型(BoolRandom, BoolToggle, BoolCsv) **Files:** - Create: `TestProject/RNG/model/BoolRandomModel.h` - Create: `TestProject/RNG/model/BoolToggleModel.h` - Create: `TestProject/RNG/model/BoolCsvModel.h` - [ ] **Step 1: 编写 BoolRandomModel.h** ```cpp #pragma once #include #include #include using json = nlohmann::json; struct BoolRandomModel : IModel { float prob_true; BoolRandomModel(const json& params, float defaultVal) : prob_true(params.value("prob_true", 0.5f)) {} bool evaluateBool(size_t) override { return (double)rand() / RAND_MAX < prob_true; } }; ``` - [ ] **Step 2: 编写 BoolToggleModel.h** ```cpp #pragma once #include #include using json = nlohmann::json; struct BoolToggleModel : IModel { int period_ticks; // ~20ms per tick BoolToggleModel(const json& params, float) : period_ticks(params.value("period_ms", 2000) / 20) {} bool evaluateBool(size_t t) override { return (t / period_ticks) % 2 == 0; } }; ``` - [ ] **Step 3: 编写 BoolCsvModel.h** ```cpp #pragma once #include #include #include #include using json = nlohmann::json; struct BoolCsvModel : IModel { ReadCSV::IntData data; int column; BoolCsvModel(const json& params, float) : data(params["file"].get()) , column(params["column"].get()) {} bool evaluateBool(size_t t) override { return (bool)data(t, column); } }; ``` - [ ] **Step 4: Commit** ```bash git add TestProject/RNG/model/BoolRandomModel.h TestProject/RNG/model/BoolToggleModel.h \ TestProject/RNG/model/BoolCsvModel.h git commit -m "feat: add 3 boolean signal models" ``` --- ### Task 6: 实现 ValvePairModel **Files:** - Create: `TestProject/RNG/model/ValvePairModel.h` - [ ] **Step 1: 编写 ValvePairModel.h** ```cpp #pragma once #include #include #include #include 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); // edge detection bool rising_edge = !prev_action && action_now; bool falling_edge = prev_action && !action_now; prev_action = action_now; switch (state) { case IDLE_LOW: if (rising_edge) { 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; } break; case WAITING_RISE: if (delay_counter > 0) { delay_counter--; } else { state = HIGH; } break; case HIGH: if (falling_edge) { 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; // flash: momentary drop, auto-recover next cycle } 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` 实现在 Task 7 ModelRegistry 之后,详见 Step 2。 - [ ] **Step 2: 在 ValvePairModel 中实现 linkPeers(需要 ModelRegistry 声明)** ```cpp // ValvePairModel::linkPeers — 在 model/ValvePairModel.h 末尾,需要先 include ModelRegistry.h // (或者将 linkPeers 实现放在 ModelRegistry.cc 中) // 由于循环依赖(ValvePairModel::linkPeers 需要 ModelRegistry),使用前向声明 + 延迟实现: // model/ValvePairModel.h 中声明 linkPeers,实现在 ModelRegistry.cc 尾部。 #include // ... in ModelRegistry.cc or a separate file: void ValvePairModel::linkPeers(ModelRegistry& reg) { auto models = reg.findByModelName(actionModelName); if (!models.empty()) action = models[0]; } ``` - [ ] **Step 3: Commit** ```bash git add TestProject/RNG/model/ValvePairModel.h git commit -m "feat: add ValvePairModel with jitter/flash/over-delay" ``` --- ### Task 7: 实现 CompositeModel + ModelRegistry **Files:** - Create: `TestProject/RNG/model/CompositeModel.h` - Create: `TestProject/RNG/model/ModelRegistry.h` - Create: `TestProject/RNG/model/ModelRegistry.cc` - [ ] **Step 1: 编写 CompositeModel.h** ```cpp #pragma once #include #include struct CompositeModel : IModel { std::unique_ptr base; std::unique_ptr noise; CompositeModel(std::unique_ptr b, std::unique_ptr n) : base(std::move(b)), noise(std::move(n)) {} float evaluate(size_t t) override { return base->evaluate(t) + noise->evaluate(t); } }; ``` - [ ] **Step 2: 编写 ModelRegistry.h** ```cpp #pragma once #include #include #include #include #include #include #include using json = nlohmann::json; class ModelRegistry { public: using Ctor = std::function(const json& params, float defaultVal)>; static ModelRegistry& instance(); void loadModels(const std::string& jsonPath); IModel* getOrCreate(const std::string& tables1Spec, float defaultVal); std::vector findByModelName(const std::string& modelName); void registerMode(const std::string& mode, Ctor ctor); private: ModelRegistry(); std::unique_ptr createModel(const std::string& modelName, float defaultVal); struct ModelDef { std::string mode; json params; }; std::map modelTemplates; // JSON loaded templates std::map> instances; // created instances, keyed by spec std::map> byModelName; // model name → instances std::map factory; // mode → constructor }; ``` - [ ] **Step 3: 编写 ModelRegistry.cc** ```cpp #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ModelRegistry& ModelRegistry::instance() { static ModelRegistry reg; return reg; } ModelRegistry::ModelRegistry() { registerMode("constant", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("normal", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("linear", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("sine", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("uniform", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("spike", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("drift", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("csv", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("bool_random",[](const json& p, float d) { return std::make_unique(p, d); }); registerMode("bool_toggle",[](const json& p, float d) { return std::make_unique(p, d); }); registerMode("bool_csv", [](const json& p, float d) { return std::make_unique(p, d); }); registerMode("valve_pair", [](const json& p, float d) { return std::make_unique(p, d); }); } void ModelRegistry::registerMode(const std::string& mode, Ctor ctor) { factory[mode] = std::move(ctor); } void ModelRegistry::loadModels(const std::string& jsonPath) { std::ifstream f(jsonPath); if (!f.is_open()) throw std::runtime_error("Cannot open " + jsonPath); json j; f >> j; for (auto& [name, def] : j["models"].items()) { modelTemplates[name] = { def["mode"].get(), def.value("params", json::object()) }; } } std::unique_ptr ModelRegistry::createModel(const std::string& modelName, float defaultVal) { // Check if it's a composite: base+noise auto plusPos = modelName.find('+'); if (plusPos != std::string::npos) { auto base = createModel(modelName.substr(0, plusPos), defaultVal); auto noise = createModel(modelName.substr(plusPos + 1), defaultVal); return std::make_unique(std::move(base), std::move(noise)); } // Check if it's inline CSV: csv:file:col if (modelName.rfind("csv:", 0) == 0) { auto first = modelName.find(':', 4); auto second = modelName.find(':', first + 1); json p; p["file"] = modelName.substr(4, first - 4); p["column"] = std::stoi(modelName.substr(first + 1, second - first - 1)); return factory["csv"](p, 0.0f); } // Check if it's a valve_pair:action_model pair reference auto colonPos = modelName.find(':'); if (colonPos != std::string::npos) { std::string pairModel = modelName.substr(0, colonPos); std::string actionModel = modelName.substr(colonPos + 1); auto it = modelTemplates.find(pairModel); if (it != modelTemplates.end() && it->second.mode == "valve_pair") { auto model = factory["valve_pair"](it->second.params, defaultVal); static_cast(model.get())->actionModelName = actionModel; return model; } } // Simple model name lookup auto it = modelTemplates.find(modelName); if (it == modelTemplates.end()) { // Fallback to normal_tiny if model not found it = modelTemplates.find("normal_tiny"); } auto fit = factory.find(it->second.mode); if (fit == factory.end()) { throw std::runtime_error("Unknown mode: " + it->second.mode); } return fit->second(it->second.params, defaultVal); } IModel* ModelRegistry::getOrCreate(const std::string& spec, float defaultVal) { std::string key = spec.empty() ? "default" : spec; auto it = instances.find(key); if (it != instances.end()) return it->second.get(); auto model = createModel(spec.empty() ? "normal_tiny" : spec, defaultVal); // Track by model name (parse base model name for composite/pair) std::string modelName = spec; auto plusPos = modelName.find('+'); if (plusPos != std::string::npos) modelName = modelName.substr(0, plusPos); auto colonPos = modelName.find(':'); if (colonPos != std::string::npos) modelName = modelName.substr(0, colonPos); byModelName[modelName].push_back(model.get()); instances[key] = std::move(model); return instances[key].get(); } std::vector ModelRegistry::findByModelName(const std::string& modelName) { auto it = byModelName.find(modelName); if (it != byModelName.end()) return it->second; return {}; } // ValvePairModel::linkPeers — defined here to avoid circular include void ValvePairModel::linkPeers(ModelRegistry& reg) { auto models = reg.findByModelName(actionModelName); if (!models.empty()) action = models[0]; } ``` - [ ] **Step 4: Commit** ```bash git add TestProject/RNG/model/CompositeModel.h TestProject/RNG/model/ModelRegistry.h \ TestProject/RNG/model/ModelRegistry.cc git commit -m "feat: add ModelRegistry with JSON loading and composite model" ``` --- ### Task 8: 重构 Generator 去除硬编码 **Files:** - Modify: `TestProject/RNG/Generator.h` - Modify: `TestProject/RNG/Generator.cc` - [ ] **Step 1: 更新 Generator.h — 添加 ModelRegistry 成员** 将现有 `Generator.h` 的内容替换为: ```cpp #pragma once #include #include #include #include #include #include #include #include #include #include #include using namespace std; class Generator { public: Generator(); ~Generator(); bool wtite_in_shm(int event_no); private: std::unique_ptr logger_; BinaryTele binary_tele{CMemVar::Const()->event_eis_start, "T_LOV_FDAAITEM"}; map*> m_mapfix; chrono::system_clock::time_point stime; ModelRegistry& registry; }; ``` - [ ] **Step 2: 重写 Generator.cc — 去掉全局 CSV 变量和硬编码 if-else** 将现有 `Generator.cc` 的内容替换为: ```cpp #include #include #include #include #include #include #include #include "mix_cc/debug/pre_define.h" using namespace std; using namespace chrono; Generator::Generator() { stime = chrono::system_clock::now(); logger_ = make_unique("Generator"); registry = ModelRegistry::instance(); } Generator::~Generator() { for (auto& it : m_mapfix) { if (it.second != nullptr) { delete it.second; } } } bool Generator::wtite_in_shm(int event_no) { try { if (m_mapfix.find(event_no) == m_mapfix.end()) { m_mapfix.insert( make_pair(event_no, new CMemFix(to_string(event_no), TEL_CACHE_SIZE))); } binary_tele.ReBuild(event_no); int size = binary_tele.size(); size_t data_index = ((chrono::system_clock::now() - stime).count() / (size_t)pow(10, 6)) / 20; for (int i = 0; i < size; i++) { const char* spec = binary_tele[i].tables[1]; string specStr = (spec != nullptr && strlen(spec) > 0) ? string(spec) : ""; float defaultVal = atof(binary_tele[i].defaultValue); IModel* model = registry.getOrCreate(specStr, defaultVal); if (binary_tele[i].type[0] == 'b') { binary_tele[i] = model->evaluateBool(data_index) ? 1.0f : 0.0f; } else { binary_tele[i] = model->evaluate(data_index); } } char* buff = binary_tele.GetTeleData(); m_mapfix[event_no]->push((PLC_DATA*)buff); return true; } catch (const std::exception& e) { logger_->Error() << "wtite_in_shm Error!" << e.what() << std::endl; return false; } } ``` - [ ] **Step 3: Commit** ```bash git add TestProject/RNG/Generator.h TestProject/RNG/Generator.cc git commit -m "refactor: replace hardcoded signal mappings with ModelRegistry" ``` --- ### Task 9: 更新 RNG 启动流程加载配置 + 链接 valve_pair **Files:** - Modify: `TestProject/RNG/RNG.h` - Modify: `TestProject/RNG/RNG.cc` - [ ] **Step 1: 更新 RNG.cc — 在 start() 中加载 rng_models.json** 修改 `RNG::start()`(文件 `TestProject/RNG/RNG.cc`),在 `con_mag_->dbLogin()` 之后添加一行: 原始 code: ```cpp int RNG::start() { logger_->Info() << "-------RNG::start-------" << std::endl; con_mag_ = std::make_shared(); con_mag_->dbLogin(); try { auto module_name = name(); RNG_server = new RNGICEI(); this->add(string("baosight/") + name(), RNG_server); ``` 替换为: ```cpp int RNG::start() { logger_->Info() << "-------RNG::start-------" << std::endl; con_mag_ = std::make_shared(); con_mag_->dbLogin(); ModelRegistry::instance().loadModels("/users/dsc/code/TestProject/RNG/json/rng_models.json"); try { auto module_name = name(); RNG_server = new RNGICEI(); this->add(string("baosight/") + name(), RNG_server); ``` 同时在 RNG.cc 顶部添加 include: ```cpp #include ``` - [ ] **Step 2: 提交** ```bash git add TestProject/RNG/RNG.cc git commit -m "feat: load rng_models.json on startup" ``` - [ ] **Step 3: 在 Generator::wtite_in_shm 中添加 valve_pair linkPeers 调用** Generator 首次为 event_no 创建所有 model 实例后需要 link。修改 `Generator.cc`: 在 `for (int i = 0; i < size; i++)` 循环**之前**添加一次 link 循环: ```cpp // First pass: create all models, then link valve_pair models for (int i = 0; i < size; i++) { const char* spec = binary_tele[i].tables[1]; string specStr = (spec != nullptr && strlen(spec) > 0) ? string(spec) : ""; float defaultVal = atof(binary_tele[i].defaultValue); IModel* model = registry.getOrCreate(specStr, defaultVal); model->linkPeers(registry); } // Second pass: evaluate for (int i = 0; i < size; i++) { const char* spec = binary_tele[i].tables[1]; string specStr = (spec != nullptr && strlen(spec) > 0) ? string(spec) : ""; float defaultVal = atof(binary_tele[i].defaultValue); IModel* model = registry.getOrCreate(specStr, defaultVal); if (binary_tele[i].type[0] == 'b') { binary_tele[i] = model->evaluateBool(data_index) ? 1.0f : 0.0f; } else { binary_tele[i] = model->evaluate(data_index); } } ``` - [ ] **Step 4: 提交** ```bash git add TestProject/RNG/Generator.cc git commit -m "feat: link valve_pair action models before evaluation" ``` --- ### Task 10: 更新 CMakeLists.txt **Files:** - Modify: `TestProject/RNG/CMakeLists.txt` - [ ] **Step 1: 添加 model/ 目录的源文件** 在 `aux_source_directory(./ DIR_ROOT)` 之后添加: ```cmake aux_source_directory(./model MODEL_DIR) ``` 在 `add_executable(RNG ${DIR_ROOT})` 中添加 `${MODEL_DIR}`: ```cmake add_executable( RNG ${DIR_ROOT} ${MODEL_DIR} ) ``` - [ ] **Step 2: 验证 CMake 变更** ```bash cd TestProject/RNG/build && cmake .. -DCMAKE_BUILD_TYPE=Release # 预期: Configuring done, 无错误 ``` - [ ] **Step 3: Commit** ```bash git add TestProject/RNG/CMakeLists.txt git commit -m "build: add model/ source directory to CMake" ``` --- ### Task 11: 清理旧的未使用文件 **Files:** - Remove references: `TestProject/RNG/BaseData.h` (不再被任何文件引用) - [ ] **Step 1: 验证 BaseData.h 无引用** ```bash grep -r "BaseData" TestProject/RNG/ --include="*.cc" --include="*.h" # 预期: 无匹配(所有引用在 Generator.cc 重构中已移除) ``` - [ ] **Step 2: 删除 BaseData.h** ```bash git rm TestProject/RNG/BaseData.h ``` - [ ] **Step 3: Commit** ```bash git commit -m "chore: remove unused BaseData.h" ``` --- ## 实现顺序总结 ``` Task 1 (json config) ──┐ Task 2 (IModel interface) ──┤ 基础设施,可并行 Task 3 (6 analog models) ──┤ Task 4 (CsvReplayModel) ──┤ Task 5 (3 boolean models) ──┤ Task 6 (ValvePairModel) ──┤ Task 7 (ModelRegistry) ──┘ ← 依赖 Task 2-6 Task 8 (refactor Generator) ──── ← 依赖 Task 7 Task 9 (RNG startup + link) ──── ← 依赖 Task 8 Task 10 (CMakeLists) ──── ← 依赖 Task 7 (需要 model/ModelRegistry.cc 存在) Task 11 (cleanup) ──── ← 最后 ``` 每个 Task 提交一次,编译验证在 Linux 环境进行(本机无编译环境)。