Update date in Doxyfile
[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   for(it = it_min; it != it_max; it++) {
103     realName = "";
104     if(providedName != "") realName = anna::functions::asString("%s.%d.csv", providedName.c_str(), (*it).first);
105     SampleFile_ptr = &((*it).second.SampleFile);
106     *SampleFile_ptr = realName;
107   }
108
109   return true;
110 }
111
112
113 //------------------------------------------------------------------------------
114 //--------------------------------------------------- Engine::disableSampleLog()
115 //------------------------------------------------------------------------------
116 bool Engine::disableSampleLog(const int & id) throw() {
117
118   if(id != -1) {
119     _concept_identification_map_nc_iter it = a_concept_identification_map.find(id);
120
121     if(it == a_concept_identification_map.end()) return false;
122
123     // Access to map
124     std::string *SampleFile_ptr = &((*it).second.SampleFile);
125     *SampleFile_ptr = "";
126     return true;
127   }
128
129   // For all concepts:
130   return enableSampleLog(id /* -1 */, "");
131 }
132
133
134 //------------------------------------------------------------------------------
135 //--------------------------------------------------- Engine::disableSampleLog()
136 //------------------------------------------------------------------------------
137 bool Engine::logSample(const int & conceptId, const anna::Millisecond & unixTimestamp, const double & value) const throw() {
138   anna::Guard guard(a_mutex);
139
140   _concept_identification_map_iter it = a_concept_identification_map.find(conceptId);
141
142   if(it == a_concept_identification_map.end()) return false;
143
144   std::string target = (*it).second.SampleFile;
145
146   if(target != "") {  // enabled
147     std::ofstream out(target.c_str(), std::ifstream::out | std::ifstream::app);
148     // Write and close (quiza no deberia cerrar cada vez...)
149     std::string log = anna::functions::asString(unixTimestamp);
150     log += ",";
151     log += anna::functions::asString(value, (*it).second.IntegerNatureSample ? "%.0f" : "%e");
152     log += "\n";
153     out.write(log.c_str(), log.size());
154     out.close();
155   }
156
157   return true;
158 }
159
160
161 //------------------------------------------------------------------------------
162 //-------------------------------------------------- Engine::createAccumulator()
163 //------------------------------------------------------------------------------
164 Accumulator *Engine::createAccumulator(const std::string &name) throw(anna::RuntimeException) {
165   Accumulator *result = getAccumulator(name);
166
167   if (result)
168     throw anna::RuntimeException(anna::functions::asString("Cannot register another accumulator with the same name: %s", name.c_str()), ANNA_FILE_LOCATION);
169
170   result = new Accumulator(name);
171   a_accumulators[name] = result;
172   return result;
173 }
174
175 Accumulator* Engine::getAccumulator(const std::string &name) throw() {
176   Accumulator *result = NULL;
177
178   _accumulator_map_nc_it it = a_accumulators.find(name);
179   if (it != a_accumulators.end())
180     result = it->second;
181
182   return result;
183 }
184
185
186 //------------------------------------------------------------------------------
187 //----------------------------------------------------------- Engine::asString()
188 //------------------------------------------------------------------------------
189 std::string Engine::asString(void) const throw() {
190   std::string trace;
191   _concept_identification_map_iter iter;
192   _concept_identification_map_iter iter_min(a_concept_identification_map.begin());
193   _concept_identification_map_iter iter_max(a_concept_identification_map.end());
194   trace =  "\n=============================";
195   trace +=  "\nStatistic Engine Information";
196   trace +=  "\n============================";
197
198   if(!enabled())
199     trace +=  "\nWARNING: engine is disabled !";
200
201   if(a_concept_identification_map.size() == 0) {
202     trace += "\nNo concepts found (empty map)";
203     return trace;
204   }
205
206   trace += "\nNumber of elements (registered concepts) = "; trace += anna::functions::asString(a_concept_identification_map.size());
207
208   for(iter = iter_min; iter != iter_max; iter++) {
209     trace += "\n";
210     trace += "\n   Concept id:            "; trace += anna::functions::asString((*iter).first);
211
212     if((*iter).second.SampleFile != "") trace += "\n   Sample file:           "; trace += (*iter).second.SampleFile;
213
214     trace += "\n   Description:           "; trace += (*iter).second.Description;
215     trace += "\n   Unit:                  "; trace += (*iter).second.Unit;
216     trace += "\n   Integer Nature Sample: "; trace += (*iter).second.IntegerNatureSample ? "yes" : "no";
217   }
218
219   trace += "\n";
220
221   // Accumulators:
222   trace += "\nNumber of accumulators= "; trace += anna::functions::asString(a_accumulators.size());
223   for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++) {
224     trace += "\n";
225     trace += it->second->asString();
226   }
227
228   return (trace);
229 }
230
231
232 //------------------------------------------------------------------------------
233 //-------------------------------------------------------------- Engine::asXML()
234 //------------------------------------------------------------------------------
235 anna::xml::Node* Engine::asXML(anna::xml::Node* parent, const int & numberOfDecimals) const throw() {
236   anna::xml::Node* result = parent->createChild("anna.statistics.Engine");
237   _concept_identification_map_iter iter;
238   _concept_identification_map_iter iter_min(a_concept_identification_map.begin());
239   _concept_identification_map_iter iter_max(a_concept_identification_map.end());
240   int size = a_concept_identification_map.size();
241   result->createAttribute("State", enabled() ? "Enabled" : "Disabled");
242   anna::xml::Node* registeredConcepts = result->createChild("ConceptsList");
243   registeredConcepts->createAttribute("Size", (size > 0) ? anna::functions::asString(size) : "No concepts found (empty map)");
244
245   for(iter = iter_min; iter != iter_max; iter++) {
246     anna::xml::Node* concept = registeredConcepts->createChild("Concept");
247     concept->createAttribute("Id", anna::functions::asString((*iter).first));
248
249     if((*iter).second.SampleFile != "") concept->createAttribute("SampleFile", (*iter).second.SampleFile);
250
251     concept->createAttribute("Description", (*iter).second.Description);
252     concept->createAttribute("Unit", (*iter).second.Unit);
253     concept->createAttribute("IntegerNatureSample", (*iter).second.IntegerNatureSample ? "yes" : "no");
254   }
255
256   // Accumulators:
257   anna::xml::Node* accumulators = result->createChild("anna.statistics.Accumulators");
258   accumulators->createAttribute("RegisteredAccumulators", a_accumulators.size());
259   for (_accumulator_map_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
260     it->second->asXML(accumulators);
261
262   return result;
263 }