Documentation of UrbanFireXDT
Documentation of UrbanFireXDT
Loading...
Searching...
No Matches
cache_helper.hpp
Go to the documentation of this file.
1
7#pragma once
8
9// This header files defines the following classes
12
13#include <boost/json.hpp>
14#include <fstream>
15#include <sstream>
16#include <unordered_map>
17#include <optional>
18#include <string>
19#include <mutex>
20
21namespace json = boost::json;
22
28 private:
29 HPProfileIDCache() = default;
30 ~HPProfileIDCache() = default;
31
32 public:
34 void operator=(HPProfileIDCache const&) = delete;
35
40 static HPProfileIDCache instance_; // thread-safe since C++11, instantiated on first use
41 return instance_;
42 }
43
47 void setCacheFilename(const std::string& filename) {
48 std::lock_guard<std::mutex> lock(mutex_);
49 cache_filename_ = filename;
50 load_from_file();
51 }
52
56 void updateCache(size_t unitID, size_t profileID) {
57 std::lock_guard<std::mutex> lock(mutex_);
58 cache_updated = true;
59 cache_[unitID] = profileID;
60 //save_to_file();
61 }
62
66 std::optional<size_t> readCache(size_t unitID) {
67 auto it = cache_.find(unitID);
68 if (it != cache_.end()) {
69 return it->second;
70 }
71 return std::nullopt;
72 }
73
78 std::lock_guard<std::mutex> lock(mutex_);
79 save_to_file();
80 }
81
82 private:
83 std::string cache_filename_;
84 std::unordered_map<size_t, size_t> cache_;
85 bool cache_updated = false;
86 std::mutex mutex_;
87
88 void save_to_file() {
89 if (!cache_updated)
90 return;
91
92 if (cache_filename_.empty()) {
93 throw std::runtime_error("HP cache filename is not set. Call HPProfileIDCache::setCacheFilename() before saving.");
94 }
95
96 json::array jarray;
97 for (const auto& [unitID, profileID] : cache_) {
98 jarray.emplace_back(json::array{unitID, profileID});
99 }
100
101 std::ofstream ofs(cache_filename_);
102 if (ofs) {
103 ofs << json::serialize(jarray);
104 std::cout << "Heat pump profile allocation written to cache file '" << cache_filename_ << "'\n";
105 } else {
106 std::cout << "Error: Heat pump cache file cound not be written! Cannot write to " << cache_filename_ << "'\n";
107 }
108 }
109
110 void load_from_file() {
111 cache_.clear();
112 std::ifstream ifs(cache_filename_);
113 if (!ifs) return;
114
115 std::stringstream buffer;
116 buffer << ifs.rdbuf();
117
118 boost::system::error_code ec;
119 json::value jv = json::parse(buffer.str(), ec);
120 if (ec) {
121 throw std::runtime_error("Failed to parse JSON cache file: " + ec.message());
122 }
123 const json::array& jarray = jv.as_array();
124
125 for (const auto& item : jarray) {
126 const json::array& pair = item.as_array();
127 size_t unitID;
128 size_t profileID;
129 bool skip = false;
130
131 if (pair.size() != 2) {
132 skip = true;
133 }
134 if (!skip && pair[0].is_int64()) {
135 unitID = static_cast<size_t>(pair[0].as_int64());
136 } else if (!skip && pair[0].is_uint64()) {
137 unitID = static_cast<size_t>(pair[0].as_uint64());
138 } else {
139 skip = true;
140 }
141 if (!skip && pair[1].is_int64()) {
142 profileID = static_cast<size_t>(pair[1].as_int64());
143 } else if (!skip && pair[1].is_uint64()) {
144 profileID = static_cast<size_t>(pair[1].as_uint64());
145 } else {
146 skip = true;
147 }
148
149 if (skip) {
150 std::cerr << "Skipping malformed cache entry: " << json::serialize(pair) << "\n";
151 continue;
152 }
153
154 cache_[unitID] = profileID;
155 }
156
157 std::cout << "Heat pump profile allocation read from cache file '" << cache_filename_ << "'\n";
158 }
159};
160
161
162
168 private:
169 PVProfileIDCache() = default;
170 ~PVProfileIDCache() = default;
171
172 public:
174 void operator=(PVProfileIDCache const&) = delete;
175
180 static PVProfileIDCache instance_; // thread-safe since C++11, instantiated on first use
181 return instance_;
182 }
183
187 void setCacheFilename(const std::string& filename) {
188 std::lock_guard<std::mutex> lock(mutex_);
189 cache_filename_ = filename;
190 load_from_file();
191 }
192
196 void updateCache(size_t locationID, const std::string& roof_orientation, size_t profileID) {
197 std::lock_guard<std::mutex> lock(mutex_);
198 cache_updated = true;
199 cache_[locationID][roof_orientation] = profileID;
200 //save_to_file();
201 }
202
206 std::optional<size_t> readCache(size_t locationID, const std::string& roof_orientation) {
207 std::lock_guard<std::mutex> lock(mutex_);
208 auto loc_it = cache_.find(locationID);
209 if (loc_it != cache_.end()) {
210 auto orient_it = loc_it->second.find(roof_orientation);
211 if (orient_it != loc_it->second.end()) {
212 return orient_it->second;
213 }
214 }
215 return std::nullopt;
216 }
217
222 std::lock_guard<std::mutex> lock(mutex_);
223 save_to_file();
224 }
225
226 private:
227 std::string cache_filename_;
228 std::unordered_map<size_t, std::unordered_map<std::string, size_t>> cache_; // locationID -> map< orientation string, profileID >
229 bool cache_updated = false;
230 std::mutex mutex_;
231
232 void save_to_file() {
233 if (!cache_updated)
234 return;
235
236 if (cache_filename_.empty()) {
237 throw std::runtime_error("PV cache filename is not set. Call PVProfileIDCache::setCacheFilename() before saving.");
238 }
239
240 json::array jarray;
241 for (const auto& [locationID, orientation_map] : cache_) {
242 for (const auto& [orientation, profileID] : orientation_map) {
243 jarray.emplace_back(json::array{locationID, orientation, profileID});
244 }
245 }
246
247 std::ofstream ofs(cache_filename_);
248 if (ofs) {
249 ofs << json::serialize(jarray);
250 std::cout << "PV profile allocation written to cache file '" << cache_filename_ << "'\n";
251 } else {
252 std::cout << "Error: PV cache file cound not be written! Cannot write to " << cache_filename_ << "'\n";
253 }
254 }
255
256 void load_from_file() {
257 cache_.clear();
258 std::ifstream ifs(cache_filename_);
259 if (!ifs) return;
260
261 std::stringstream buffer;
262 buffer << ifs.rdbuf();
263
264 boost::system::error_code ec;
265 json::value jv = json::parse(buffer.str(), ec);
266 if (ec) {
267 throw std::runtime_error("Failed to parse JSON cache file: " + ec.message());
268 }
269
270 const json::array& jarray = jv.as_array();
271 for (const auto& item : jarray) {
272 const json::array& entry = item.as_array();
273 size_t locationID;
274 std::string roof_orientation;
275 size_t profileID;
276 bool skip = false;
277
278 if (entry.size() != 3) {
279 skip = true;
280 }
281 if (!skip && entry[0].is_int64()) {
282 locationID = static_cast<size_t>(entry[0].as_int64());
283 } else if (!skip && entry[0].is_uint64()) {
284 locationID = static_cast<size_t>(entry[0].as_uint64());
285 } else {
286 skip = true;
287 }
288 if (!skip && entry[1].is_string()) {
289 roof_orientation = entry[1].as_string().c_str();
290 } else {
291 skip = true;
292 }
293 if (!skip && entry[2].is_int64()) {
294 profileID = static_cast<size_t>(entry[2].as_int64());
295 } else if (!skip && entry[2].is_uint64()) {
296 profileID = static_cast<size_t>(entry[2].as_uint64());
297 } else {
298 skip = true;
299 }
300
301 if (skip) {
302 std::cerr << "Skipping malformed cache entry: " << json::serialize(entry) << "\n";
303 continue;
304 }
305
306 cache_[locationID][roof_orientation] = profileID;
307 }
308
309 std::cout << "PV profile allocation read from cache file '" << cache_filename_ << "'\n";
310 }
311};
312
313
Definition cache_helper.hpp:27
void updateCache(size_t unitID, size_t profileID)
Definition cache_helper.hpp:56
void operator=(HPProfileIDCache const &)=delete
static HPProfileIDCache & GetInstance()
Definition cache_helper.hpp:39
void setCacheFilename(const std::string &filename)
Definition cache_helper.hpp:47
HPProfileIDCache(HPProfileIDCache const &)=delete
void saveCacheFile()
Definition cache_helper.hpp:77
std::optional< size_t > readCache(size_t unitID)
Definition cache_helper.hpp:66
Definition cache_helper.hpp:167
std::optional< size_t > readCache(size_t locationID, const std::string &roof_orientation)
Definition cache_helper.hpp:206
void setCacheFilename(const std::string &filename)
Definition cache_helper.hpp:187
void updateCache(size_t locationID, const std::string &roof_orientation, size_t profileID)
Definition cache_helper.hpp:196
void operator=(PVProfileIDCache const &)=delete
static PVProfileIDCache & GetInstance()
Definition cache_helper.hpp:179
PVProfileIDCache(PVProfileIDCache const &)=delete
void saveCacheFile()
Definition cache_helper.hpp:221