2026-03-20 21:41:01 -05:00
//+------------------------------------------------------------------+
//| 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 ;
2026-03-21 08:06:31 -05:00
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 ; }
2026-03-20 21:41:01 -05:00
} ;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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
}
}
2026-03-21 08:06:31 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTrainingPyVisualizer : : OnTrainingInit ( )
{
CleanItems ( true ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTrainingPyVisualizer : : OnTrainingNewResult ( CJson * json )
{
AddItemFast ( json ) ; // Añadifmos a fastr (aqui habra hock)
}
2026-03-20 21:41:01 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/*
// 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 ( ) ;
}
2026-03-21 08:06:31 -05:00
//---
m_text_box . Update ( true ) ;
2026-03-20 21:41:01 -05:00
}
else
{
2026-03-21 08:06:31 -05:00
LogError ( StringFormat ( " Key [%s] no existe en el hash map " , ( path + type ) ) , FUNCION_ACTUAL ) ;
2026-03-20 21:41:01 -05:00
}
}
# endif // AIDATATASKRUNER_UI_TRAINING_RESVISUALIZER_MQH