• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 18062081503

27 Sep 2025 03:59PM UTC coverage: 70.089% (+0.3%) from 69.825%
18062081503

push

github

paulmthompson
missing time should return -1 instead of 0

10 of 10 new or added lines in 2 files covered. (100.0%)

76 existing lines in 1 file now uncovered.

43707 of 62359 relevant lines covered (70.09%)

1128.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.38
/src/DataManager/utils/TableView/ComputerRegistry.cpp
1
#include "ComputerRegistry.hpp"
2

3
#include "Lines/Line_Data.hpp"
4
#include "Points/Point_Data.hpp"
5
#include "adapters/LineDataAdapter.h"
6
#include "adapters/PointComponentAdapter.h"
7
#include "computers/AnalogSliceGathererComputer.h"
8
#include "computers/AnalogTimestampOffsetsMultiComputer.h"
9
#include "computers/EventInIntervalComputer.h"
10
#include "computers/IntervalOverlapComputer.h"
11
#include "computers/IntervalPropertyComputer.h"
12
#include "computers/IntervalReductionComputer.h"
13
#include "computers/LineSamplingMultiComputer.h"
14
#include "computers/LineTimestampComputer.h"
15
#include "computers/TimestampInIntervalComputer.h"
16
#include "computers/TimestampValueComputer.h"
17
#include "interfaces/IEventSource.h"
18
#include "interfaces/ILineSource.h"
19

20
#include <iostream>
21
#include <optional>
22
#include <set>
23
#include <sstream>
24

25
IParameterDescriptor::IParameterDescriptor() = default;
2,325✔
26

27
IParameterDescriptor::~IParameterDescriptor() = default;
2,325✔
28

29
ComputerParameterInfo::ComputerParameterInfo()
×
30
    : name(),
×
31
      description(),
×
32
      type(typeid(void)),
×
33
      isRequired(false),
×
UNCOV
34
      defaultValue() {}
×
35

36
ComputerParameterInfo::ComputerParameterInfo(std::string name_, std::string description_, std::type_index type_, bool required, std::string defaultValue_)
×
37
    : name(std::move(name_)),
×
38
      description(std::move(description_)),
×
39
      type(type_),
×
40
      isRequired(required),
×
UNCOV
41
      defaultValue(std::move(defaultValue_)) {}
×
42

UNCOV
43
ComputerParameterInfo::~ComputerParameterInfo() = default;
×
44

45
ComputerRegistry::ComputerRegistry() {
345✔
46
    //std::cout << "Initializing Computer Registry..." << std::endl;
47

48
    registerBuiltInComputers();
345✔
49
    registerBuiltInAdapters();
345✔
50

51
    computeComputerMappings();
345✔
52
    computeAdapterMappings();
345✔
53

54
    /*
55
    std::cout << "Computer Registry Initialized with " 
56
              << all_computers_.size() << " computers and " 
57
              << all_adapters_.size() << " adapters." << std::endl;
58
    */
59
}
345✔
60

61
std::vector<ComputerInfo> ComputerRegistry::getAvailableComputers(
519✔
62
        RowSelectorType rowSelectorType,
63
        DataSourceVariant const & dataSource) const {
64

65
    auto sourceTypeIndex = getSourceTypeIndex(dataSource);
519✔
66
    auto key = std::make_pair(rowSelectorType, sourceTypeIndex);
519✔
67

68
    auto it = selector_source_to_computers_.find(key);
519✔
69
    if (it != selector_source_to_computers_.end()) {
519✔
70
        std::vector<ComputerInfo> result;
519✔
71
        result.reserve(it->second.size());
519✔
72

73
        for (auto const * computerInfo: it->second) {
3,215✔
74
            result.push_back(*computerInfo);
2,696✔
75
        }
76

77
        return result;
519✔
78
    }
519✔
79

UNCOV
80
    return {};// No computers available for this combination
×
81
}
82

83
std::vector<AdapterInfo> ComputerRegistry::getAvailableAdapters(std::type_index dataType) const {
×
84
    auto it = input_type_to_adapters_.find(dataType);
×
85
    if (it != input_type_to_adapters_.end()) {
×
86
        std::vector<AdapterInfo> result;
×
UNCOV
87
        result.reserve(it->second.size());
×
88

89
        for (auto const * adapterInfo: it->second) {
×
UNCOV
90
            result.push_back(*adapterInfo);
×
91
        }
92

93
        return result;
×
UNCOV
94
    }
×
95

UNCOV
96
    return {};// No adapters available for this type
×
97
}
98

99
std::unique_ptr<IComputerBase> ComputerRegistry::createComputer(
337✔
100
        std::string const & computerName,
101
        DataSourceVariant const & dataSource,
102
        std::map<std::string, std::string> const & parameters) const {
103

104
    auto it = computer_factories_.find(computerName);
337✔
105
    if (it != computer_factories_.end()) {
337✔
106
        try {
107
            return it->second(dataSource, parameters);
337✔
108
        } catch (std::exception const & e) {
1✔
109
            std::cerr << "Error creating computer '" << computerName << "': " << e.what() << std::endl;
1✔
110
            return nullptr;
1✔
111
        }
1✔
112
    }
113

114
    std::cerr << "Computer '" << computerName << "' not found in registry." << std::endl;
×
UNCOV
115
    return nullptr;
×
116
}
117

118
std::unique_ptr<IComputerBase> ComputerRegistry::createMultiComputer(
15✔
119
        std::string const & computerName,
120
        DataSourceVariant const & dataSource,
121
        std::map<std::string, std::string> const & parameters) const {
122
    auto it = multi_computer_factories_.find(computerName);
15✔
123
    if (it != multi_computer_factories_.end()) {
15✔
124
        try {
125
            return it->second(dataSource, parameters);
15✔
126
        } catch (std::exception const & e) {
×
127
            std::cerr << "Error creating multi-computer '" << computerName << "': " << e.what() << std::endl;
×
128
            return nullptr;
×
UNCOV
129
        }
×
130
    }
131
    std::cerr << "Multi-computer '" << computerName << "' not found in registry." << std::endl;
×
UNCOV
132
    return nullptr;
×
133
}
134

135
DataSourceVariant ComputerRegistry::createAdapter(
2✔
136
        std::string const & adapterName,
137
        std::shared_ptr<void> const & sourceData,
138
        std::shared_ptr<TimeFrame> const & timeFrame,
139
        std::string const & name,
140
        std::map<std::string, std::string> const & parameters) const {
141

142
    auto it = adapter_factories_.find(adapterName);
2✔
143
    if (it != adapter_factories_.end()) {
2✔
144
        try {
145
            return it->second(sourceData, timeFrame, name, parameters);
2✔
146
        } catch (std::exception const & e) {
×
147
            std::cerr << "Error creating adapter '" << adapterName << "': " << e.what() << std::endl;
×
148
            return DataSourceVariant{};
×
UNCOV
149
        }
×
150
    }
151

152
    std::cerr << "Adapter '" << adapterName << "' not found in registry." << std::endl;
×
UNCOV
153
    return DataSourceVariant{};
×
154
}
155

156
ComputerInfo const * ComputerRegistry::findComputerInfo(std::string const & computerName) const {
489✔
157
    auto it = name_to_computer_.find(computerName);
489✔
158
    return (it != name_to_computer_.end()) ? it->second : nullptr;
978✔
159
}
160

161
AdapterInfo const * ComputerRegistry::findAdapterInfo(std::string const & adapterName) const {
×
162
    auto it = name_to_adapter_.find(adapterName);
×
UNCOV
163
    return (it != name_to_adapter_.end()) ? it->second : nullptr;
×
164
}
165

166
std::vector<std::string> ComputerRegistry::getAllComputerNames() const {
×
167
    std::vector<std::string> names;
×
UNCOV
168
    names.reserve(all_computers_.size());
×
169

170
    for (auto const & info: all_computers_) {
×
UNCOV
171
        names.push_back(info.name);
×
172
    }
173

174
    return names;
×
UNCOV
175
}
×
176

177
std::vector<std::string> ComputerRegistry::getAllAdapterNames() const {
1✔
178
    std::vector<std::string> names;
1✔
179
    names.reserve(all_adapters_.size());
1✔
180

181
    for (auto const & info: all_adapters_) {
4✔
182
        names.push_back(info.name);
3✔
183
    }
184

185
    return names;
1✔
UNCOV
186
}
×
187

188
std::vector<std::type_index> ComputerRegistry::getAvailableOutputTypes() const {
×
UNCOV
189
    std::set<std::type_index> unique_types;
×
190

191
    for (auto const & info: all_computers_) {
×
UNCOV
192
        unique_types.insert(info.outputType);
×
193
    }
194

195
    return std::vector<std::type_index>(unique_types.begin(), unique_types.end());
×
UNCOV
196
}
×
197

198
std::map<std::type_index, std::string> ComputerRegistry::getOutputTypeNames() const {
×
UNCOV
199
    std::map<std::type_index, std::string> type_names;
×
200

201
    for (auto const & info: all_computers_) {
×
UNCOV
202
        type_names[info.outputType] = info.outputTypeName;
×
203
    }
204

205
    return type_names;
×
UNCOV
206
}
×
207

UNCOV
208
std::vector<ComputerInfo> ComputerRegistry::getComputersByOutputType(
×
209
        std::type_index outputType,
210
        std::optional<RowSelectorType> rowSelectorType,
211
        std::optional<std::type_index> sourceType) const {
UNCOV
212
    std::vector<ComputerInfo> result;
×
213

214
    for (auto const & info: all_computers_) {
×
215
        if (info.outputType != outputType) {
×
UNCOV
216
            continue;
×
217
        }
218

219
        if (rowSelectorType && info.requiredRowSelector != *rowSelectorType) {
×
UNCOV
220
            continue;
×
221
        }
222

223
        if (sourceType && info.requiredSourceType != *sourceType) {
×
UNCOV
224
            continue;
×
225
        }
226

UNCOV
227
        result.push_back(info);
×
228
    }
229

230
    return result;
×
UNCOV
231
}
×
232

233
bool ComputerRegistry::isVectorComputer(std::string const & computerName) const {
×
234
    auto info = findComputerInfo(computerName);
×
UNCOV
235
    return info ? info->isVectorType : false;
×
236
}
237

238
std::type_index ComputerRegistry::getElementType(std::string const & computerName) const {
×
239
    auto info = findComputerInfo(computerName);
×
UNCOV
240
    return info ? info->elementType : typeid(void);
×
241
}
242

243
void ComputerRegistry::registerComputer(ComputerInfo info, ComputerFactory factory) {
7,245✔
244
    std::string const name = info.name;// Copy the name before moving
7,245✔
245

246
    if (name_to_computer_.count(name)) {
7,245✔
247
        std::cerr << "Warning: Computer '" << name << "' already registered." << std::endl;
×
UNCOV
248
        return;
×
249
    }
250

251
    /*
252
    std::cout << "Registering computer: " << name 
253
              << " (Row selector: " << static_cast<int>(info.requiredRowSelector)
254
              << ", Source type: " << info.requiredSourceType.name() << ")" << std::endl;
255
    */
256
    all_computers_.push_back(std::move(info));
7,245✔
257
    ComputerInfo const * infoPtr = &all_computers_.back();
7,245✔
258

259
    name_to_computer_[name] = infoPtr;
7,245✔
260
    computer_factories_[name] = std::move(factory);
7,245✔
261
}
7,245✔
262

263
void ComputerRegistry::registerAdapter(AdapterInfo info, AdapterFactory factory) {
1,035✔
264
    std::string const name = info.name;// Copy the name before moving
1,035✔
265

266
    if (name_to_adapter_.count(name)) {
1,035✔
267
        std::cerr << "Warning: Adapter '" << name << "' already registered." << std::endl;
×
UNCOV
268
        return;
×
269
    }
270

271
    /*
272
    std::cout << "Registering adapter: " << name 
273
              << " (Input type: " << info.inputType.name()
274
              << ", Output type: " << info.outputType.name() << ")" << std::endl;
275
    */
276
    all_adapters_.push_back(std::move(info));
1,035✔
277
    AdapterInfo const * infoPtr = &all_adapters_.back();
1,035✔
278

279
    name_to_adapter_[name] = infoPtr;
1,035✔
280
    adapter_factories_[name] = std::move(factory);
1,035✔
281
}
1,035✔
282

283
void ComputerRegistry::registerMultiComputer(ComputerInfo info, MultiComputerFactory factory) {
690✔
284
    std::string const name = info.name;
690✔
285
    if (name_to_computer_.count(name) || multi_computer_factories_.count(name)) {
690✔
286
        std::cerr << "Warning: Computer '" << name << "' already registered." << std::endl;
×
UNCOV
287
        return;
×
288
    }
289

290
    info.isMultiOutput = true;
690✔
291

292
    /*
293
    std::cout << "Registering multi-output computer: " << name
294
              << " (Row selector: " << static_cast<int>(info.requiredRowSelector)
295
              << ", Source type: " << info.requiredSourceType.name() << ")" << std::endl;
296
    */
297
    all_computers_.push_back(std::move(info));
690✔
298
    ComputerInfo const * infoPtr = &all_computers_.back();
690✔
299

300
    name_to_computer_[name] = infoPtr;
690✔
301
    multi_computer_factories_[name] = std::move(factory);
690✔
302
}
690✔
303

304
void ComputerRegistry::computeComputerMappings() {
345✔
305
    //std::cout << "Computing computer mappings..." << std::endl;
306
    selector_source_to_computers_.clear();
345✔
307

308
    for (auto const & info: all_computers_) {
8,280✔
309
        auto key = std::make_pair(info.requiredRowSelector, info.requiredSourceType);
7,935✔
310
        selector_source_to_computers_[key].push_back(&info);
7,935✔
311
    }
312

313
    //std::cout << "Finished computing computer mappings." << std::endl;
314
}
345✔
315

316
void ComputerRegistry::computeAdapterMappings() {
345✔
317
    //std::cout << "Computing adapter mappings..." << std::endl;
318
    input_type_to_adapters_.clear();
345✔
319

320
    for (auto const & info: all_adapters_) {
1,380✔
321
        input_type_to_adapters_[info.inputType].push_back(&info);
1,035✔
322
    }
323

324
    //std::cout << "Finished computing adapter mappings." << std::endl;
325
}
345✔
326

327
std::type_index ComputerRegistry::getSourceTypeIndex(DataSourceVariant const & source) const {
519✔
328
    return std::visit([](auto const & src) -> std::type_index {
1,557✔
329
        return typeid(src);
519✔
330
    },
331
                      source);
1,038✔
332
}
333

334
void ComputerRegistry::registerBuiltInComputers() {
345✔
335
    //std::cout << "Registering built-in computers..." << std::endl;
336

337
    // IntervalReductionComputer - Mean
338
    {
339
        ComputerInfo info("Interval Mean",
345✔
340
                          "Calculate mean value over intervals",
341
                          typeid(double),
342
                          "double",
343
                          RowSelectorType::IntervalBased,
344
                          typeid(std::shared_ptr<IAnalogSource>));
2,415✔
345

346
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
347
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
348
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
6✔
349
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Mean);
6✔
350
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
6✔
351
            }
6✔
UNCOV
352
            return nullptr;
×
353
        };
345✔
354

355
        registerComputer(std::move(info), std::move(factory));
345✔
356
    }
345✔
357

358
    // IntervalReductionComputer - Max
359
    {
360
        ComputerInfo info("Interval Max",
345✔
361
                          "Calculate maximum value over intervals",
362
                          typeid(double),
363
                          "double",
364
                          RowSelectorType::IntervalBased,
365
                          typeid(std::shared_ptr<IAnalogSource>));
2,415✔
366

367
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
368
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
369
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
370
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Max);
2✔
371
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
2✔
372
            }
2✔
UNCOV
373
            return nullptr;
×
374
        };
345✔
375

376
        registerComputer(std::move(info), std::move(factory));
345✔
377
    }
345✔
378

379
    // IntervalReductionComputer - Min
380
    {
381
        ComputerInfo info("Interval Min",
345✔
382
                          "Calculate minimum value over intervals",
383
                          typeid(double),
384
                          "double",
385
                          RowSelectorType::IntervalBased,
386
                          typeid(std::shared_ptr<IAnalogSource>));
2,415✔
387

388
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
389
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
390
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
1✔
391
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Min);
1✔
392
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
1✔
393
            }
1✔
UNCOV
394
            return nullptr;
×
395
        };
345✔
396

397
        registerComputer(std::move(info), std::move(factory));
345✔
398
    }
345✔
399

400
    // IntervalReductionComputer - StdDev
401
    {
402
        ComputerInfo info("Interval Standard Deviation",
345✔
403
                          "Calculate standard deviation over intervals",
404
                          typeid(double),
405
                          "double",
406
                          RowSelectorType::IntervalBased,
407
                          typeid(std::shared_ptr<IAnalogSource>));
2,415✔
408

409
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
410
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
411
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
412
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::StdDev);
2✔
413
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
2✔
414
            }
2✔
UNCOV
415
            return nullptr;
×
416
        };
345✔
417

418
        registerComputer(std::move(info), std::move(factory));
345✔
419
    }
345✔
420

421
    // IntervalReductionComputer - Sum
422
    {
423
        ComputerInfo info("Interval Sum",
345✔
424
                          "Calculate sum of values over intervals",
425
                          typeid(double),
426
                          "double",
427
                          RowSelectorType::IntervalBased,
428
                          typeid(std::shared_ptr<IAnalogSource>));
2,415✔
429

430
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
431
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
432
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
433
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Sum);
2✔
434
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
2✔
435
            }
2✔
UNCOV
436
            return nullptr;
×
437
        };
345✔
438

439
        registerComputer(std::move(info), std::move(factory));
345✔
440
    }
345✔
441

442
    // IntervalReductionComputer - Count
443
    {
444
        ComputerInfo info("Interval Count",
345✔
445
                          "Count number of values over intervals",
446
                          typeid(double),
447
                          "double",
448
                          RowSelectorType::IntervalBased,
449
                          typeid(std::shared_ptr<IAnalogSource>));
2,415✔
450

451
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
452
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
453
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
1✔
454
                auto computer = std::make_unique<IntervalReductionComputer>(*analogSrc, ReductionType::Count);
1✔
455
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
1✔
456
            }
1✔
UNCOV
457
            return nullptr;
×
458
        };
345✔
459

460
        registerComputer(std::move(info), std::move(factory));
345✔
461
    }
345✔
462

463
    // EventInIntervalComputer - Presence
464
    {
465
        ComputerInfo info("Event Presence",
345✔
466
                          "Check if events exist in intervals",
467
                          typeid(bool),
468
                          "bool",
469
                          RowSelectorType::IntervalBased,
470
                          typeid(std::shared_ptr<IEventSource>));
2,415✔
471

472
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
473
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
474
            if (auto eventSrc = std::get_if<std::shared_ptr<IEventSource>>(&source)) {
118✔
475
                auto computer = std::make_unique<EventInIntervalComputer<bool>>(*eventSrc, EventOperation::Presence, (*eventSrc)->getName());
118✔
476
                return std::make_unique<ComputerWrapper<bool>>(std::move(computer));
118✔
477
            }
118✔
UNCOV
478
            return nullptr;
×
479
        };
345✔
480

481
        registerComputer(std::move(info), std::move(factory));
345✔
482
    }
345✔
483

484
    // EventInIntervalComputer - Count
485
    {
486
        ComputerInfo info("Event Count",
345✔
487
                          "Count events in intervals",
488
                          typeid(int),
489
                          "int",
490
                          RowSelectorType::IntervalBased,
491
                          typeid(std::shared_ptr<IEventSource>));
2,415✔
492

493
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
494
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
495
            if (auto eventSrc = std::get_if<std::shared_ptr<IEventSource>>(&source)) {
97✔
496
                auto computer = std::make_unique<EventInIntervalComputer<int>>(*eventSrc, EventOperation::Count, (*eventSrc)->getName());
97✔
497
                return std::make_unique<ComputerWrapper<int>>(std::move(computer));
97✔
498
            }
97✔
UNCOV
499
            return nullptr;
×
500
        };
345✔
501

502
        registerComputer(std::move(info), std::move(factory));
345✔
503
    }
345✔
504

505
    // IntervalPropertyComputer - Start
506
    {
507
        ComputerInfo info("Interval Start",
345✔
508
                          "Get the start time of intervals",
509
                          typeid(double),
510
                          "double",
511
                          RowSelectorType::IntervalBased,
512
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
513

514
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
515
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
516
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
15✔
517
                auto computer = std::make_unique<IntervalPropertyComputer<double>>(*intervalSrc, IntervalProperty::Start, (*intervalSrc)->getName());
15✔
518
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
15✔
519
            }
15✔
UNCOV
520
            return nullptr;
×
521
        };
345✔
522

523
        registerComputer(std::move(info), std::move(factory));
345✔
524
    }
345✔
525

526
    // IntervalPropertyComputer - End
527
    {
528
        ComputerInfo info("Interval End",
345✔
529
                          "Get the end time of intervals",
530
                          typeid(double),
531
                          "double",
532
                          RowSelectorType::IntervalBased,
533
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
534

535
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
536
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
537
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
12✔
538
                auto computer = std::make_unique<IntervalPropertyComputer<double>>(*intervalSrc, IntervalProperty::End, (*intervalSrc)->getName());
12✔
539
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
12✔
540
            }
12✔
UNCOV
541
            return nullptr;
×
542
        };
345✔
543

544
        registerComputer(std::move(info), std::move(factory));
345✔
545
    }
345✔
546

547
    // IntervalPropertyComputer - Duration
548
    {
549
        ComputerInfo info("Interval Duration",
345✔
550
                          "Get the duration of intervals",
551
                          typeid(double),
552
                          "double",
553
                          RowSelectorType::IntervalBased,
554
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
555

556
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
557
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
558
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
12✔
559
                auto computer = std::make_unique<IntervalPropertyComputer<double>>(*intervalSrc, IntervalProperty::Duration, (*intervalSrc)->getName());
12✔
560
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
12✔
561
            }
12✔
UNCOV
562
            return nullptr;
×
563
        };
345✔
564

565
        registerComputer(std::move(info), std::move(factory));
345✔
566
    }
345✔
567

568
    // EventInIntervalComputer - Gather with parameter
569
    {
570
        // Create parameter descriptors
571
        std::vector<std::unique_ptr<IParameterDescriptor>> paramDescriptors;
345✔
572
        paramDescriptors.push_back(std::make_unique<EnumParameterDescriptor>(
1,035✔
573
                "mode", "Gathering mode for event times",
574
                std::vector<std::string>{"absolute", "centered"},
2,415✔
575
                "absolute", true));
690✔
576

577
        ComputerInfo info("Event Gather",
345✔
578
                          "Gather event times within intervals",
579
                          typeid(std::vector<float>),
580
                          "std::vector<float>",
581
                          typeid(float),
582
                          "float",
583
                          RowSelectorType::IntervalBased,
584
                          typeid(std::shared_ptr<IEventSource>),
585
                          std::move(paramDescriptors));
3,105✔
586

587
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
588
                                     std::map<std::string, std::string> const & parameters) -> std::unique_ptr<IComputerBase> {
589
            if (auto eventSrc = std::get_if<std::shared_ptr<IEventSource>>(&source)) {
9✔
590
                // Parse the mode parameter
591
                EventOperation operation = EventOperation::Gather;// default
9✔
592
                auto mode_it = parameters.find("mode");
27✔
593
                if (mode_it != parameters.end()) {
9✔
594
                    if (mode_it->second == "centered") {
5✔
595
                        operation = EventOperation::Gather_Center;
2✔
596
                    } else {
597
                        operation = EventOperation::Gather;
3✔
598
                    }
599
                }
600

601
                auto computer = std::make_unique<EventInIntervalComputer<std::vector<float>>>(
9✔
602
                        *eventSrc, operation, (*eventSrc)->getName());
9✔
603
                return std::make_unique<ComputerWrapper<std::vector<float>>>(std::move(computer));
9✔
604
            }
9✔
UNCOV
605
            return nullptr;
×
606
        };
345✔
607

608
        registerComputer(std::move(info), std::move(factory));
345✔
609
    }
345✔
610

611
    // TimestampValueComputer - Extract values at specific timestamps
612
    {
613
        ComputerInfo info("Timestamp Value",
345✔
614
                          "Extract analog signal values at specific timestamps",
615
                          typeid(double),
616
                          "double",
617
                          RowSelectorType::Timestamp,
618
                          typeid(std::shared_ptr<IAnalogSource>));
2,415✔
619

620
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
621
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
622
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
30✔
623
                auto computer = std::make_unique<TimestampValueComputer>(*analogSrc);
30✔
624
                return std::make_unique<ComputerWrapper<double>>(std::move(computer));
29✔
625
            }
29✔
UNCOV
626
            return nullptr;
×
627
        };
345✔
628

629
        registerComputer(std::move(info), std::move(factory));
345✔
630
    }
345✔
631

632
    // AnalogTimestampOffsetsMultiComputer - multi-output sampling at offsets
633
    {
634
        std::vector<std::unique_ptr<IParameterDescriptor>> paramDescriptors;
345✔
635
        // Offsets provided as comma-separated integers, e.g., "-2,-1,0,1"
636
        // Use a simple text parameter via IParameterDescriptor base replacement: reuse IntParameterDescriptor for a hint?
637
        // We'll not enforce via UI here; consumers pass string list in parameters["offsets"].
638

639
        ComputerInfo info("Analog Timestamp Offsets",
345✔
640
                          "Sample analog values at specified integer offsets from each timestamp",
641
                          typeid(double),
642
                          "double",
643
                          RowSelectorType::Timestamp,
644
                          typeid(std::shared_ptr<IAnalogSource>),
645
                          std::move(paramDescriptors));
2,415✔
646
        info.isMultiOutput = true;
345✔
647
        info.makeOutputSuffixes = [](std::map<std::string, std::string> const & parameters) {
690✔
648
            std::vector<std::string> suffixes;
×
649
            auto it = parameters.find("offsets");
×
UNCOV
650
            if (it == parameters.end() || it->second.empty()) {
×
651
                // default single output at t+0
652
                suffixes.emplace_back(".t+0");
×
UNCOV
653
                return suffixes;
×
654
            }
655
            std::string const & csv = it->second;
×
656
            size_t pos = 0;
×
657
            while (pos < csv.size()) {
×
658
                size_t next = csv.find(',', pos);
×
UNCOV
659
                std::string token = csv.substr(pos, next == std::string::npos ? std::string::npos : next - pos);
×
660
                // trim spaces
661
                size_t beg = token.find_first_not_of(" \t");
×
662
                size_t end = token.find_last_not_of(" \t");
×
663
                if (beg != std::string::npos) token = token.substr(beg, end - beg + 1);
×
UNCOV
664
                int off = 0;
×
665
                try {
666
                    off = std::stoi(token);
×
667
                } catch (...) { off = 0; }
×
668
                if (off == 0) suffixes.emplace_back(".t+0");
×
669
                else if (off > 0)
×
UNCOV
670
                    suffixes.emplace_back(".t+" + std::to_string(off));
×
671
                else
672
                    suffixes.emplace_back(".t" + std::to_string(off));
×
673
                if (next == std::string::npos) break;
×
674
                pos = next + 1;
×
675
            }
×
676
            if (suffixes.empty()) suffixes.emplace_back(".t+0");
×
UNCOV
677
            return suffixes;
×
678
        };
345✔
679

680
        MultiComputerFactory factory = [](DataSourceVariant const & source,
690✔
681
                                          std::map<std::string, std::string> const & parameters) -> std::unique_ptr<IComputerBase> {
682
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
683
                // parse offsets
684
                std::vector<int> offsets;
2✔
685
                auto it = parameters.find("offsets");
6✔
686
                if (it != parameters.end()) {
2✔
687
                    std::string const & csv = it->second;
2✔
688
                    size_t pos = 0;
2✔
689
                    while (pos < csv.size()) {
6✔
690
                        size_t next = csv.find(',', pos);
6✔
691
                        std::string token = csv.substr(pos, next == std::string::npos ? std::string::npos : next - pos);
6✔
692
                        size_t beg = token.find_first_not_of(" \t");
6✔
693
                        size_t end = token.find_last_not_of(" \t");
6✔
694
                        if (beg != std::string::npos) token = token.substr(beg, end - beg + 1);
6✔
695
                        try {
696
                            offsets.push_back(std::stoi(token));
6✔
UNCOV
697
                        } catch (...) { offsets.push_back(0); }
×
698
                        if (next == std::string::npos) break;
6✔
699
                        pos = next + 1;
4✔
700
                    }
6✔
701
                }
702
                if (offsets.empty()) offsets.push_back(0);
2✔
703
                auto comp = std::make_unique<AnalogTimestampOffsetsMultiComputer>(*analogSrc, (*analogSrc)->getName(), offsets);
2✔
704
                return std::make_unique<MultiComputerWrapper<double>>(std::move(comp));
2✔
705
            }
2✔
UNCOV
706
            return nullptr;
×
707
        };
345✔
708

709
        registerMultiComputer(std::move(info), std::move(factory));
345✔
710
    }
345✔
711

712
    // TimestampInIntervalComputer - bool for timestamps inside digital intervals
713
    {
714
        ComputerInfo info("Timestamp In Interval",
345✔
715
                          "Returns true if timestamp lies within any digital interval",
716
                          typeid(bool),
717
                          "bool",
718
                          RowSelectorType::Timestamp,
719
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
720

721
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
722
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
723
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
6✔
724
                auto comp = std::make_unique<TimestampInIntervalComputer>(*intervalSrc, (*intervalSrc)->getName());
6✔
725
                return std::make_unique<ComputerWrapper<bool>>(std::move(comp));
6✔
726
            }
6✔
UNCOV
727
            return nullptr;
×
728
        };
345✔
729

730
        registerComputer(std::move(info), std::move(factory));
345✔
731
    }
345✔
732

733
    // LineSamplingMultiComputer - sample x/y at equally spaced segments along line
734
    {
735
        std::vector<std::unique_ptr<IParameterDescriptor>> paramDescriptors;
345✔
736
        paramDescriptors.push_back(std::make_unique<IntParameterDescriptor>(
1,035✔
737
                "segments", "Number of equal segments to divide the line into (generates segments+1 sample points)", 2, 1, 1000, true));
690✔
738

739
        ComputerInfo info("Line Sample XY",
345✔
740
                          "Sample line x and y at equally spaced positions",
741
                          typeid(double),
742
                          "double",
743
                          typeid(double),
744
                          "double",
745
                          RowSelectorType::Timestamp,
746
                          typeid(std::shared_ptr<ILineSource>),
747
                          std::move(paramDescriptors));
3,105✔
748
        info.isMultiOutput = true;
345✔
749
        info.makeOutputSuffixes = [](std::map<std::string, std::string> const & parameters) {
690✔
750
            int segments = 2;
×
751
            auto it = parameters.find("segments");
×
752
            if (it != parameters.end()) {
×
UNCOV
753
                segments = std::max(1, std::stoi(it->second));
×
754
            }
755
            std::vector<std::string> suffixes;
×
756
            suffixes.reserve(static_cast<size_t>((segments + 1) * 2));
×
757
            for (int i = 0; i <= segments; ++i) {
×
758
                double frac = static_cast<double>(i) / static_cast<double>(segments);
×
759
                char buf[32];
×
760
                std::snprintf(buf, sizeof(buf), "@%.3f", frac);
×
761
                suffixes.emplace_back(std::string{".x"} + buf);
×
UNCOV
762
                suffixes.emplace_back(std::string{".y"} + buf);
×
763
            }
UNCOV
764
            return suffixes;
×
765
        };
345✔
766

767
        MultiComputerFactory factory = [](DataSourceVariant const & source,
690✔
768
                                          std::map<std::string, std::string> const & parameters) -> std::unique_ptr<IComputerBase> {
769
            if (auto lineSrc = std::get_if<std::shared_ptr<ILineSource>>(&source)) {
13✔
770
                int segments = 2;
13✔
771
                auto it = parameters.find("segments");
39✔
772
                if (it != parameters.end()) {
13✔
773
                    segments = std::max(1, std::stoi(it->second));
13✔
774
                }
775
                auto comp = std::make_unique<LineSamplingMultiComputer>(*lineSrc, (*lineSrc)->getName(), (*lineSrc)->getTimeFrame(), segments);
13✔
776
                return std::make_unique<MultiComputerWrapper<double>>(std::move(comp));
13✔
777
            }
13✔
UNCOV
778
            return nullptr;
×
779
        };
345✔
780

781
        registerMultiComputer(std::move(info), std::move(factory));
345✔
782
    }
345✔
783

784
    // LineTimestampComputer - Extract timestamps from line data
785
    {
786
        ComputerInfo info("Line Timestamp",
345✔
787
                          "Extract timestamps from line data",
788
                          typeid(int64_t),
789
                          "int64_t",
790
                          RowSelectorType::Timestamp,
791
                          typeid(std::shared_ptr<ILineSource>));
2,415✔
792

793
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
794
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
795
            if (auto lineSrc = std::get_if<std::shared_ptr<ILineSource>>(&source)) {
4✔
796
                auto computer = std::make_unique<LineTimestampComputer>(*lineSrc, (*lineSrc)->getName(), (*lineSrc)->getTimeFrame());
4✔
797
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
4✔
798
            }
4✔
799
            return nullptr;
×
800
        };
345✔
801

802
        registerComputer(std::move(info), std::move(factory));
345✔
803
    }
345✔
804

805
    // IntervalOverlapComputer - AssignID operation
806
    {
807
        ComputerInfo info("Interval Overlap Assign ID",
345✔
808
                          "Find the ID of the column interval that overlaps with each row interval",
809
                          typeid(int64_t),
810
                          "int64_t",
811
                          RowSelectorType::IntervalBased,
812
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
813

814
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
815
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
816
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
7✔
817
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
7✔
818
                        *intervalSrc, IntervalOverlapOperation::AssignID, (*intervalSrc)->getName());
7✔
819
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
7✔
820
            }
7✔
821
            return nullptr;
×
822
        };
345✔
823

824
        registerComputer(std::move(info), std::move(factory));
345✔
825
    }
345✔
826

827
    // IntervalOverlapComputer - CountOverlaps operation
828
    {
829
        ComputerInfo info("Interval Overlap Count",
345✔
830
                          "Count the number of column intervals that overlap with each row interval",
831
                          typeid(int64_t),
832
                          "int64_t",
833
                          RowSelectorType::IntervalBased,
834
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
835

836
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
837
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
838
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
5✔
839
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
5✔
840
                        *intervalSrc, IntervalOverlapOperation::CountOverlaps, (*intervalSrc)->getName());
5✔
841
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
5✔
842
            }
5✔
843
            return nullptr;
×
844
        };
345✔
845

846
        registerComputer(std::move(info), std::move(factory));
345✔
847
    }
345✔
848

849
    // IntervalOverlapComputer - AssignID_Start operation
850
    {
851
        ComputerInfo info("Interval Overlap Assign Start",
345✔
852
                          "Find the start index of the column interval that overlaps with each row interval",
853
                          typeid(int64_t),
854
                          "int64_t",
855
                          RowSelectorType::IntervalBased,
856
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
857

858
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
859
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
860
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
1✔
861
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
1✔
862
                        *intervalSrc, IntervalOverlapOperation::AssignID_Start, (*intervalSrc)->getName());
1✔
863
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
1✔
864
            }
1✔
865
            return nullptr;
×
866
        };
345✔
867

868
        registerComputer(std::move(info), std::move(factory));
345✔
869
    }
345✔
870

871
    // IntervalOverlapComputer - AssignID_End operation
872
    {
873
        ComputerInfo info("Interval Overlap Assign End",
345✔
874
                          "Find the end index of the column interval that overlaps with each row interval",
875
                          typeid(int64_t),
876
                          "int64_t",
877
                          RowSelectorType::IntervalBased,
878
                          typeid(std::shared_ptr<IIntervalSource>));
2,415✔
879

880
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
881
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
882
            if (auto intervalSrc = std::get_if<std::shared_ptr<IIntervalSource>>(&source)) {
1✔
883
                auto computer = std::make_unique<IntervalOverlapComputer<int64_t>>(
1✔
884
                        *intervalSrc, IntervalOverlapOperation::AssignID_End, (*intervalSrc)->getName());
1✔
885
                return std::make_unique<ComputerWrapper<int64_t>>(std::move(computer));
1✔
886
            }
1✔
UNCOV
887
            return nullptr;
×
888
        };
345✔
889

890
        registerComputer(std::move(info), std::move(factory));
345✔
891
    }
345✔
892

893
    // AnalogSliceGathererComputer - Gather analog data slices within intervals
894
    {
895
        ComputerInfo info("Analog Slice Gatherer",
345✔
896
                          "Gather analog data slices within intervals as vectors",
897
                          typeid(std::vector<double>),
898
                          "std::vector<double>",
899
                          typeid(double),
900
                          "double",
901
                          RowSelectorType::IntervalBased,
902
                          typeid(std::shared_ptr<IAnalogSource>));
3,105✔
903

904
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
905
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
906
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
4✔
907
                auto computer = std::make_unique<AnalogSliceGathererComputer<std::vector<double>>>(*analogSrc, (*analogSrc)->getName());
4✔
908
                return std::make_unique<ComputerWrapper<std::vector<double>>>(std::move(computer));
4✔
909
            }
4✔
UNCOV
910
            return nullptr;
×
911
        };
345✔
912

913
        registerComputer(std::move(info), std::move(factory));
345✔
914
    }
345✔
915

916
    // AnalogSliceGathererComputer - Float version
917
    {
918
        ComputerInfo info("Analog Slice Gatherer Float",
345✔
919
                          "Gather analog data slices within intervals as vectors of floats",
920
                          typeid(std::vector<float>),
921
                          "std::vector<float>",
922
                          typeid(float),
923
                          "float",
924
                          RowSelectorType::IntervalBased,
925
                          typeid(std::shared_ptr<IAnalogSource>));
3,105✔
926

927
        ComputerFactory factory = [](DataSourceVariant const & source,
690✔
928
                                     std::map<std::string, std::string> const &) -> std::unique_ptr<IComputerBase> {
929
            if (auto analogSrc = std::get_if<std::shared_ptr<IAnalogSource>>(&source)) {
2✔
930
                auto computer = std::make_unique<AnalogSliceGathererComputer<std::vector<float>>>(*analogSrc, (*analogSrc)->getName());
2✔
931
                return std::make_unique<ComputerWrapper<std::vector<float>>>(std::move(computer));
2✔
932
            }
2✔
UNCOV
933
            return nullptr;
×
934
        };
345✔
935

936
        registerComputer(std::move(info), std::move(factory));
345✔
937
    }
345✔
938

939
    //std::cout << "Finished registering built-in computers." << std::endl;
940
}
1,380✔
941

942
void ComputerRegistry::registerBuiltInAdapters() {
345✔
943
    //std::cout << "Registering built-in adapters..." << std::endl;
944

945
    // PointComponentAdapter - X Component
946
    {
947
        AdapterInfo info("Point X Component",
345✔
948
                         "Extract X component from PointData as analog source",
949
                         typeid(PointData),
950
                         typeid(std::shared_ptr<IAnalogSource>));
1,725✔
951

952
        AdapterFactory factory = [](std::shared_ptr<void> const & sourceData,
690✔
953
                                    std::shared_ptr<TimeFrame> const & timeFrame,
954
                                    std::string const & name,
955
                                    std::map<std::string, std::string> const &) -> DataSourceVariant {
UNCOV
956
            if (auto pointData = std::static_pointer_cast<PointData>(sourceData)) {
×
UNCOV
957
                auto adapter = std::make_shared<PointComponentAdapter>(
×
958
                        pointData,
959
                        PointComponentAdapter::Component::X,
×
960
                        timeFrame,
UNCOV
961
                        name + "_X");
×
962
                return DataSourceVariant{std::static_pointer_cast<IAnalogSource>(adapter)};
×
UNCOV
963
            }
×
964
            return DataSourceVariant{};
×
965
        };
345✔
966

967
        registerAdapter(std::move(info), std::move(factory));
345✔
968
    }
345✔
969

970
    // PointComponentAdapter - Y Component
971
    {
972
        AdapterInfo info("Point Y Component",
345✔
973
                         "Extract Y component from PointData as analog source",
974
                         typeid(PointData),
975
                         typeid(std::shared_ptr<IAnalogSource>));
1,725✔
976

977
        AdapterFactory factory = [](std::shared_ptr<void> const & sourceData,
690✔
978
                                    std::shared_ptr<TimeFrame> const & timeFrame,
979
                                    std::string const & name,
980
                                    std::map<std::string, std::string> const &) -> DataSourceVariant {
UNCOV
981
            if (auto pointData = std::static_pointer_cast<PointData>(sourceData)) {
×
UNCOV
982
                auto adapter = std::make_shared<PointComponentAdapter>(
×
983
                        pointData,
UNCOV
984
                        PointComponentAdapter::Component::Y,
×
985
                        timeFrame,
UNCOV
986
                        name + "_Y");
×
UNCOV
987
                return DataSourceVariant{std::static_pointer_cast<IAnalogSource>(adapter)};
×
988
            }
×
UNCOV
989
            return DataSourceVariant{};
×
990
        };
345✔
991

992
        registerAdapter(std::move(info), std::move(factory));
345✔
993
    }
345✔
994

995
    // LineDataAdapter - LineData -> ILineSource
996
    {
997
        AdapterInfo info("Line Data",
345✔
998
                         "Expose LineData as ILineSource",
999
                         typeid(LineData),
1000
                         typeid(std::shared_ptr<ILineSource>));
1,725✔
1001

1002
        AdapterFactory factory = [](std::shared_ptr<void> const & sourceData,
690✔
1003
                                    std::shared_ptr<TimeFrame> const & timeFrame,
1004
                                    std::string const & name,
1005
                                    std::map<std::string, std::string> const &) -> DataSourceVariant {
1006
            if (auto ld = std::static_pointer_cast<LineData>(sourceData)) {
2✔
1007
                auto adapter = std::make_shared<LineDataAdapter>(ld, timeFrame, name);
2✔
1008
                return DataSourceVariant{std::static_pointer_cast<ILineSource>(adapter)};
2✔
1009
            }
4✔
UNCOV
1010
            return DataSourceVariant{};
×
1011
        };
345✔
1012

1013
        registerAdapter(std::move(info), std::move(factory));
345✔
1014
    }
345✔
1015

1016
    //std::cout << "Finished registering built-in adapters." << std::endl;
1017
}
345✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc