AiDataTaskRuner/Backend/Tester/Main.mqh
Nique_372 7f18f1f4f2
2026-04-13 17:42:23 -05:00

787 lines
28 KiB
MQL5

//+------------------------------------------------------------------+
//| 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;
ENUM_MTTESTER_MODELADO_MODE m_modelado_type;
//---
string m_expert_path; // Ruta al experto que se desea ejeuctar (para ejecutarlo)
string m_main_folder; // Folder base
string m_files_move_json_base_file;
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);
bool LoadJsonMoveFiles(const string& str);
public:
CExecutionTester(void);
~CExecutionTester(void) {}
//---
void Set(CTaskRunerAiTabDGenMain *sec_gen, bool comon_in, bool comon_out, ENUM_MTTESTER_MODELADO_MODE modelado_type_);
//---
void InitCurrentTask(const TaskTester& t) override final { m_current_task = t; }
//--- Configuracion de la tarea actual
bool OnCurrentTask_ModifyConfigMoveFile(const string str) override final;
__forceinline string MoveFiles() const override final
{ return !m_in_execution ? m_files_move_json_base_file : m_temp_arr_file_to_move[0]; }
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
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; }
//---
bool AddDirectTask(const TaskTester& task) override final;
//---
void ChartEvent(const int32_t id, const long& lparam, const double& dparam, const string& sparam);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CExecutionTester::CExecutionTester(void)
: m_progres_task_file(NULL), m_temp_main_folder(NULL), m_current_chart_id(ChartID()),
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)
{
m_files_common_to_move_size = ArrayResize(m_files_common_to_move, 0);
ArrayResize(m_temp_arr_file_to_move, 0);
AddLogger(m_saver);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CExecutionTester::Set(CTaskRunerAiTabDGenMain *sec_gen, bool comon_in, bool comon_out, ENUM_MTTESTER_MODELADO_MODE modelado_type_)
{
//---
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;
m_modelado_type = modelado_type_;
//--- 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;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester::OnCurrentTask_ModifyConfigMoveFile(const string str)
{
//---
if(!m_in_execution)
{
m_files_move_json_base_file = str;
return LoadJsonMoveFiles(str);
}
else
{
// En training guardamos el archivo
ArrayResize(m_temp_arr_file_to_move, 1);
m_temp_arr_file_to_move[0] = str;
return true;
}
}
//+------------------------------------------------------------------+
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)
{
// set file debe de tener la ruta completa (asi que la aumtentamos)
// el user solo pone la relative a Pro
m_current_task.set_file = TERMINAL_MT5_ROOT + "Profiles\\Tester\\" + set_file;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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))
{
m_last_error_msg += "Simbolo no existe " + m_current_task.symbol + "|";
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;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester::AddDirectTask(const TaskTester& task) override final
{
//---
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(task.symbol, is_cts))
{
m_last_error_msg += "Simbolo no existe " + task.symbol + "|";
res = false;
}
if(task.timeframe == WRONG_VALUE)
{
m_last_error_msg += "Timeframe no configurado|";
res = false;
}
if(task.start_date >= 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] = task;
m_tasks_size++;
m_sec_generation.AddTaskToTable(task);
}
//---
return res;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// 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;
//---
m_current_task_procces_idx = -1; // reinit
//---
// Puede no haber valores... de str
if(ArraySize(m_temp_arr_file_to_move) == 1)
{
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
return;
//---
m_files_move_json_base_file = m_temp_arr_file_to_move[0]; // Asignamos el archivo
LoadJsonMoveFiles(m_files_move_json_base_file);
}
return;
}
//---
const int idx = m_cola_indices.Dequeue();
//---
const string full_path = AIDATATASKRUNER_PATH_TASK + "Com\\data.csv";
if(!DEFMMTesterCreateFileWriteData(full_path, AIDATATASK_RUNNER_COMON_FLAG_VAL, m_tasks[idx].ToStringToMTTester(m_current_chart_id, m_expert_path, m_modelado_type)))
{
//--- 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);
//---
m_tasks[idx].state = AIEXECUTOR_TASK_STATE_IN_PROCESS;
m_sec_generation.UpdateStateInTable(idx, m_tasks[idx].state);
m_current_task_procces_idx = idx;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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)
{
//---
// 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);
}
//---
// Aqui movemos...
for(int i = 0; i < m_files_common_to_move_size; i++)
{
//--- Movemos
::ResetLastError();
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
if(!::FileMove(m_files_common_to_move[i], m_file_common_flag_in, file_out, FILE_REWRITE | m_file_common_flag_out))
{
LogError(::StringFormat("No se pudo mover el archivo =%s, a = %s, ultimo error = %d"
, m_files_common_to_move[i], file_out, ::GetLastError()), FUNCION_ACTUAL);
}
}
}
//--- Copiamos el setfile
if(::StringLen(m_tasks[m_current_task_procces_idx].set_file) > 4) // .set
{
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)
// Nota set_file tiene ruta completa
if(!MTTESTER::FileCopy(m_tasks[m_current_task_procces_idx].set_file, out, true)) // copiamos no movemos
{
LogError(::StringFormat("Fallo al mover:\n%s\nA\n%s\nUltimo error en kernel32 = %d", m_tasks[m_current_task_procces_idx].set_file, out, kernel32::GetLastError()), FUNCION_ACTUAL);
}
}
//--- Guardamos progreso
// El progreso se guarda junto con los archivos out (data que pertenece al backend)
// solo se guardan las tareas (proceseando|pendientes|encola)
if(m_progres_task_file.Length() > 4) // .txt \ .csv
{
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]);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester::LoadJsonMoveFiles(const string& str)
{
::ResetLastError();
const int fh = FileOpen(str, FILE_BIN | FILE_READ | m_file_common_flag_out);
if(fh == INVALID_HANDLE)
{
m_last_error_msg = StringFormat("Fallo al leer el archivo = %s, ultimo error = %d", str, ::GetLastError());
LogFatalError(m_last_error_msg, FUNCION_ACTUAL);
return false;
}
//---
const ulong size = ::FileSize(fh);
string file_content = ::FileReadString(fh, int(size));
file_content.SetChar(0, ' '); // quitamos el boom
::FileClose(fh);
//---
CJson json;
if(json.Parse(file_content)) // omitimos el bom del incio del utf16le
{
CJsonNode files_to_move_arr = json["files_to_move"];
//---
if(!files_to_move_arr.IsValid())
{
m_last_error_msg = "El key 'files_to_move' no existe en el json";
LogFatalError(m_last_error_msg, FUNCION_ACTUAL);
return false;
}
if(!files_to_move_arr.IsArray())
{
m_last_error_msg = "El key 'files_to_move' no es un array";
LogFatalError(m_last_error_msg, FUNCION_ACTUAL);
return false;
}
//---
m_files_common_to_move_size = files_to_move_arr.Size();
ArrayResize(m_files_common_to_move, m_files_common_to_move_size << 1);
for(int i = 0; i < m_files_common_to_move_size; i++)
{
m_files_common_to_move[i] = files_to_move_arr[i].ToString();
m_files_common_to_move[i + m_files_common_to_move_size] = GetPureFileName(m_files_common_to_move[i]);
}
}
else
{
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);
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester::LoadConfig(const string &file_name)
{
m_last_error_msg = "";
if(!m_in_execution)
{
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);
}
else
{
// 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);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CExecutionTester::SaveConfig(const string &file_name)
{
m_last_error_msg = "";
if(!m_in_execution)
{
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);
}
else
{
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);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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)
{
//--- Check quizas fallo al cargar
m_last_error_msg = "";
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;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
#endif // AIDATATASKRUNNER_BACKEND_MAIN_MQH