ebde06c7fbc2748252db21216af76a0d7a6377b1
[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_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
43     delete (*it);
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::asString()
160 //------------------------------------------------------------------------------
161 Accumulator *Engine::createAccumulator(const std::string &name) throw() {
162   Accumulator *result;
163
164   result = new Accumulator(name);
165   a_accumulators.push_back(result);
166   return result;
167 }
168
169
170 //------------------------------------------------------------------------------
171 //----------------------------------------------------------- Engine::asString()
172 //------------------------------------------------------------------------------
173 std::string Engine::asString(void) const throw() {
174   std::string trace;
175   _concept_identification_map_iter iter;
176   _concept_identification_map_iter iter_min(a_concept_identification_map.begin());
177   _concept_identification_map_iter iter_max(a_concept_identification_map.end());
178   trace =  "\n=============================";
179   trace +=  "\nStatistic Engine Information";
180   trace +=  "\n============================";
181
182   if(!enabled())
183     trace +=  "\nWARNING: engine is disabled !";
184
185   if(a_concept_identification_map.size() == 0) {
186     trace += "\nNo concepts found (empty map)";
187     return trace;
188   }
189
190   trace += "\nNumber of elements (registered concepts) = "; trace += anna::functions::asString(a_concept_identification_map.size());
191
192   for(iter = iter_min; iter != iter_max; iter++) {
193     trace += "\n";
194     trace += "\n   Concept id:            "; trace += anna::functions::asString((*iter).first);
195
196     if((*iter).second.SampleFile != "") trace += "\n   Sample file:           "; trace += (*iter).second.SampleFile;
197
198     trace += "\n   Description:           "; trace += (*iter).second.Description;
199     trace += "\n   Unit:                  "; trace += (*iter).second.Unit;
200     trace += "\n   Integer Nature Sample: "; trace += (*iter).second.IntegerNatureSample ? "yes" : "no";
201   }
202
203   trace += "\n";
204
205   // Accumulators:
206   trace += "\nNumber of accumulators= "; trace += anna::functions::asString(a_accumulators.size());
207   for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++) {
208     trace += "\n";
209     trace += (*it)->asString();
210   }
211
212   return (trace);
213 }
214
215
216 //------------------------------------------------------------------------------
217 //-------------------------------------------------------------- Engine::asXML()
218 //------------------------------------------------------------------------------
219 anna::xml::Node* Engine::asXML(anna::xml::Node* parent, const int & numberOfDecimals) const throw() {
220   anna::xml::Node* result = parent->createChild("anna.statistics.Engine");
221   _concept_identification_map_iter iter;
222   _concept_identification_map_iter iter_min(a_concept_identification_map.begin());
223   _concept_identification_map_iter iter_max(a_concept_identification_map.end());
224   int size = a_concept_identification_map.size();
225   result->createAttribute("State", enabled() ? "Enabled" : "Disabled");
226   anna::xml::Node* registeredConcepts = result->createChild("ConceptsList");
227   registeredConcepts->createAttribute("Size", (size > 0) ? anna::functions::asString(size) : "No concepts found (empty map)");
228
229   for(iter = iter_min; iter != iter_max; iter++) {
230     anna::xml::Node* concept = registeredConcepts->createChild("Concept");
231     concept->createAttribute("Id", anna::functions::asString((*iter).first));
232
233     if((*iter).second.SampleFile != "") concept->createAttribute("SampleFile", (*iter).second.SampleFile);
234
235     concept->createAttribute("Description", (*iter).second.Description);
236     concept->createAttribute("Unit", (*iter).second.Unit);
237     concept->createAttribute("IntegerNatureSample", (*iter).second.IntegerNatureSample ? "yes" : "no");
238   }
239
240   // Accumulators:
241   anna::xml::Node* accumulators = result->createChild("anna.statistics.Accumulators");
242   accumulators->createAttribute("RegisteredAccumulators", a_accumulators.size());
243   for (_accumulator_vector_it it = a_accumulators.begin(); it != a_accumulators.end(); it++)
244     (*it)->asXML(accumulators);
245
246   return result;
247 }