#include #include #include #include #include #include #include #include /* -- */ #include #include #include #include #include #include #include #include #include /* -- */ #include "plugin/Plugin.hpp" /* -- */ #include "trace/EntityTypes.hpp" #include "trace/Entitys.hpp" #include "trace/Container.hpp" #include "trace/EntityValue.hpp" #include "trace/StateChange.hpp" #include "trace/tree/BinaryTree.hpp" #include "trace/tree/Node.hpp" #include "trace/Trace.hpp" /* -- */ #include "common/Message.hpp" class Distribution : public Plugin { class LogEntry { public: Date start; double duration; LogEntry(Date _start, double _duration) { this->start = _start; this->duration = _duration; } /* XXX could not this be nicer ? */ struct compar_date_sort { bool operator()(LogEntry *e1, LogEntry *e2) { return (e1->start < e2->start); } } compar_date_sort_op; struct compar_duration_sort { bool operator()(LogEntry *e1, LogEntry *e2) { return (e1->duration < e2->duration); } } compar_duration_sort_op; void sort_by_duration(std::vector &le_list) { std::sort(le_list.begin(), le_list.end(), compar_duration_sort_op); } void sort_by_date(std::vector &le_list) { std::sort(le_list.begin(), le_list.end(), compar_date_sort_op); } }; private: QTextEdit *_text_info; QTreeWidget *_nodes_selected; QTreeWidget *_state_names_selected; QGraphicsScene *scene; QGraphicsView *view; QSlider *min_slider; QSlider *max_slider; /* all names found in the trace */ std::set state_types_names; void select_container_rec(QTreeWidgetItem * root_node, Container *current_container) const { const std::list *children = current_container->get_children(); // Add the root container names QList items; QFlags flg = Qt::ItemIsUserCheckable | Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsTristate; for (std::list::const_iterator it = children->begin(); it != children->end(); it ++) { // We create the node and we do the recursivity std::string name = (*it)->get_name().to_string(); QStringList temp(QString::fromStdString(name)); QTreeWidgetItem *current_node = new QTreeWidgetItem((QTreeWidgetItem *)root_node, temp); current_node->setFlags(flg); current_node->setCheckState(0,Qt::Unchecked); items.append(current_node); select_container_rec(current_node, (*it)); } } void select_container() const { const std::list *root_containers = _trace->get_root_containers(); // Add the root container names QList items; QFlags flg=Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate; for (std::list::const_iterator it = root_containers->begin(); it != root_containers->end(); it++) { std::string name = (*it)->get_name().to_string(); QStringList temp(QString::fromStdString(name)); QTreeWidgetItem *current_node = new QTreeWidgetItem((QTreeWidgetItem *)0, temp); current_node->setFlags(flg); current_node->setCheckState(0,Qt::Unchecked); items.append(current_node); // Recursivity to add the children names select_container_rec(current_node, *it); } (*(items.begin()))->setExpanded(true); _nodes_selected->insertTopLevelItems(0, items); } void browse_statechange_tree(Node *node, QString &text, std::string &container_name, std::ostream &stream, std::set &selected_state_types_names, std::vector &found_states) const { if (!node) return; /* handle the node */ const State *st = node->get_element()->get_left_state(); if (st) { const std::string name = st->get_value()->get_name().to_string(); /* does the name appear in the set of selected names ? */ std::set::const_iterator it = selected_state_types_names.find(name); if (it != selected_state_types_names.end()) { double length = st->get_duration(); Date start = st->get_start_time(); stream << container_name; stream << "\t"; stream << name; stream << "\t"; stream << start.to_string(); stream << "\t"; stream << length; stream << "\n"; LogEntry *le = new LogEntry(start, length); found_states.push_back(le); } } /* handle its left child */ browse_statechange_tree(node->get_left_child(), text, container_name, stream, selected_state_types_names, found_states); /* handle its right child */ browse_statechange_tree(node->get_right_child(), text, container_name, stream, selected_state_types_names, found_states); } std::string get_container_complete_name(const Container * container) const { std::string str; if (container->get_parent()) { str = get_container_complete_name(container->get_parent()); str.append("_"); } else { str = ""; } std::string name = container->get_name().to_string(); str.append(name); return str; } int handle_container(Container * &container, QString &text, std::ostream &stream, std::set &selected_state_types_names, std::vector &found_states) const { std::string name = get_container_complete_name(container); text += QString::fromStdString(name); Node *root_node = container->get_states()->get_root(); browse_statechange_tree(root_node, text, name, stream, selected_state_types_names, found_states); int localcnt = container->get_state_number(); text += QString(" count: %1
").arg(localcnt); return localcnt; } void get_statechange_distribution(QString &text) const { /* count */ int count = 0; text += "

States:

"; std::ofstream SaveFile("distribution.txt"); /* the names that were selected by the application */ std::set selected_state_types_names; find_selected_state_types_names(selected_state_types_names); /* A vector to store the entries that matched user contraints */ std::vector found_states; /* Only handle the containers that the user have selected */ QTreeWidgetItemIterator it(_nodes_selected); while (*it) { (*it)->setFlags ((*it)->flags () | Qt::ItemIsUserCheckable); if ((*it)->checkState(0)) { Container *cont = _trace->search_container((*it)->text(0).toStdString()); std::string name = get_container_complete_name(cont); //printf("Container %s was selected\n", name.c_str()); count += handle_container(cont, text, SaveFile, selected_state_types_names, found_states); } ++it; } /* XXX i need C++ courses ;) */ LogEntry dummy(0, 0); dummy.sort_by_duration(found_states); /* TODO really take the min and the max ... */ double min_quantile = 0.01 * (double)min_slider->value(); double max_quantile = 0.01 * (double)max_slider->value(); printf("quantiles : min %lf max %lf\n", min_quantile, max_quantile); compute_histogram_duration(found_states, min_quantile, max_quantile, 25); text += QString("Total count: %1").arg(count); SaveFile.close(); } /* Fill name_set with the names of the state contained in sub-tree node */ void get_state_names_list(std::set &name_set, Node *node) { if (!node) return; /* handle the node */ const State *left_st = node->get_element()->get_left_state(); if (left_st) { const std::string name = left_st->get_value()->get_name().to_string(); name_set.insert(name); } const State *right_st = node->get_element()->get_right_state(); if (right_st) { const std::string name = right_st->get_value()->get_name().to_string(); name_set.insert(name); } /* handle its left child */ get_state_names_list(name_set, node->get_left_child()); /* handle its right child */ get_state_names_list(name_set, node->get_right_child()); } void select_state_types(void) { /* For all containers, get the list of state names */ std::list container_list; _trace->get_all_containers(container_list); for(std::list::const_iterator it = container_list.begin(); it != container_list.end(); ++ it) { BinaryTree *states; states = (*it)->get_states(); if(states && states->get_root()) { get_state_names_list(state_types_names, states->get_root()); } } QList items; QFlags flg=Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate; /* Add a tick box per name of event */ for(std::set::const_iterator it = state_types_names.begin(); it != state_types_names.end(); it++) { QStringList temp(QString::fromStdString(*it)); QTreeWidgetItem *current_node = new QTreeWidgetItem((QTreeWidgetItem *)0, temp); current_node->setFlags(flg); current_node->setCheckState(0,Qt::Unchecked); items.append(current_node); } (*(items.begin()))->setExpanded(true); _state_names_selected->insertTopLevelItems(0, items); } void find_selected_state_types_names(std::set &selected_state_types_names) const { /* Go through the tick box list to find which are the names that have been selected */ QTreeWidgetItemIterator it(_state_names_selected); while (*it) { (*it)->setFlags ((*it)->flags () | Qt::ItemIsUserCheckable); if ((*it)->checkState(0)) { std::string name = (*it)->text(0).toStdString(); selected_state_types_names.insert(name); //printf("Name %s was selected\n", name.c_str()); } ++it; } } double compute_quantile_duration(std::vectorle_list, float alpha) const { float sizef = (float)(le_list.size() - 1); if (alpha > 1.0) alpha = 1.0; if (alpha < 0.0) alpha = 0.0; float indf = alpha*sizef; unsigned ind = floor(indf); LogEntry *le = le_list[ind]; return le->duration; } void compute_histogram_duration(std::vectorle_list, float min_quantile, float max_quantile, unsigned nbreaks) const { if (le_list.size() == 0) return; /* Select values in [min_val ; max_val[ */ double min_val = compute_quantile_duration(le_list, min_quantile); double max_val = compute_quantile_duration(le_list, max_quantile); if (max_val - min_val == 0.0) { printf("Cannot display histogram: not enough different values\n"); return; } unsigned i; unsigned *cnt = (unsigned *)malloc((nbreaks+1)*sizeof(unsigned)); unsigned total_cnt = 0; unsigned max_cnt = 0; /* start from a blank histogram */ for (i = 0; i < nbreaks; i++) cnt[i] = 0; for (i = 0; i < le_list.size(); i++) { double val = le_list[i]->duration; if ((val >= min_val) && (val < max_val)) { /* in which bin does the value go ? */ unsigned bin = floor((nbreaks*(val - min_val))/(max_val - min_val)); cnt[bin]++; total_cnt++; } } if (total_cnt == 0) { free(cnt); return; } for (i = 0; i < nbreaks; i++) { if (max_cnt < cnt[i]) max_cnt = cnt[i]; double start = (i * (max_val - min_val))/nbreaks + min_val; double end = ((i+1) * (max_val - min_val))/nbreaks + min_val; printf("BIN[%d] = %d / %d - [ %lf, %lf [\n", i, cnt[i], total_cnt, start, end); } /* Start from a blank canva */ scene->clear(); /* Display the histogram now */ int height = 200; int width = 100; int offsety = 100; scene->addItem(new QGraphicsLineItem(0, 0+offsety, 0, -height+offsety, NULL)); scene->addItem(new QGraphicsLineItem(0, 0+offsety, width, 0+offsety, NULL)); for (i = 0; i < nbreaks; i++) { int xstart = floor(((double)width * i)/nbreaks); int xend = floor(((double)width * (i+1))/nbreaks); int yend = floor(((double)height*cnt[i])/max_cnt); QGraphicsRectItem *rect = new QGraphicsRectItem(xstart, -yend+offsety, xend - xstart, yend, NULL); QColor col(0, 0, 255, 127); rect->setBrush(QColor(255, 0, 0, 255)); rect->brush(); scene->addItem(rect); } free(cnt); } public: Distribution() { QHBoxLayout *horizontalLayout = new QHBoxLayout(this); _text_info = new QTextEdit(); horizontalLayout->addWidget(_text_info); //QStackedWidget *stackedWidget = new QStackedWidget; scene = new QGraphicsScene(0, 0, 100, 100, this); view = new QGraphicsView(scene); horizontalLayout->addWidget(view); _nodes_selected = new QTreeWidget(); _state_names_selected = new QTreeWidget(); horizontalLayout->addWidget(_nodes_selected); horizontalLayout->addWidget(_state_names_selected); min_slider = new QSlider(); min_slider->setFocusPolicy(Qt::StrongFocus); min_slider->setTickPosition(QSlider::TicksBothSides); min_slider->setTickInterval(10); min_slider->setRange(0, 100); min_slider->setSingleStep(1); min_slider->setObjectName("totp"); min_slider->setValue(5); horizontalLayout->addWidget(min_slider); max_slider = new QSlider(); max_slider->setFocusPolicy(Qt::StrongFocus); max_slider->setTickPosition(QSlider::TicksBothSides); max_slider->setTickInterval(10); max_slider->setRange(0, 100); max_slider->setSingleStep(1); max_slider->setValue(95); horizontalLayout->addWidget(max_slider); } void init() { //_text_info->clear(); select_container(); select_state_types(); } void clear() { _text_info->clear(); } void set_arguments(std::map) {} std::string get_name() { return "Distribution"; } public slots: void execute() { _text_info->clear(); QString text ("

Distribution

"); get_statechange_distribution(text); _text_info->setHtml(text); } }; extern "C" #ifdef WIN32 __declspec(dllexport) #endif Plugin *create() { return new Distribution(); }