25 #ifndef SRC_TIME_THREADSAFEINTERPOLATINGTIMEHISTORY_H_
26 #define SRC_TIME_THREADSAFEINTERPOLATINGTIMEHISTORY_H_
46 #include <forward_list>
52 #include "../unit/Unit.h"
53 #include "../platform/File.h"
54 #include "TimestampInfo.h"
65 bool accept(
File& dir,
const string& name) {
66 bool starts_with = (name.find(prefix) == 0);
67 bool ends_with = (name.find(suffix)
68 == name.size() - suffix.size() - 1);
69 return starts_with && ends_with;
81 int num_valid_samples;
97 history_size = num_samples;
99 for (
int i = 0; i < num_samples; i++) {
101 history.push_back(p_t);
104 this->default_obj = default_obj;
106 num_valid_samples = 0;
107 this->value_name = name;
112 for (
size_t i = 0; i < history.size(); i++) {
123 std::unique_lock<mutex> sync(list_mutex);
124 for (
int i = 0; i < history_size; i++) {
126 p_t->setValid(
false);
129 num_valid_samples = 0;
137 return num_valid_samples;
145 std::unique_lock<mutex> sync(list_mutex);
146 T* p_existing = history[curr_index];
149 if (curr_index >= history_size) {
152 if (num_valid_samples < history_size) {
166 bool get(
long requested_timestamp, T& out) {
167 bool success =
false;
169 long nearest_preceding_timestamp = LONG_MIN;
170 long nearest_preceding_timestamp_delta = LONG_MIN;
171 T *p_nearest_preceding_obj = NULL;
172 long nearest_following_timestamp_delta = LONG_MAX;
173 T *p_nearest_following_obj = NULL;
174 bool copy_object =
true;
176 std::unique_lock<mutex> sync(list_mutex);
178 int entry_index = curr_index;
179 for (
int i = 0; i < num_valid_samples; i++) {
180 T *p_obj = history[entry_index];
181 long entry_timestamp = p_obj->getTimestamp();
182 long delta = entry_timestamp - requested_timestamp;
184 if (delta > nearest_preceding_timestamp_delta) {
185 nearest_preceding_timestamp_delta = delta;
186 nearest_preceding_timestamp = entry_timestamp;
187 p_nearest_preceding_obj = p_obj;
193 if (p_nearest_following_obj != NULL)
196 }
else if (delta > 0) {
197 if (delta < nearest_following_timestamp_delta) {
198 nearest_following_timestamp_delta = delta;
199 p_nearest_following_obj = p_obj;
206 if (entry_index < 0) {
207 entry_index = history_size - 1;
215 if ((p_match == NULL) && (p_nearest_preceding_obj != NULL)
216 && (p_nearest_following_obj != NULL)) {
217 double timestamp_delta = nearest_following_timestamp_delta
218 - nearest_preceding_timestamp_delta;
219 double requested_timestamp_offset = requested_timestamp
220 - nearest_preceding_timestamp;
221 double requested_timestamp_ratio = requested_timestamp_offset
224 p_nearest_preceding_obj->interpolate(*p_nearest_following_obj,
225 requested_timestamp_ratio, out);
226 out.setInterpolated(
true);
231 if ((p_match != NULL) && copy_object) {
236 out.setInterpolated(
false);
249 T* p_most_recent_t = NULL;
251 std::unique_lock<mutex> sync(list_mutex);
253 if (num_valid_samples > 0) {
254 int curr_idx = this->curr_index;
257 curr_idx = (history_size - 1);
259 p_most_recent_t = history[curr_idx];
260 if (!p_most_recent_t->getValid()) {
261 p_most_recent_t = NULL;
265 if (p_most_recent_t != NULL) {
268 out.copy(*p_most_recent_t);
275 bool writeToDirectory(
string& directory) {
277 if (!dir.isDirectory() || !dir.canWrite()) {
278 printf(
"Directory parameter '%s' must be a writable directory.", directory.c_str());
282 if ((directory[(directory.length() - 1)] !=
'/')
283 && (directory[(directory.length() - 1)] !=
'\\')) {
284 directory += File::separatorChar;
287 string filename_prefix = value_name +
"History";
288 string filename_suffix =
"csv";
291 forward_list<File *> matching_files;
293 f.listFiles(matching_files, filter);
295 int next_available_index = -1;
297 for (
File *p_matching_file : matching_files) {
298 string file_name = p_matching_file->getName();
299 regex expression(
"[.][^.]+$");
300 string replacement(
"");
301 string file_name_prefix = regex_replace(file_name, expression,
303 string file_counter = file_name_prefix.substr(
304 filename_prefix.length());
305 int counter = atoi(file_counter.c_str());
306 if (counter > next_available_index) {
307 next_available_index = counter;
309 delete p_matching_file;
312 next_available_index++;
314 string new_filename = filename_prefix + std::to_string(next_available_index);
315 return writeToFile(directory + new_filename +
"." + filename_suffix);
318 bool writeToFile(
const string& file_path) {
320 bool success = writeToDiskInternal(out);
330 if (num_valid_samples > 0) {
331 if (num_valid_samples == history_size) {
332 oldest_index = curr_index + 1;
333 if (oldest_index >= history_size) {
336 num_to_write = num_valid_samples;
339 num_to_write = curr_index + 1;
341 T *p_first_entry = history[oldest_index];
342 vector<string> quantity_names;
343 IQuantity& quantity = p_first_entry->getQuantity();
344 bool is_quantity_container = quantity.getContainedQuantityNames(
347 string header =
"Timestamp";
348 if (is_quantity_container) {
349 for (
string& quantity_name : quantity_names) {
350 header +=
"," + value_name +
"." + quantity_name;
353 header +=
"," + value_name;
357 for (
int i = 0; i < num_to_write; i++) {
358 vector<string> value_string;
359 T* p_entry_to_write = history[oldest_index++];
360 quantity = p_entry_to_write->getQuantity();
361 value_string.push_back(std::to_string(p_entry_to_write->getTimestamp()));
362 value_string.push_back(
",");
363 if (is_quantity_container) {
364 vector<IQuantity *> contained_quantities;
365 quantity.getContainedQuantities(contained_quantities);
367 for (
IQuantity* contained_quantity : contained_quantities) {
368 vector<string> printable_string;
370 value_string.push_back(
",");
372 contained_quantity->getPrintableString(
374 for (
auto string_part : printable_string) {
375 value_string.push_back(string_part);
379 quantity.getPrintableString(value_string);
381 string output_string;
382 for (
auto string_part : value_string) {
383 output_string += string_part;
385 out.println(output_string);
386 if (oldest_index >= history_size) {
389 if (oldest_index == curr_index) {
void add(T &t)
Adds the provided object to the ThreadsafeInterpolatingTimeHistory.
Definition: ThreadsafeInterpolatingTimeHistory.h:144
ThreadsafeInterpolatingTimeHistory(T &default_obj, int num_samples, TimestampInfo &ts_info, string &name)
Constructs a ThreadsafeInterpolatingTimeHihstory to hold up to a specified number of objects of the s...
Definition: ThreadsafeInterpolatingTimeHistory.h:93
Definition: TimestampInfo.h:28
int getValidSampleCount()
Returns the current count of valid objects in this ThreadsafeInterpolatingTimeHistory.
Definition: ThreadsafeInterpolatingTimeHistory.h:136
void reset()
Clears all contents of the ThreadsafeInterpolatingTimeHistory by marking all contained objects as inv...
Definition: ThreadsafeInterpolatingTimeHistory.h:122
Definition: ThreadsafeInterpolatingTimeHistory.h:75
Definition: ThreadsafeInterpolatingTimeHistory.h:57
Definition: IQuantity.h:33
bool getMostRecent(T &out)
Retrieves the most recently-added object in the ThreadsafeInterpolatingTimeHistory.
Definition: ThreadsafeInterpolatingTimeHistory.h:248