e804599713f8411ec08128b81e3f6019d21dd5c9
[anna.git] / source / statistics / Engine.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 // Local
10 #include <anna/statistics/Engine.hpp>
11 #include <anna/statistics/internal/sccs.hpp>
12 #include <anna/core/mt/Guard.hpp>
13 #include <anna/core/functions.hpp>
14 #include <anna/xml/xml.hpp>
15
16 // Std
17 #include <iostream>
18 #include <fstream>
19
20
21 using namespace anna::statistics;
22
23
24 //******************************************************************************
25 //----------------------------------------------------------------------- Engine
26 //******************************************************************************
27
28 //------------------------------------------------------------------------------
29 //------------------------------------------------------------- Engine::Engine()
30 //------------------------------------------------------------------------------
31 Engine::Engine() {
32   statistics::sccs::activate();
33   a_enabled = false;
34   a_sequence_concept_id = 0;
35 }
36
37
38 //------------------------------------------------------------------------------
39 //------------------------------------------------------------ Engine::~Engine()
40 //------------------------------------------------------------------------------
41 Engine::~Engine() {
42   for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
43     delete (it->second);
44 }
45
46
47 //------------------------------------------------------------------------------
48 //--------------------------------------------------------- Engine::addConcept()
49 //------------------------------------------------------------------------------
50 int Engine::addConcept(const std::string & description, const std::string & unit, const bool & integerNatureSample) throw() {
51   a_sequence_concept_id++;
52   _concept_identification_t aux;
53   aux.SampleFile = ""; // sample dump disabled by default for new concepts
54   aux.Description = description;
55   aux.Unit = unit;
56   aux.IntegerNatureSample = integerNatureSample;
57   a_concept_identification_map[a_sequence_concept_id] = aux;
58   return (a_sequence_concept_id);
59 }
60
61
62 //------------------------------------------------------------------------------
63 //--------------------------------------------------------- Engine::getConcept()
64 //------------------------------------------------------------------------------
65 bool Engine::getConcept(const int & id, std::string & description, std::string & unit, bool & integerNatureSample) const throw() {
66   _concept_identification_map_iter it = a_concept_identification_map.find(id);
67
68   if(it == a_concept_identification_map.end()) return false;
69
70   description = (*it).second.Description;
71   unit = (*it).second.Unit;
72   integerNatureSample = (*it).second.IntegerNatureSample;
73   return (true);
74 }
75
76
77 //------------------------------------------------------------------------------
78 //---------------------------------------------------- Engine::enableSampleLog()
79 //------------------------------------------------------------------------------
80 bool Engine::enableSampleLog(const int & id, const char *sampleFileName) throw() {
81   _concept_identification_map_nc_iter it;
82   std::string providedName = sampleFileName ? sampleFileName : "sample";
83   std::string *SampleFile_ptr;
84   std::string realName = "";
85
86   if(id != -1) {
87     it = a_concept_identification_map.find(id);
88
89     if(it == a_concept_identification_map.end()) return false;
90
91     if(providedName != "") realName = anna::functions::asString("%s.%d.csv", providedName.c_str(), id);
92
93     // Assignment
94     SampleFile_ptr = &((*it).second.SampleFile);
95     *SampleFile_ptr = realName;
96     return true;
97   }
98
99   // For all concepts:
100   _concept_identification_map_nc_iter it_min(a_concept_identification_map.begin());
101   _concept_identification_map_nc_iter it_max(a_concept_identification_map.end());
102
103   for(it = it_min; it != it_max; it++) {
104     realName = "";
105
106     if(providedName != "") realName = anna::functions::asString("%s.%d.csv", providedName.c_str(), (*it).first);
107
108     SampleFile_ptr = &((*it).second.SampleFile);
109     *SampleFile_ptr = realName;
110   }
111
112   return true;
113 }
114
115
116 //------------------------------------------------------------------------------
117 //--------------------------------------------------- Engine::disableSampleLog()
118 //------------------------------------------------------------------------------
119 bool Engine::disableSampleLog(const int & id) throw() {
120   _concept_identification_map_nc_iter it = a_concept_identification_map.find(id);
121
122   if(it == a_concept_identification_map.end()) return false;
123
124   // Access to map
125   std::string *SampleFile_ptr = &((*it).second.SampleFile);
126   *SampleFile_ptr = "";
127   return true;
128 }
129
130
131 //------------------------------------------------------------------------------
132 //--------------------------------------------------- Engine::disableSampleLog()
133 //------------------------------------------------------------------------------
134 bool Engine::logSample(const int & conceptId, const anna::Millisecond & unixTimestamp, const double & value) const throw() {
135   anna::Guard guard(a_mutex);
136
137   _concept_identification_map_iter it = a_concept_identification_map.find(conceptId);
138
139   if(it == a_concept_identification_map.end()) return false;
140
141   std::string target = (*it).second.SampleFile;
142
143   if(target != "") {  // enabled
144     std::ofstream out(target.c_str(), std::ifstream::out | std::ifstream::app);
145     // Write and close (quiza no deberia cerrar cada vez...)
146     std::string log = anna::functions::asString(unixTimestamp);
147     log += ",";
148     log += anna::functions::asString(value, (*it).second.IntegerNatureSample ? "%.0f" : "%e");
149     log += "\n";
150     out.write(log.c_str(), log.size());
151     out.close();
152   }
153
154   return true;
155 }
156
157
158 //------------------------------------------------------------------------------
159 //-------------------------------------------------- Engine::createAccumulator()
160 //------------------------------------------------------------------------------
161 Accumulator *Engine::createAccumulator(const std::string &name) throw(anna::RuntimeException) {
162   Accumulator *result = getAccumulator(name);
163
164   if (result)
165     throw anna::RuntimeException(anna::functions::asString("Cannot register another accumulator with the same name: %s", name.c_str()), ANNA_FILE_LOCATION);
166
167   result = new Accumulator(name);
168   a_accumulators[name] = result;
169   return result;
170 }
171
172 Accumulator* Engine::getAccumulator(const std::string &name) throw() {
173   Accumulator *result = NULL;
174
175   _accumulator_map_nc_it it = a_accumulators.find(name);
176   if (it != a_accumulators.end())
177     result = it->second;
178
179   return result;
180 }
181
182
183 //------------------------------------------------------------------------------
184 //----------------------------------------------------------- Engine::asString()
185 //------------------------------------------------------------------------------
186 std::string Engine::asString(void) const throw() {
187   std::string trace;
188   _concept_identification_map_iter iter;
189   _concept_identification_map_iter iter_min(a_concept_identification_map.begin());
190   _concept_identification_map_iter iter_max(a_concept_identification_map.end());
191   trace =  "\n=============================";
192   trace +=  "\nStatistic Engine Information";
193   trace +=  "\n============================";
194
195   if(!enabled())
196     trace +=  "\nWARNING: engine is disabled !";
197
198   if(a_concept_identification_map.size() == 0) {
199     trace += "\nNo concepts found (empty map)";
200     return trace;
201   }
202
203   trace += "\nNumber of elements (registered concepts) = "; trace += anna::functions::asString(a_concept_identification_map.size());
204
205   for(iter = iter_min; iter != iter_max; iter++) {
206     trace += "\n";
207     trace += "\n   Concept id:            "; trace += anna::functions::asString((*iter).first);
208
209     if((*iter).second.SampleFile != "") trace += "\n   Sample file:           "; trace += (*iter).second.SampleFile;
210
211     trace += "\n   Description:           "; trace += (*iter).second.Description;
212     trace += "\n   Unit:                  "; trace += (*iter).second.Unit;
213     trace += "\n   Integer Nature Sample: "; trace += (*iter).second.IntegerNatureSample ? "yes" : "no";
214   }
215
216   trace += "\n";
217
218   // Accumulators:
219   trace += "\nNumber of accumulators= "; trace += anna::functions::asString(a_accumulators.size());
220   for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++) {
221     trace += "\n";
222     trace += it->second->asString();
223   }
224
225   return (trace);
226 }
227
228
229 //------------------------------------------------------------------------------
230 //-------------------------------------------------------------- Engine::asXML()
231 //------------------------------------------------------------------------------
232 anna::xml::Node* Engine::asXML(anna::xml::Node* parent, const int & numberOfDecimals) const throw() {
233   anna::xml::Node* result = parent->createChild("anna.statistics.Engine");
234   _concept_identification_map_iter iter;
235   _concept_identification_map_iter iter_min(a_concept_identification_map.begin());
236   _concept_identification_map_iter iter_max(a_concept_identification_map.end());
237   int size = a_concept_identification_map.size();
238   result->createAttribute("State", enabled() ? "Enabled" : "Disabled");
239   anna::xml::Node* registeredConcepts = result->createChild("ConceptsList");
240   registeredConcepts->createAttribute("Size", (size > 0) ? anna::functions::asString(size) : "No concepts found (empty map)");
241
242   for(iter = iter_min; iter != iter_max; iter++) {
243     anna::xml::Node* concept = registeredConcepts->createChild("Concept");
244     concept->createAttribute("Id", anna::functions::asString((*iter).first));
245
246     if((*iter).second.SampleFile != "") concept->createAttribute("SampleFile", (*iter).second.SampleFile);
247
248     concept->createAttribute("Description", (*iter).second.Description);
249     concept->createAttribute("Unit", (*iter).second.Unit);
250     concept->createAttribute("IntegerNatureSample", (*iter).second.IntegerNatureSample ? "yes" : "no");
251   }
252
253   // Accumulators:
254   anna::xml::Node* accumulators = result->createChild("anna.statistics.Accumulators");
255   accumulators->createAttribute("RegisteredAccumulators", a_accumulators.size());
256   for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
257     it->second->asXML(accumulators);
258
259   return result;
260 }