//+------------------------------------------------------------------+ //| ResVisualizer.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372 | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372" #property strict #ifndef AIDATATASKRUNER_UI_TRAINING_RESVISUALIZER_MQH #define AIDATATASKRUNER_UI_TRAINING_RESVISUALIZER_MQH //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #include "ResultsTab.mqh" //+------------------------------------------------------------------+ //| Defines \ Enums \ Struct | //+------------------------------------------------------------------+ // Valor key para el hashmap #define AIDATATASKRUNER_TRAINIG_PY_KEY(A) (A["path"].ToString()+A["type"].ToString()) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CTrainingPyVisualizer : public CTrainingResultsAlmacenador { private: //--- CTextBox m_text_box; //--- void OnAntesClear() override final; // Function executed each time a new element is added at index new_pos void OnNewElement(int new_pos, int8_t action) override final; // Function executed each time an element is deleted at delete_pos void OnDeleteElement(int delete_pos, CJson* item, int8_t action) override final; // Funcion on swap void OnSwap(int pos1, int pos2) override final; // Cambio masivo void OnMasiveIndexChange() override final; public: CTrainingPyVisualizer(void) {} ~CTrainingPyVisualizer(void) {} //--- bool Set(int top_gap, int left_gap, int right_gap, int bottom_gap, CWindow* win, CWndCreate* wnd_create) override final; void Show(const string path, const string type) override final; void OnLenguajeChange() override final {} // Nada no necesitamos //--- void OnTrainingInit() override final; void OnTrainingNewResult(CJson* json) override final; //--- __forceinline uint8_t EventsFlags() const override final { return TRAINING_RUNNER_PY_FLAG_ON_TRAINIG | TRAINING_RUNNER_PY_FLAG_ON_INIT; } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingPyVisualizer::Set(int top_gap, int left_gap, int right_gap, int bottom_gap, CWindow *win, CWndCreate *wnd_create) { //--- TextBox m_text_box.MainPointer(win); m_text_box.FontSize(10); m_text_box.Font("Arial"); m_text_box.MultiLineMode(true); m_text_box.WordWrapMode(false); m_text_box.ReadOnlyMode(true); m_text_box.AutoXResizeMode(true); m_text_box.AutoXResizeRightOffset(right_gap); m_text_box.AutoYResizeMode(true); m_text_box.AutoYResizeBottomOffset(bottom_gap); m_text_box.SelectedTextColor(C'61,142,240'); m_text_box.SelectedBackColor(clrAquamarine); m_text_box.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_text_box.BackColor(AIDATATASKRUNER_COLOR_FONDO_TAB_PRESSED); m_text_box.BackColorHover(AIDATATASKRUNER_COLOR_FONDO_TAB_PRESSED); m_text_box.BackColorPressed(AIDATATASKRUNER_COLOR_FONDO_TAB_PRESSED); m_base_tab.AddToElementsArray(m_base_tab_idx, m_text_box); //--- if(!m_text_box.CreateTextBox(left_gap, top_gap)) { GUIBASE_ERROR_CREATION(m_text_box); return false; } //--- wnd_create.AddToElementsArray(0, m_text_box); return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::OnAntesClear(void) { m_hash_key_to_hist_index.Clear(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::OnSwap(int pos1, int pos2) { // items ya están intercambiados cuando llega aquí // items[pos1] el que ANTES estaba en pos2 // items[pos2] el que ANTES estaba en pos1 // Solo actualizar las 2 entradas del hash m_hash_key_to_hist_index.TrySetValue(AIDATATASKRUNER_TRAINIG_PY_KEY(items[pos1]), pos1); m_hash_key_to_hist_index.TrySetValue(AIDATATASKRUNER_TRAINIG_PY_KEY(items[pos2]), pos2); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::OnMasiveIndexChange(void) { m_hash_key_to_hist_index.Clear(); for(int i = 0; i < total; i++) { m_hash_key_to_hist_index.Add(AIDATATASKRUNER_TRAINIG_PY_KEY(items[i]), i); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::OnNewElement(int new_pos, char action) { //--- switch(action) { // No hay recalculo dado que estas acciones no afectan los indices de los demas case MANAGER_BASE_ACTION_NEWEL_PUSH: case MANAGER_BASE_ACTION_NEWEL_REPLACE: { if(!m_hash_key_to_hist_index.Add(AIDATATASKRUNER_TRAINIG_PY_KEY(items[new_pos]), new_pos)) { LogError(StringFormat("No se pudo agregar la key [%s]", AIDATATASKRUNER_TRAINIG_PY_KEY(items[new_pos])), FUNCION_ACTUAL); Remove(new_pos); // manda hook de ondelete } break; } case MANAGER_BASE_ACTION_NEWEL_INSERT: { // Desde la posicion que se inserto hasta el final if(!m_hash_key_to_hist_index.Add(AIDATATASKRUNER_TRAINIG_PY_KEY(items[new_pos]), new_pos)) { LogError(StringFormat("No se pudo agregar la key[%s]", AIDATATASKRUNER_TRAINIG_PY_KEY(items[new_pos])), FUNCION_ACTUAL); Remove(new_pos); // manda hook de ondelete // Nota: dado que el remove lo que hace es <= enotnces las clasvez volieron a su valor original } else { // No hay repeiticon de key todo en orden entonces lo que haremos sera modificar los valores en adelante for(int i = new_pos + 1; i < total; i++) { m_hash_key_to_hist_index.TrySetValue(AIDATATASKRUNER_TRAINIG_PY_KEY(items[i]), i); // Cambia el indice } } break; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::OnDeleteElement(int delete_pos, CJson* item, int8_t action) { switch(action) { //--- case MANAGER_BASE_ACTION_DEL_REMOVE: { // Eliminar del hash if(!m_hash_key_to_hist_index.Remove(AIDATATASKRUNER_TRAINIG_PY_KEY(item))) LogError(StringFormat("No se pudo eliminar tool[%s]", AIDATATASKRUNER_TRAINIG_PY_KEY(item)), FUNCION_ACTUAL); // Actualizar índices desde delete_pos en adelante // OJO: en este punto el array AÚN no se desplazó // items[delete_pos] sigue siendo el eliminado // items[delete_pos+1..total-1] son los que bajarán un índice for(int i = delete_pos + 1; i < total; i++) { m_hash_key_to_hist_index.TrySetValue(AIDATATASKRUNER_TRAINIG_PY_KEY(items[i]), i - 1); //i-1 nuevo indice predecible } break; } //--- case MANAGER_BASE_ACTION_DEL_DELETE: case MANAGER_BASE_ACTION_DEL_REPLACE: case MANAGER_BASE_ACTION_DEL_REMOVE_LAST: { // No desplazan índices — solo eliminar del hash if(!m_hash_key_to_hist_index.Remove(AIDATATASKRUNER_TRAINIG_PY_KEY(item))) LogError(StringFormat("No se pudo eliminar tool[%s]", AIDATATASKRUNER_TRAINIG_PY_KEY(item)), FUNCION_ACTUAL); break; } //--- case MANAGER_BASE_ACTION_CLEAR_ITEMS: break; // OnAntesClear ya limpia el hash } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::OnTrainingInit() { CleanItems(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::OnTrainingNewResult(CJson *json) { AddItemFast(json); // Añadifmos a fastr (aqui habra hock) } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ /* // type = clasificacion self.m_metrics = { 'accuracy': accuracy, 'precision': precision, 'recall': recall, 'f1_score': f1 } // type = regresion */ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingPyVisualizer::Show(const string path, const string type) { static int out; if(m_hash_key_to_hist_index.TryGetValue(path + type, out)) { //--- m_text_box.ClearTextBox(); //--- CJsonIterator it = items[out]["metrics"].begin(); while(it.IsValid()) { //--- const string key = it.Key(); CJsonNode val = it.Val(); //--- string display = ""; if(val.IsNumber()) display = ::DoubleToString(val.ToDouble(), 4); else display = val.ToString(); //--- m_text_box.AddLine(key + ": " + display); //--- it.Next(); } //--- m_text_box.Update(true); } else { LogError(StringFormat("Key [%s] no existe en el hash map", (path + type)), FUNCION_ACTUAL); } } #endif // AIDATATASKRUNER_UI_TRAINING_RESVISUALIZER_MQH