2026-03-18 12:10:52 -05:00
//+------------------------------------------------------------------+
//| Main.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 AIDATATASKRUNNER_BACKEND_MAIN_MQH
# define AIDATATASKRUNNER_BACKEND_MAIN_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
# include "Saver.mqh"
# include "..\\..\\UI\\Main.mqh"
# include <Generic\Queue.mqh>
# include <TSN\\ExtraCodes\\MTTester.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CExecutionTester : public ITaskRunerAi
{
private :
//---
long m_chart_id_ea_2 ; // Chart id del ea 2
TaskTester m_current_task ; // Tarea actual en configuracion
TaskTester m_tasks [ ] ; // Array de tareas
int m_tasks_size ; // Cantidad de tareas
CTaskSaver m_saver ; // Guardado y carga de tareas
const long m_current_chart_id ;
2026-04-11 17:18:10 -05:00
ENUM_MTTESTER_MODELADO_MODE m_modelado_type ;
2026-03-18 12:10:52 -05:00
//---
string m_expert_path ; // Ruta al experto que se desea ejeuctar (para ejecutarlo)
string m_main_folder ; // Folder base
2026-03-25 15:17:13 -05:00
string m_files_move_json_base_file ;
2026-03-18 12:10:52 -05:00
int m_files_common_to_move_size ; // Tamaaño de archivos a mover
string m_files_common_to_move [ ] ; // Archivos a mover
string m_progres_task_file ; // Archivo de progreso
//---
string m_base_path ;
//---
int m_current_task_procces_idx ;
// temporales (se modican en ejecucion)
string m_temp_arr_file_to_move [ ] ;
string m_temp_exp_path ; // path temproal
string m_temp_progres_csv_file ;
string m_temp_main_folder ;
//---
bool m_in_execution ; // Ahora mismo se estan ejeuctando tareas?
CTaskRunerAiTabDGenMain * m_sec_generation ;
CQueue < int > m_cola_indices ;
//---
void SentEvent ( ) ; // Envia evento
void RecibirEvento ( const bool result , const string & msg ) ;
2026-03-25 06:48:29 -05:00
bool LoadJsonMoveFiles ( const string & str ) ;
2026-03-18 12:10:52 -05:00
public :
CExecutionTester ( void ) ;
~ CExecutionTester ( void ) { }
//---
2026-04-11 17:18:10 -05:00
void Set ( CTaskRunerAiTabDGenMain * sec_gen , bool comon_in , bool comon_out , ENUM_MTTESTER_MODELADO_MODE modelado_type_ ) ;
2026-03-18 12:10:52 -05:00
//---
void InitCurrentTask ( const TaskTester & t ) override final { m_current_task = t ; }
//--- Configuracion de la tarea actual
2026-03-25 06:48:29 -05:00
bool OnCurrentTask_ModifyConfigMoveFile ( const string str ) override final ;
2026-03-18 12:10:52 -05:00
__forceinline string MoveFiles ( ) const override final
2026-03-25 21:39:19 -05:00
{ return ! m_in_execution ? m_files_move_json_base_file : m_temp_arr_file_to_move [ 0 ] ; }
2026-03-18 12:10:52 -05:00
void OnCurrentTask_ModifyConfigExpertPath ( const string str ) override final ;
__forceinline string ExperthPath ( ) const override final { return ! m_in_execution ? m_expert_path : m_temp_exp_path ; }
void OnCurrentTask_ModifyConfigProgresCsvFile ( const string str ) override final ;
__forceinline string ProgreesFile ( ) const override final { return ! m_in_execution ? m_progres_task_file : m_temp_progres_csv_file ; }
void OnCurrentTask_ModifyConfigMainFolder ( const string str ) override final ;
__forceinline string MainFolder ( ) const override final { return ! m_in_execution ? m_main_folder : m_temp_main_folder ; }
//--- Modificacion de la tarea actual
void OnCurrentTask_ModifyDateStart ( const datetime new_start ) override final ;
void OnCurrentTask_ModifyDateEnd ( const datetime new_end ) override final ;
void OnCurrentTask_ModifySimbolo ( const string new_symbol ) override final ;
void OnCurrentTask_ModifySimboloFolder ( const string new_symbol_f ) override final ;
void OnCurrentTask_ModifyTimeframe ( const ENUM_TIMEFRAMES new_tf ) override final ;
void OnCurrentTask_ModifyLabel ( const string label ) override final ;
void OnCurrentTask_ModifyLabelId ( const int label_id ) override final ;
void OnCurrentTask_ModifySetFile ( const string set_file ) override final ;
//---
bool OnCurrentTask_Add ( ) ;
int RunAllTask ( int & out [ ] ) override final ;
int CleanAllTask ( int & out [ ] ) override final ;
//--- Guardado \ Carga
bool SaveAllTaskInFile ( const string & file_name , bool only_no_proccesed ) override final ;
bool SetTastByFile ( const string & file_name ) override final ;
//---
bool LoadConfig ( const string & file_name ) override final ;
bool SaveConfig ( const string & file_name ) override final ;
// El archivo debera de estar en comon
// task: aqui se pondran todas las tareas
// retonar el numero de tareas
2026-04-10 15:42:04 -05:00
inline TaskTester GetTaskByIndex ( const int index ) const override final { return m_tasks [ index ] ; }
inline ENUM_AIEXECUTOR_TASK_STATE GetTaskStatus ( const int index ) const override final { return m_tasks [ index ] . state ; }
inline TaskTester CurrentTask ( ) const override final { return m_current_task ; }
inline int TaskSize ( ) const override final { return m_tasks_size ; }
2026-03-18 12:10:52 -05:00
//---
2026-03-18 12:55:47 -05:00
bool AddDirectTask ( const TaskTester & task ) override final ;
2026-03-18 12:10:52 -05:00
//---
void ChartEvent ( const int32_t id , const long & lparam , const double & dparam , const string & sparam ) ;
} ;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CExecutionTester : : CExecutionTester ( void )
2026-03-25 06:48:29 -05:00
: m_progres_task_file ( NULL ) , m_temp_main_folder ( NULL ) , m_current_chart_id ( ChartID ( ) ) ,
2026-03-25 15:17:13 -05:00
m_in_execution ( false ) , m_expert_path ( NULL ) , m_main_folder ( NULL ) , m_current_task_procces_idx ( -1 ) , m_files_move_json_base_file ( NULL )
2026-03-18 12:10:52 -05:00
{
m_files_common_to_move_size = ArrayResize ( m_files_common_to_move , 0 ) ;
ArrayResize ( m_temp_arr_file_to_move , 0 ) ;
AddLogger ( m_saver ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-04-11 17:18:10 -05:00
void CExecutionTester : : Set ( CTaskRunerAiTabDGenMain * sec_gen , bool comon_in , bool comon_out , ENUM_MTTESTER_MODELADO_MODE modelado_type_ )
2026-03-18 12:10:52 -05:00
{
//---
m_sec_generation = sec_gen ;
m_file_common_flag_in = comon_in ? FILE_COMMON : 0 ;
m_file_common_flag_out = comon_out ? FILE_COMMON : 0 ;
m_base_path = comon_out ? TERMINAL_MT5_COMMON_PATH : TERMINAL_MT5_DATA_PAH ;
2026-04-11 17:18:10 -05:00
m_modelado_type = modelado_type_ ;
2026-03-18 12:10:52 -05:00
//--- Abrimos el segundo grafico
// Sin
const long chart_id_ea = DEFMTTesterGetChartId ( ) ;
if ( : : ChartSymbol ( chart_id_ea ) = = " " )
{
LogError ( StringFormat ( " Chart id = %d, invalido " , chart_id_ea ) , FUNCION_ACTUAL ) ;
Remover ( ) ;
return ;
}
m_chart_id_ea_2 = chart_id_ea ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-03-25 06:48:29 -05:00
bool CExecutionTester : : OnCurrentTask_ModifyConfigMoveFile ( const string str )
2026-03-18 12:10:52 -05:00
{
2026-03-25 06:48:29 -05:00
//---
if ( ! m_in_execution )
2026-03-18 12:10:52 -05:00
{
2026-03-25 15:17:13 -05:00
m_files_move_json_base_file = str ;
2026-03-25 06:48:29 -05:00
return LoadJsonMoveFiles ( str ) ;
2026-03-18 12:10:52 -05:00
}
else
2026-03-25 06:48:29 -05:00
{
// En training guardamos el archivo
ArrayResize ( m_temp_arr_file_to_move , 1 ) ;
m_temp_arr_file_to_move [ 0 ] = str ;
return true ;
}
2026-03-18 12:10:52 -05:00
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifyConfigExpertPath ( const string str )
{
if ( m_in_execution )
{
m_temp_exp_path = str ;
}
else
{
m_expert_path = str ;
}
}
//+------------------------------------------------------------------+
// NOTA:
// EL ARCHIVO DE PROGRESO VA RELAITIVO AL MAIN_FOLDER
// por jeemplo Progreess\\temp.csv
void CExecutionTester : : OnCurrentTask_ModifyConfigProgresCsvFile ( const string str )
{
if ( m_in_execution )
{
m_temp_progres_csv_file = m_temp_main_folder + str ;
}
else
{
m_progres_task_file = m_main_folder + str ;
}
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifyConfigMainFolder ( const string str )
{
if ( m_in_execution )
{
m_temp_main_folder = str ;
}
else
{
m_main_folder = str ;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifyDateStart ( const datetime new_start )
{
m_current_task . start_date = new_start ;
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifyDateEnd ( const datetime new_end )
{
m_current_task . end_date = new_end ;
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifySimbolo ( const string new_symbol )
{
m_current_task . symbol = new_symbol ;
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifySimboloFolder ( const string new_symbol_f )
{
m_current_task . symbol_folder = new_symbol_f ;
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifyTimeframe ( const ENUM_TIMEFRAMES new_tf )
{
m_current_task . timeframe = new_tf ;
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifyLabel ( const string label )
{
m_current_task . label = label ;
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifyLabelId ( const int label_id )
{
m_current_task . label_id = label_id ;
}
//+------------------------------------------------------------------+
void CExecutionTester : : OnCurrentTask_ModifySetFile ( const string set_file )
{
2026-04-11 17:18:10 -05:00
// set file debe de tener la ruta completa (asi que la aumtentamos)
// el user solo pone la relative a Pro
2026-04-11 16:24:48 -05:00
m_current_task . set_file = TERMINAL_MT5_ROOT + " Profiles \\ Tester \\ " + set_file ;
2026-03-18 12:10:52 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester : : OnCurrentTask_Add ( void )
{
//---
m_last_error_msg = " " ;
bool res = true ;
bool is_cts ;
//---
if ( m_main_folder = = NULL )
{
m_last_error_msg + = " Main folder invalido| " ;
res = false ;
}
if ( m_expert_path .Length ( ) < 4 | | StringFindAtras ( m_expert_path , " .ex5 " ) = = -1 )
{
m_last_error_msg + = " Path invalido o extension no es ex5| " ;
res = false ;
}
//--- Como tal de la tarea
if ( ! : : SymbolExist ( m_current_task . symbol , is_cts ) )
{
2026-03-18 21:52:07 -05:00
m_last_error_msg + = " Simbolo no existe " + m_current_task . symbol + " | " ;
2026-03-18 12:10:52 -05:00
res = false ;
}
if ( m_current_task . timeframe = = WRONG_VALUE )
{
m_last_error_msg + = " Timeframe no configurado| " ;
res = false ;
}
if ( m_current_task . start_date > = m_current_task . end_date )
{
m_last_error_msg + = " Fecha inicio debe ser menor a fecha fin| " ;
res = false ;
}
//---
if ( ! res )
LogError ( m_last_error_msg , FUNCION_ACTUAL ) ;
else
{
: : ArrayResize ( m_tasks , m_tasks_size + 1 ) ;
m_tasks [ m_tasks_size ] = m_current_task ;
m_tasks_size + + ;
}
//---
return res ;
}
2026-03-18 12:55:47 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester : : AddDirectTask ( const TaskTester & task ) override final
{
//---
m_last_error_msg = " " ;
bool res = true ;
bool is_cts ;
2026-03-18 12:10:52 -05:00
2026-03-18 12:55:47 -05:00
//---
if ( m_main_folder = = NULL )
{
m_last_error_msg + = " Main folder invalido| " ;
res = false ;
}
if ( m_expert_path .Length ( ) < 4 | | StringFindAtras ( m_expert_path , " .ex5 " ) = = -1 )
{
m_last_error_msg + = " Path invalido o extension no es ex5| " ;
res = false ;
}
//--- Como tal de la tarea
2026-03-18 21:52:07 -05:00
if ( ! : : SymbolExist ( task . symbol , is_cts ) )
2026-03-18 12:55:47 -05:00
{
2026-03-25 06:48:29 -05:00
m_last_error_msg + = " Simbolo no existe " + task . symbol + " | " ;
2026-03-18 12:55:47 -05:00
res = false ;
}
2026-03-18 21:52:07 -05:00
if ( task . timeframe = = WRONG_VALUE )
2026-03-18 12:55:47 -05:00
{
m_last_error_msg + = " Timeframe no configurado| " ;
res = false ;
}
2026-03-18 21:52:07 -05:00
if ( task . start_date > = task . end_date )
2026-03-18 12:55:47 -05:00
{
m_last_error_msg + = " Fecha inicio debe ser menor a fecha fin| " ;
res = false ;
}
//---
if ( ! res )
LogError ( m_last_error_msg , FUNCION_ACTUAL ) ;
else
{
: : ArrayResize ( m_tasks , m_tasks_size + 1 ) ;
m_tasks [ m_tasks_size ] = task ;
m_tasks_size + + ;
m_sec_generation . AddTaskToTable ( task ) ;
}
//---
return res ;
}
2026-03-25 06:48:29 -05:00
2026-03-18 12:10:52 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// Aquilimpiamos todas las tareas que se puedan limpiar
// Osea que esa tarea NO se este procesando o este en cola a ser ejecutada
int CExecutionTester : : CleanAllTask ( int & out [ ] )
{
//---
m_last_error_msg = " " ;
//--- Sin tareas
if ( m_tasks_size < = 0 )
{
m_last_error_msg = " No hay tareas para limpiar " ;
return 0 ;
}
//---
for ( int i = 0 ; i < m_tasks_size ; i + + )
{
if ( m_tasks [ i ] . state = = AIEXECUTOR_TASK_STATE_IN_PROCESS | | m_tasks [ i ] . state = = AIEXECUTOR_TASK_STATE_IN_QUEQE )
continue ; // No
out .Push ( i ) ;
}
m_tasks_size = RemoveMultipleIndexes ( m_tasks , out , 0 ) ;
return ArraySize ( out ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CExecutionTester : : RunAllTask ( int & out [ ] )
{
//---
m_last_error_msg = " " ;
//--- Sin tareas
if ( m_tasks_size < = 0 )
{
m_last_error_msg = " No hay tareas para ejecutar " ;
return 0 ;
}
//---
int t = 0 ;
//---
for ( int i = 0 ; i < m_tasks_size ; i + + )
{
if ( m_tasks [ i ] . state = = AIEXECUTOR_TASK_STATE_PENDIENTE )
{
// Actuliazamos el estado
m_tasks [ i ] . state = AIEXECUTOR_TASK_STATE_IN_QUEQE ;
// Añadimos a la cola interna
m_cola_indices . Enqueue ( i ) ; // Agregamos este elemento a la cola
// Añadimos al array out
out [ : : ArrayResize ( out , + + t ) - 1 ] = i ;
}
}
//--- Sin tareas pendientes
if ( t < 1 )
{
m_last_error_msg = " No hay tareas pendientes para ejecutar " ;
}
else
{
//---
LogInfo ( StringFormat ( " Numero de tareas en cola a ejeuctar = %d " , m_cola_indices . Count ( ) ) , FUNCION_ACTUAL ) ;
m_in_execution = true ;
//--- Valor incial de los temp
m_temp_main_folder = m_main_folder ;
m_temp_exp_path = m_expert_path ;
m_temp_progres_csv_file = m_progres_task_file ;
ArrayCopy ( m_temp_arr_file_to_move , m_files_common_to_move ) ;
// Mandamos el primer evento
SentEvent ( ) ;
}
//---
return t ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CExecutionTester : : SentEvent ( )
{
if ( m_cola_indices . Count ( ) < 1 )
{
LogCaution ( " Todas las tareas han acabado " , FUNCION_ACTUAL ) ;
m_in_execution = false ; // Termino
//--- asing de los temp
m_main_folder = m_temp_main_folder ;
m_expert_path = m_temp_exp_path ;
m_progres_task_file = m_temp_progres_csv_file ;
2026-03-31 22:09:17 -05:00
//---
m_current_task_procces_idx = -1 ; // reinit
2026-03-25 06:48:29 -05:00
//---
// Puede no haber valores... de str
if ( ArraySize ( m_temp_arr_file_to_move ) = = 1 )
{
2026-03-25 15:17:13 -05:00
if ( m_temp_arr_file_to_move [ 0 ] ! = m_files_common_to_move [ 0 ] ) // No hay modifiacion asi que retornamos no tiene sentido seguir aqui
2026-03-25 06:48:29 -05:00
return ;
2026-03-25 15:17:13 -05:00
//---
m_files_move_json_base_file = m_temp_arr_file_to_move [ 0 ] ; // Asignamos el archivo
LoadJsonMoveFiles ( m_files_move_json_base_file ) ;
2026-03-25 06:48:29 -05:00
}
2026-03-18 12:10:52 -05:00
return ;
}
//---
const int idx = m_cola_indices . Dequeue ( ) ;
2026-03-31 22:09:17 -05:00
//---
const string full_path = AIDATATASKRUNER_PATH_TASK + " Com \\ data.csv " ;
2026-04-11 17:18:10 -05:00
if ( ! DEFMMTesterCreateFileWriteData ( full_path , AIDATATASK_RUNNER_COMON_FLAG_VAL , m_tasks [ idx ] . ToStringToMTTester ( m_current_chart_id , m_expert_path , m_modelado_type ) ) )
2026-03-31 22:09:17 -05:00
{
//--- Imprimimos error
LogError ( StringFormat ( " Fallo al ejecutar el indice en cola = %d " , idx ) , FUNCION_ACTUAL ) ;
// Actulizamso el fronted le decimos que fallo la ejecuion del evento
m_tasks [ idx ] . state = AIEXECUTOR_TASK_STATE_FAILED ;
m_sec_generation . UpdateStateInTable ( idx , m_tasks [ idx ] . state ) ;
//--- Continuamos
SentEvent ( ) ;
//---
return ;
}
: : EventChartCustom ( m_chart_id_ea_2 , DEFMTTESTER_E_ON_TASK , m_current_chart_id , DEFMTTESTER_TO_DBL_ON_TASK ( AIDATATASK_RUNNER_COMON_FLAG_VAL ) , full_path ) ;
//---
2026-03-18 12:10:52 -05:00
m_tasks [ idx ] . state = AIEXECUTOR_TASK_STATE_IN_PROCESS ;
m_sec_generation . UpdateStateInTable ( idx , m_tasks [ idx ] . state ) ;
m_current_task_procces_idx = idx ;
}
2026-03-25 06:48:29 -05:00
2026-03-18 12:10:52 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CExecutionTester : : RecibirEvento ( const bool result , const string & msg )
{
//---
if ( m_current_task_procces_idx < 0 | | m_current_task_procces_idx > = m_tasks_size )
{
LogError ( " Índice de tarea inválido en RecibirEvento, posible llamada desconocida " , FUNCION_ACTUAL ) ;
return ;
}
//---
if ( result )
{
//---
m_tasks [ m_current_task_procces_idx ] . state = AIEXECUTOR_TASK_STATE_FINISHED ;
//---
string tf = : : EnumToString ( m_tasks [ m_current_task_procces_idx ] . timeframe ) ;
: : StringReplace ( tf , " PERIOD_ " , " " ) ;
// main folder debe de tener \
const string final_ubicaction_folder = : : StringFormat ( " %s%s \\ %s \\ %s_%d \\ " , m_main_folder , m_tasks [ m_current_task_procces_idx ] . symbol_folder , tf ,
m_tasks [ m_current_task_procces_idx ] . label , m_tasks [ m_current_task_procces_idx ] . label_id ) ;
//---
if ( m_files_common_to_move_size > 0 )
{
2026-03-25 06:48:29 -05:00
//---
// creamos el folder por si acaso quizas exista entonces supongo qeu no pasara nada si no existe no lo creamos vale?
// por lo visto filemove pide ya la ruta hecha no la contruye asi que tenemos que crearla
: : ResetLastError ( ) ;
if ( ! : : FolderCreate ( final_ubicaction_folder , m_file_common_flag_out ) )
{
LogWarning ( StringFormat ( " Fallo al crear el folder = %s, ultimo error =%d " , final_ubicaction_folder , : : GetLastError ( ) ) , FUNCION_ACTUAL ) ;
}
//---
2026-03-18 12:10:52 -05:00
// Aqui movemos...
for ( int i = 0 ; i < m_files_common_to_move_size ; i + + )
{
//--- Movemos
: : ResetLastError ( ) ;
2026-03-31 22:09:17 -05:00
const string file_out = final_ubicaction_folder + ( m_files_common_to_move [ i + m_files_common_to_move_size ] ) ; // archivo final el offset de size indica que leermos la version sin el path tla cual
2026-03-25 06:48:29 -05:00
if ( ! : : FileMove ( m_files_common_to_move [ i ] , m_file_common_flag_in , file_out , FILE_REWRITE | m_file_common_flag_out ) )
2026-03-18 12:10:52 -05:00
{
LogError ( : : StringFormat ( " No se pudo mover el archivo =%s, a = %s, ultimo error = %d "
2026-03-25 06:48:29 -05:00
, m_files_common_to_move [ i ] , file_out , : : GetLastError ( ) ) , FUNCION_ACTUAL ) ;
2026-03-18 12:10:52 -05:00
}
}
}
//--- Copiamos el setfile
if ( : : StringLen ( m_tasks [ m_current_task_procces_idx ] . set_file ) > 4 ) // .set
{
2026-03-30 15:00:40 -05:00
const string out = m_base_path + " \\ Files \\ " + final_ubicaction_folder + GetPureFileName ( m_tasks [ m_current_task_procces_idx ] . set_file ) ; // donde se pondra (le quitamos cualquier anidacion que halla)
2026-04-13 17:42:23 -05:00
// Nota set_file tiene ruta completa
if ( ! MTTESTER : : FileCopy ( m_tasks [ m_current_task_procces_idx ] . set_file , out , true ) ) // copiamos no movemos
2026-03-18 12:10:52 -05:00
{
2026-04-13 17:42:23 -05:00
LogError ( : : StringFormat ( " Fallo al mover: \n %s \n A \n %s \n Ultimo error en kernel32 = %d " , m_tasks [ m_current_task_procces_idx ] . set_file , out , kernel32 : : GetLastError ( ) ) , FUNCION_ACTUAL ) ;
2026-03-18 12:10:52 -05:00
}
}
//--- Guardamos progreso
// El progreso se guarda junto con los archivos out (data que pertenece al backend)
// solo se guardan las tareas (proceseando|pendientes|encola)
2026-03-25 06:48:29 -05:00
if ( m_progres_task_file .Length ( ) > 4 ) // .txt \ .csv
2026-03-18 12:10:52 -05:00
{
m_last_error_msg = " " ;
if ( ! m_saver . Save ( m_progres_task_file , m_tasks , m_tasks_size , m_file_common_flag_out , true , m_last_error_msg ) ) // filtrasmos solo guramos lo necesario
{
LogError ( StringFormat ( " Fallo al guardar progreso en el archivo csv, %s " , m_last_error_msg ) , FUNCION_ACTUAL ) ;
}
}
}
else
{
m_tasks [ m_current_task_procces_idx ] . state = AIEXECUTOR_TASK_STATE_FAILED ;
LogError ( StringFormat ( " Fallo al procesar la tarea #%d, msg: \n %s " , m_current_task_procces_idx , msg ) , FUNCION_ACTUAL ) ;
}
//---
m_sec_generation . UpdateStateInTable ( m_current_task_procces_idx , m_tasks [ m_current_task_procces_idx ] . state ) ; // Actulizar el estado
//---
SentEvent ( ) ; // Lanzamos el siguiente evento (intemante se verifica si es que hay tareas ono)
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CExecutionTester : : ChartEvent ( const int id , const long & lparam , const double & dparam , const string & sparam )
{
//--- de vuelta
//lparam = combinacion de banderas en caso de error 0 exito total
//sparam = se empaqueta como (chartid|log)
//dparam = nada
//---
// Si se finaliza
if ( id = = CHARTEVENT_CUSTOM + DEFMTTESTER_E_FINISH_TASK )
{
//---
static string arr [ 2 ] ;
if ( StringSplit ( sparam , DEFMTTESTER_OUT_SPARAM_SEP_U , arr ) ! = DEFMTTESTER_OUT_SPARAM_TOTAL ) // formato invalido
{
return ;
}
//---
const long chart_id = long ( arr [ DEFMTTESTER_OUT_SPARAM_IDX_CHARTID ] ) ;
Print ( " Nuevo evento chart_id = " , chart_id ) ;
if ( chart_id ! = m_current_chart_id )
return ;
LogInfo ( StringFormat ( " Evento recibido desde = %I64d | Resultado = %I64d " , chart_id , lparam ) , FUNCION_ACTUAL ) ;
RecibirEvento ( ( lparam = = DEFMTTESTER_TESTER_R_EXITO ) , arr [ DEFMTTESTER_OUT_SPARAM_IDX_LOG ] ) ;
}
}
2026-03-25 06:48:29 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester : : LoadJsonMoveFiles ( const string & str )
{
: : ResetLastError ( ) ;
2026-03-25 12:58:33 -05:00
const int fh = FileOpen ( str , FILE_BIN | FILE_READ | m_file_common_flag_out ) ;
2026-03-25 06:48:29 -05:00
if ( fh = = INVALID_HANDLE )
{
2026-03-25 15:17:13 -05:00
m_last_error_msg = StringFormat ( " Fallo al leer el archivo = %s, ultimo error = %d " , str , : : GetLastError ( ) ) ;
LogFatalError ( m_last_error_msg , FUNCION_ACTUAL ) ;
2026-03-25 06:48:29 -05:00
return false ;
}
2026-03-25 12:58:33 -05:00
//---
const ulong size = : : FileSize ( fh ) ;
string file_content = : : FileReadString ( fh , int ( size ) ) ;
file_content .SetChar ( 0 , ' ' ) ; // quitamos el boom
: : FileClose ( fh ) ;
2026-03-25 15:17:13 -05:00
2026-03-25 12:58:33 -05:00
//---
2026-03-25 06:48:29 -05:00
CJson json ;
2026-03-25 12:58:33 -05:00
if ( json . Parse ( file_content ) ) // omitimos el bom del incio del utf16le
2026-03-25 06:48:29 -05:00
{
CJsonNode files_to_move_arr = json [ " files_to_move " ] ;
2026-03-25 12:58:33 -05:00
//---
if ( ! files_to_move_arr . IsValid ( ) )
{
2026-03-25 15:17:13 -05:00
m_last_error_msg = " El key 'files_to_move' no existe en el json " ;
LogFatalError ( m_last_error_msg , FUNCION_ACTUAL ) ;
2026-03-25 12:58:33 -05:00
return false ;
}
2026-03-25 06:48:29 -05:00
if ( ! files_to_move_arr . IsArray ( ) )
{
2026-03-25 15:17:13 -05:00
m_last_error_msg = " El key 'files_to_move' no es un array " ;
LogFatalError ( m_last_error_msg , FUNCION_ACTUAL ) ;
2026-03-25 06:48:29 -05:00
return false ;
}
2026-03-25 12:58:33 -05:00
//---
2026-03-25 06:48:29 -05:00
m_files_common_to_move_size = files_to_move_arr .Size ( ) ;
2026-03-25 22:18:11 -05:00
ArrayResize ( m_files_common_to_move , m_files_common_to_move_size < < 1 ) ;
2026-03-25 06:48:29 -05:00
for ( int i = 0 ; i < m_files_common_to_move_size ; i + + )
{
m_files_common_to_move [ i ] = files_to_move_arr [ i ] . ToString ( ) ;
2026-03-25 22:18:11 -05:00
m_files_common_to_move [ i + m_files_common_to_move_size ] = GetPureFileName ( m_files_common_to_move [ i ] ) ;
2026-03-25 06:48:29 -05:00
}
}
else
{
2026-03-25 15:17:13 -05:00
m_last_error_msg = StringFormat ( " Fallo al parsear el json de archivos a mover =%s, ultimo error de json parser = %s " , str , EnumToString ( EnumJsonError ( json . GetLastError ( ) ) ) ) ;
LogError ( m_last_error_msg , FUNCION_ACTUAL ) ;
2026-03-25 06:48:29 -05:00
return false ;
}
//---
return true ;
}
2026-03-18 12:10:52 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester : : LoadConfig ( const string & file_name )
{
m_last_error_msg = " " ;
if ( ! m_in_execution )
{
2026-03-25 15:17:13 -05:00
if ( ! m_saver . LoadC ( file_name , AIDATATASK_RUNNER_COMON_FLAG , m_last_error_msg , m_progres_task_file , m_files_move_json_base_file , m_main_folder , m_expert_path ) )
return false ;
return LoadJsonMoveFiles ( m_files_move_json_base_file ) ;
2026-03-18 12:10:52 -05:00
}
else
{
2026-03-25 15:17:13 -05:00
// El valor de 0 lo usamos para cargar en el indicae 0, duranete la generacion de datos solo almcenemos ese valor en el array pos 0
return m_saver . LoadC ( file_name , AIDATATASK_RUNNER_COMON_FLAG , m_last_error_msg , m_temp_progres_csv_file , m_temp_arr_file_to_move [ 0 ] , m_temp_main_folder , m_temp_exp_path ) ;
2026-03-18 12:10:52 -05:00
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester : : SaveConfig ( const string & file_name )
{
m_last_error_msg = " " ;
if ( ! m_in_execution )
{
2026-03-25 15:17:13 -05:00
return m_saver . SaveC ( file_name , AIDATATASK_RUNNER_COMON_FLAG , m_last_error_msg , m_progres_task_file , m_files_move_json_base_file , m_main_folder , m_expert_path ) ;
2026-03-18 12:10:52 -05:00
}
else
{
2026-03-25 15:17:13 -05:00
return m_saver . SaveC ( file_name , AIDATATASK_RUNNER_COMON_FLAG , m_last_error_msg , m_temp_progres_csv_file , m_temp_arr_file_to_move [ 0 ] , m_temp_main_folder , m_temp_exp_path ) ;
2026-03-18 12:10:52 -05:00
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester : : SaveAllTaskInFile ( const string & file_name , bool only_no_proccesed )
{
// usamos el valor de (is common flag) del global config que tine epuesto el fronted.. para almcenar los archivos
// only_no_proccesed = true ? entonces solo se guarda las que NO se procesaron al 100% (en cola|pendicente|procesando) : se gurada todo (inlcuido los no procesado)
m_last_error_msg = " " ;
return m_saver . Save ( file_name , m_tasks , m_tasks_size , AIDATATASK_RUNNER_COMON_FLAG , only_no_proccesed , m_last_error_msg ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester : : SetTastByFile ( const string & file_name )
{
2026-03-31 22:09:17 -05:00
//--- Check quizas fallo al cargar
2026-03-18 12:10:52 -05:00
m_last_error_msg = " " ;
2026-03-31 22:09:17 -05:00
if ( ! m_saver . Load ( file_name , m_tasks , m_tasks_size , AIDATATASK_RUNNER_COMON_FLAG , m_last_error_msg ) )
return false ;
//--- No se agrego
if ( m_tasks_size < 1 )
{
m_last_error_msg = " 0 task added " ;
return false ;
}
return true ;
2026-03-18 12:10:52 -05:00
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
# endif // AIDATATASKRUNNER_BACKEND_MAIN_MQH