AiDataTaskRuner/UI/Training/ResVisualizer.mqh
Nique_372 c5471c1153
2026-03-21 08:06:31 -05:00

293 lines
11 KiB
MQL5

//+------------------------------------------------------------------+
//| 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