//+------------------------------------------------------------------+ //| ConfigTab.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_CONFIGTAB_MQH #define AIDATATASKRUNER_UI_TRAINING_CONFIGTAB_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "..\\Defines.mqh" //--- Json para parsear (con el exe comunicador) #include //--- Expert para lanzar eas #include //--- Def para el procoolo de comunciaon #include "..\\..\\Backend\\Training\\Def.mqh" //--- Dll custom para filse eslec dialog con mas alcanzse #include "..\\..\\DllFilseSelctDialog\\DllFilseSelctDialog\\Main.mqh" /* [CTrainingTabConfig] //--- Parte general m_label_titulo="Config" m_label_name_file="Config file:" m_label_name_file_val_tooltip="Selected config file" m_btn_name_file_browse="Browse" m_btn_name_file_browse_tooltip="Select config JSON file" m_btn_open="Open" m_btn_open_tooltip="Open file in default editor" //--- Parte de python m_label_tit_run_py="Run python" m_label_py_file="Python file:" m_label_py_file_val_tooltip="Path to the Python script or executable" m_btn_py_file_browse="Browse" m_btn_py_file_browse_tooltip="Select a .py script or .exe executable" // Edit timeout m_edit_py_max_tiemout="Tiemout for execute py:" m_edit_py_max_tiemout_tooltup="Enter the value in seconds for the maximum time the py can run" // Boton m_btn_run_py="Run" m_btn_run_py_tooltip="Click here to run python exe" m_btn_run_py_running="Running..." //--- Mensajes espeficiso por funcion OnClickBottom_error_select_file="No file selected" OnClickBottom_no_config_selected="No config file selected" OnClickBottom_python_is_runing="Python is already running" OnClickBottom_python_no_py_selected="No python\exe files selected" // Error de laucher OnClickBottom_python_launch_error_file="Failed to write in args.txt for launcher for python, last error = %d" OnClickBottom_python_launch_error_exe="Failed to execute launcher, Check the terminal logs" OnClickBottom_python_launch_python_launch_error_chart="Failed to open chart, last error = %d" */ //--- #define AIDATATASKRUNNER_TRAINING_NUM_C (80) #define AIDATATASKRUNNER_FILENAME_ARGS_LAUNCHER ("LauncherPy\\args.txt") #define AIDATATASKRUNNER_FILENAME_BAT_PY ("LauncherPy\\py.bat") //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class IRunPy : public CLoggerBase { public: IRunPy(void) {} ~IRunPy(void) {} //--- virtual void OnTrainingInit() {} virtual void OnTrainingEnd() {} virtual void OnTrainingNewResult(CJson* json) {} //--- virtual __forceinline uint8_t EventsFlags() const = 0; }; //--- #define TRAINING_RUNNER_PY_FLAG_ON_TRAINIG (1) #define TRAINING_RUNNER_PY_FLAG_ON_INIT (2) #define TRAINING_RUNNER_PY_FLAG_ON_DEINIT (4) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CTrainingTabConfig : public CGuiBaseComponent { private: CTextLabel m_label_titulo; CTextLabel m_label_name_file; CTextLabel m_label_name_file_val; CButton m_btn_name_file_browse; CButton m_btn_open; CButton m_btn_file_config_template; //--- CTextLabel m_label_tit_run_py; // Py file CTextLabel m_label_py_file; CTextLabel m_label_py_file_val; CButton m_btn_py_file_browse; // Log file CTextLabel m_label_log_pyfile; CTextLabel m_label_log_pyfile_val; CButton m_btn_logpyfile_browse; // Max timeout CTextEdit m_edit_py_max_tiemout; // Btn run final CButton m_btn_run_py; //--- string m_py_file_extension; //--- bool m_py_is_run; bool m_common_flag; int m_extra_file_flags; string m_base_terminal_files_path; //--- string m_path_to_config_json; string m_path_to_lock_bin; string m_path_to_ea_launcher; string m_path_to_log_py; string m_path_py_interpete; string m_python_path_env; uint m_timeout_for_execute_py; //--- IRunPy* m_runer_py_on_pass[]; int m_runer_py_on_pass_size; IRunPy* m_runer_py_on_init[]; int m_runer_py_on_init_size; IRunPy* m_runer_py_on_deinit[]; int m_runer_py_on_deinit_size; //--- void OnTrainingFinish(); void OnTrainingStart(); public: CTrainingTabConfig(void); ~CTrainingTabConfig(void); //--- void AddRunnerPy(IRunPy* runer); //--- void SetExtra(bool common_flag, const string& path_config_json, const string& path_lock, const string& path_ea_launcer, const string& path_py_inter, const string& py_path_env); bool Create(CWndCreate* p, CWindow& main_window, int top_gap, int left_gap, int right_gap, int bottom_gap); //--- bool OnClickBottom(const long lparam); bool OnTextEdit(const long lparam); bool OnClickDec(const long lparam); bool OnClickInc(const long lparam); //--- void OnLenguajeChange() override final; //--- __forceinline string ConfigFilePath() const { return m_label_name_file_val.LabelText(); } //--- // Se tendra que llamar a aesta funcion ojito void OnFinishPy(); //--- void OnTimerEvent(); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CTrainingTabConfig::CTrainingTabConfig() : CGuiBaseComponent("CTrainingTabConfig"), m_py_is_run(false) { m_runer_py_on_deinit_size = ArrayResize(m_runer_py_on_deinit, 0); m_runer_py_on_init_size = ArrayResize(m_runer_py_on_init, 0); m_runer_py_on_pass_size = ArrayResize(m_runer_py_on_pass, 0); } //+------------------------------------------------------------------+ CTrainingTabConfig::~CTrainingTabConfig() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabConfig::SetExtra(bool common_flag, const string& path_config_json, const string& path_lock, const string& path_ea_launcer, const string& path_py_inter, const string& py_path_env) { //--- m_common_flag = common_flag; m_extra_file_flags = (m_common_flag ? FILE_COMMON : 0); m_path_py_interpete = path_py_inter; //--- Estos arhcivos van tal cual no hay una carpeta base asi que se debe esopciifcar ruta completa (son relativos a Files\\) tal cual no de bsae_path m_path_to_config_json = path_config_json; m_path_to_lock_bin = path_lock; m_path_to_ea_launcher = path_ea_launcer; m_python_path_env = py_path_env; //--- m_base_terminal_files_path = (m_common_flag ? TERMINAL_MT5_COMMON_PATH + "\\Files\\" : TERMINAL_MT5_DATA_PAH + "\\MQL5\\Files\\"); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingTabConfig::Create(CWndCreate *p, CWindow &main_window, int top_gap, int left_gap, int right_gap, int bottom_gap) { //--- const int initial_x = left_gap + 5; int x = left_gap + 5; int y = top_gap + 10; //--- Titulo m_label_titulo.FontSize(14); m_label_titulo.Font("Arial"); m_label_titulo.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_titulo.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_titulo, m_language[GUIBASE_COMPONENT_NAME(m_label_titulo)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 200)) { GUIBASE_ERROR_CREATION(m_label_titulo); return false; } y += m_label_titulo.YSize() + 14; //--- Label Config file: m_label_name_file.FontSize(10); m_label_name_file.Font("Arial"); m_label_name_file.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_label_name_file.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_name_file, m_language[GUIBASE_COMPONENT_NAME(m_label_name_file)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 100, 25)) { GUIBASE_ERROR_CREATION(m_label_name_file); return false; } x += m_label_name_file.XSize() + 5; //--- Label valor (ruta) m_label_name_file_val.FontSize(10); m_label_name_file_val.Font("Arial"); m_label_name_file_val.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_name_file_val.BackColor(AIDATATASKRUNER_COLOR_EDIT_BACK); m_label_name_file_val.LabelXGap(5); m_label_name_file_val.LabelYGap(3); m_label_name_file_val.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_name_file_val))); if(!p.CreateTextLabel(m_label_name_file_val, "", main_window, 0, m_base_tab, m_base_tab_idx, x, y, 350, 25)) { GUIBASE_ERROR_CREATION(m_label_name_file_val); return false; } x = initial_x; // Reinit y += m_label_name_file_val.YSize() + 8; // Bajamos (peude no caber la ruta) //--- Browse m_btn_name_file_browse.FontSize(10); m_btn_name_file_browse.Font("Arial"); m_btn_name_file_browse.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_name_file_browse.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_name_file_browse.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_name_file_browse.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_name_file_browse))); if(!p.CreateButton(m_btn_name_file_browse, m_language[GUIBASE_COMPONENT_NAME(m_btn_name_file_browse)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 80)) { GUIBASE_ERROR_CREATION(m_btn_name_file_browse); return false; } x += m_btn_name_file_browse.XSize() + 5; //--- Open m_btn_open.FontSize(10); m_btn_open.Font("Arial"); m_btn_open.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_open.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_open.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_open.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_open))); if(!p.CreateButton(m_btn_open, m_language[GUIBASE_COMPONENT_NAME(m_btn_open)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 80)) { GUIBASE_ERROR_CREATION(m_btn_open); return false; } x += m_btn_open.XSize() + 5; //--- m_btn_file_config_template.FontSize(10); m_btn_file_config_template.Font("Arial"); m_btn_file_config_template.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_file_config_template.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_file_config_template.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_file_config_template.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_file_config_template))); if(!p.CreateButton(m_btn_file_config_template, "?", main_window, 0, m_base_tab, m_base_tab_idx, x, y, 50)) { GUIBASE_ERROR_CREATION(m_btn_file_config_template); return false; } //--- Label titulo Run Python y += m_btn_open.YSize() + 21; // separacion visual de seccion x = initial_x; m_label_tit_run_py.FontSize(14); m_label_tit_run_py.Font("Arial"); m_label_tit_run_py.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_tit_run_py.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_tit_run_py, m_language[GUIBASE_COMPONENT_NAME(m_label_tit_run_py)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 200)) { GUIBASE_ERROR_CREATION(m_label_tit_run_py); return false; } y += m_label_tit_run_py.YSize() + 10; //--- Label py file m_label_py_file.FontSize(10); m_label_py_file.Font("Arial"); m_label_py_file.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_label_py_file.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_py_file, m_language[GUIBASE_COMPONENT_NAME(m_label_py_file)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 100, 25)) { GUIBASE_ERROR_CREATION(m_label_py_file); return false; } x += m_label_py_file.XSize() + 5; //--- Label py file val m_label_py_file_val.FontSize(10); m_label_py_file_val.Font("Arial"); m_label_py_file_val.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_py_file_val.BackColor(AIDATATASKRUNER_COLOR_EDIT_BACK); m_label_py_file_val.LabelXGap(5); m_label_py_file_val.LabelYGap(2); m_label_py_file_val.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_py_file_val))); const int x_label_py_file_val = x; if(!p.CreateTextLabel(m_label_py_file_val, "", main_window, 0, m_base_tab, m_base_tab_idx, x, y, 425, 25)) { GUIBASE_ERROR_CREATION(m_label_py_file_val); return false; } x = initial_x; y += m_label_py_file_val.YSize() + 8; //--- Browse py file m_btn_py_file_browse.FontSize(10); m_btn_py_file_browse.Font("Arial"); m_btn_py_file_browse.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_py_file_browse.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_py_file_browse.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_py_file_browse.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_py_file_browse))); if(!p.CreateButton(m_btn_py_file_browse, m_language[GUIBASE_COMPONENT_NAME(m_btn_py_file_browse)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 80)) { GUIBASE_ERROR_CREATION(m_btn_py_file_browse); return false; } //--- y += m_btn_py_file_browse.YSize() + 10; // separacion visual de seccion x = initial_x; //--- Label logpy file m_label_log_pyfile.FontSize(10); m_label_log_pyfile.Font("Arial"); m_label_log_pyfile.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_label_log_pyfile.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_log_pyfile, m_language[GUIBASE_COMPONENT_NAME(m_label_log_pyfile)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 130, 25)) { GUIBASE_ERROR_CREATION(m_label_py_file); return false; } x = x_label_py_file_val; // mismo nivel //--- Label logpy file val m_label_log_pyfile_val.FontSize(10); m_label_log_pyfile_val.Font("Arial"); m_label_log_pyfile_val.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_log_pyfile_val.BackColor(AIDATATASKRUNER_COLOR_EDIT_BACK); m_label_log_pyfile_val.LabelXGap(5); m_label_log_pyfile_val.LabelYGap(2); m_label_log_pyfile_val.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_log_pyfile_val))); if(!p.CreateTextLabel(m_label_log_pyfile_val, "", main_window, 0, m_base_tab, m_base_tab_idx, x, y, 425, 25)) { GUIBASE_ERROR_CREATION(m_label_log_pyfile_val); return false; } x = initial_x; y += m_label_log_pyfile_val.YSize() + 8; //--- Browse logpy file m_btn_logpyfile_browse.FontSize(10); m_btn_logpyfile_browse.Font("Arial"); m_btn_logpyfile_browse.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_logpyfile_browse.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_logpyfile_browse.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_logpyfile_browse.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_logpyfile_browse))); if(!p.CreateButton(m_btn_logpyfile_browse, m_language[GUIBASE_COMPONENT_NAME(m_btn_logpyfile_browse)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 80)) { GUIBASE_ERROR_CREATION(m_btn_logpyfile_browse); return false; } //--- y += m_btn_logpyfile_browse.YSize() + 10; // separacion visual de seccion x = initial_x; //--- const string texto = m_language[AIDATATASKRUNNERL_COMPONENT_NAME(m_edit_py_max_tiemout)]; m_edit_py_max_tiemout.FontSize(10); m_edit_py_max_tiemout.Font("Arial"); m_edit_py_max_tiemout.CanvasFontSet(); const int width = m_edit_py_max_tiemout.m_canvas.TextWidth(texto); m_edit_py_max_tiemout.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_edit_py_max_tiemout.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); m_edit_py_max_tiemout.GetTextBoxPointer().BackColor(AIDATATASKRUNER_COLOR_EDIT_BACK); m_edit_py_max_tiemout.GetTextBoxPointer().BorderColor(AIDATATASKRUNER_COLOR_EDIT_BORDER); m_edit_py_max_tiemout.GetTextBoxPointer().DefaultTextColor(AIDATATASKRUNER_COLOR_EDIT_TEXT_NORMAL); m_edit_py_max_tiemout.GetTextBoxPointer().LabelColor(AIDATATASKRUNER_COLOR_EDIT_TEXT_NORMAL); m_edit_py_max_tiemout.GetTextBoxPointer().SelectedBackColor(AIDATATASKRUNER_COLOR_EDIT_TEXT_SELECTED); m_edit_py_max_tiemout.GetTextBoxPointer().SelectedTextColor(AIDATATASKRUNER_COLOR_EDIT_TEXT_HIGHLIGHT); m_edit_py_max_tiemout.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_edit_py_max_tiemout))); #define AIDATATASKRUNNER_TRAINING_EDITPY_MAX_VAL (double(UINT_MAX)/1000.0) #define AIDATATASKRUNNER_TRAINING_EDITPY_DEF_VAL (1800) if(!p.CreateTextEdit(m_edit_py_max_tiemout, texto, main_window, 0, m_base_tab, m_base_tab_idx, false, x, y, width + 10 + 200, 200, AIDATATASKRUNNER_TRAINING_EDITPY_MAX_VAL , 1.0, 1.0, 0, double(AIDATATASKRUNNER_TRAINING_EDITPY_DEF_VAL))) // Min value = 1.0 | Step = 1.0 | 0 = Digitos | 1800 = valor por defecto (30 minutos) { AIDATATASKRUNER_ERROR_CREATION(m_edit_py_max_tiemout); return false; } m_timeout_for_execute_py = AIDATATASKRUNNER_TRAINING_EDITPY_DEF_VAL * 1000; // 30 min default //--- y += m_edit_py_max_tiemout.YSize() + 12; x = initial_x; //--- Boton Run m_btn_run_py.FontSize(10); m_btn_run_py.Font("Arial"); m_btn_run_py.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_run_py.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_run_py.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_run_py.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_run_py))); if(!p.CreateButton(m_btn_run_py, m_language[GUIBASE_COMPONENT_NAME(m_btn_run_py)], main_window, 0, m_base_tab, m_base_tab_idx, x, y, 140)) { GUIBASE_ERROR_CREATION(m_btn_run_py); return false; } //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingTabConfig::OnTextEdit(const long lparam) { if(m_edit_py_max_tiemout.Id() == lparam) { m_timeout_for_execute_py = uint(m_edit_py_max_tiemout.GetValue()) * 1000; return true; } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingTabConfig::OnClickDec(const long lparam) { if(m_edit_py_max_tiemout.Id() == lparam) { m_timeout_for_execute_py = uint(m_edit_py_max_tiemout.GetValue()) * 1000; return true; } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingTabConfig::OnClickInc(const long lparam) { if(m_edit_py_max_tiemout.Id() == lparam) { m_timeout_for_execute_py = uint(m_edit_py_max_tiemout.GetValue()) * 1000; return true; } return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingTabConfig::OnClickBottom(const long lparam) { //--- if(m_btn_logpyfile_browse.Id() == lparam) { //--- string arr[]; if(FileSelectDialog(GUIBASE_MSG("flselect_logiflepy"), NULL, "Log files (*.log)|*.log", (m_common_flag ? FSD_COMMON_FOLDER : 0), arr, NULL) != 1) { MessageBox(GUIBASE_MSG("error_select_file"), GUIBASE_MSG("error"), MB_ICONERROR | MB_OK); return true; } //--- Guardamos la ruta y la extension //Print(out_file_complete_path); m_label_log_pyfile_val.LabelText(arr[0]); // ruta completa aqui m_label_log_pyfile_val.Update(true); //--- return true; } //--- if(m_btn_py_file_browse.Id() == lparam) { string out_file_complete_path = ""; if(!FileSelectDialogComplete(out_file_complete_path, 500, GUIBASE_MSG("flselect_py"), "Python files (*.py)\0*.py\0Executable files (*.exe)\0*.exe\0\0", TERMINAL_MT5_DATA_PAH, // Base del temrinal NAME\\ OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST)) // EL FOLDER y archivo deben de sexisteir { //reciclamos el msg mismo que se usa en el browse deljson confgig MessageBox(GUIBASE_MSG("error_select_file"), GUIBASE_MSG("error"), MB_ICONERROR | MB_OK); return true; } //--- Guardamos la ruta y la extension //Print(out_file_complete_path); m_label_py_file_val.LabelText(out_file_complete_path); // ruta completa aqui m_label_py_file_val.Update(true); //--- m_py_file_extension = FileGetExtension(out_file_complete_path); // solo da la ext no con el . return true; } //--- Config file // Browse if(m_btn_name_file_browse.Id() == lparam) { //--- string arr[]; if(FileSelectDialog("Configuration", NULL, "JSON files (*.json)|*.json", (m_common_flag ? FSD_COMMON_FOLDER : 0) | FSD_FILE_MUST_EXIST, arr, NULL) != 1) { MessageBox(GUIBASE_MSG("error_select_file"), GUIBASE_MSG("error"), MB_ICONERROR | MB_OK); return true; } //--- m_label_name_file_val.LabelText(arr[0]); m_label_name_file_val.Update(true); //--- return true; } // Template if(m_btn_file_config_template.Id() == lparam) { //--- string arr[]; // para el temaplte usamos el common folder flag del panel dado que teamplestes se ubica ahi vale?¿ if(FileSelectDialog("Configuration", AIDATATASKRUNER_PATH_TEMPLATES, "JSON files (*.json)|*.json", AIDATATASK_RUNNER_FSD_COMON_FLAG | FSD_FILE_MUST_EXIST, arr, AIDATATASKRUNER_FILENAME_TEMPLATES_PYCONFIG) != 1) { MessageBox(GUIBASE_MSG("error_select_file"), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); return true; } //--- m_label_name_file_val.LabelText(arr[0]); m_label_name_file_val.Update(true); //--- return true; } // Open if(m_btn_open.Id() == lparam) { const string full_path = m_base_terminal_files_path + m_label_name_file_val.LabelText(); ShellExecuteW(0, "open", full_path, NULL, NULL, SW_SHOW); // no verificamos noe s critrico return true; } //--- if(m_btn_run_py.Id() == lparam) { //--- if(m_py_is_run) { MessageBox(GUIBASE_MSG("python_is_runing"), GUIBASE_COMMON("warning"), MB_ICONWARNING | MB_OK); return true; } //--- Check inicialzies // Configuracion seleccionada const string config = m_label_name_file_val.LabelText(); if(config.Length() < 1) { MessageBox(GUIBASE_MSG("no_config_selected"), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); return true; } // Archivos py selecionado const string py = m_label_py_file_val.LabelText(); if(py.Length() < 1) { MessageBox(GUIBASE_MSG("no_py_selected"), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); return true; } //--- Abrimos el archivo de comuncionacion const string fn = AIDATATASKRUNER_BASE_FOLDER + AIDATATASKRUNNER_FILENAME_ARGS_LAUNCHER; ::ResetLastError(); const int fh = FileOpen(fn, FILE_WRITE | FILE_TXT | AIDATATASK_RUNNER_COMON_FLAG, 0); if(fh == INVALID_HANDLE) { MessageBox(StringFormat(GUIBASE_MSG("python_launch_error_file"), ::GetLastError()), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); return true; } //--- // Escritura FileWrite(fh, m_label_log_pyfile_val.LabelText()); FileWrite(fh, py); // Py path to execute (ya da la ruyta completa) FileWrite(fh, m_py_file_extension); // Extension FileWrite(fh, m_path_py_interpete); // Interprete FileWrite(fh, m_python_path_env); ::FileClose(fh); //--- /* input string InpFileNameArgs = ""; input int InpFileCommonFlag = 0; input string InpArgsConfigJson = ""; input string InpArgsResJson = ""; input string InpArgsLockBin = ""; input string InpArgsBaseTerminalPath = ""; // 1 hora (3600 * 1000) en ms input uint InpPyTimeoutMs = 3600000; */ //--- Lanzamos el ea MqlParam params[9]; params[0].type = TYPE_STRING; params[0].string_value = "Experts\\" + m_path_to_ea_launcher; params[1].type = TYPE_STRING; params[1].string_value = fn; // Nombre del archivo params[2].type = TYPE_INT; params[2].integer_value = AIDATATASK_RUNNER_COMON_FLAG; // Bandera common o no common //--- // Paramemos de args como tal params[3].type = TYPE_STRING; params[3].string_value = config; params[4].type = TYPE_STRING; params[4].string_value = m_path_to_config_json; params[5].type = TYPE_STRING; params[5].string_value = m_path_to_lock_bin; // Basew terminal path s params[6].type = TYPE_STRING; params[6].string_value = m_base_terminal_files_path; //--- params[7].type = TYPE_UINT; params[7].integer_value = m_timeout_for_execute_py; //--- params[8].type = TYPE_STRING; params[8].string_value = AIDATATASKRUNER_BASE_FOLDER + AIDATATASKRUNNER_FILENAME_BAT_PY; //--- ::ResetLastError(); const long bot_chart_id = OpenChartAndDevoler(ChartID(), _Symbol, _Period, 1500); if(bot_chart_id == -1) { MessageBox(StringFormat(GUIBASE_MSG("python_launch_error_chart"), ::GetLastError()), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); return true; } //--- Check sincronizacion del grafico while(ChartGetInteger(bot_chart_id, CHART_VISIBLE_BARS) < 1) { // Espera para la siguiente iteracion Sleep(350); } if(!EXPERT::Run(bot_chart_id, params, EXPERT_PERMISOS_FLAG_DLL)) { MessageBox(GUIBASE_MSG("python_launch_error_exe"), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); ::ChartClose(bot_chart_id); // Cerramos return true; } //--- Exito al lanzar el runner entonces comenzamos OnTrainingStart(); //--- m_py_is_run = true; //--- cambio de estado a running m_btn_run_py.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_btn_run_py) + "_running"]); m_btn_run_py.Update(true); return true; } //--- return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabConfig::OnLenguajeChange(void) { //--- m_label_titulo.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_titulo)]); m_label_titulo.Update(true); //--- // Label m_label_name_file.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_name_file)]); m_label_name_file.Update(true); // Val m_label_name_file_val.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_name_file_val))); // Browse m_btn_name_file_browse.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_btn_name_file_browse)]); m_btn_name_file_browse.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_name_file_browse))); m_btn_name_file_browse.Update(true); // Open m_btn_open.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_btn_open)]); m_btn_open.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_open))); m_btn_open.Update(true); // Teemplate ? m_btn_file_config_template.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_file_config_template))); //--- Titulo run py m_label_tit_run_py.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_tit_run_py)]); m_label_tit_run_py.Update(true); //--- // Label m_label_py_file.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_py_file)]); m_label_py_file.Update(true); // Val m_label_py_file_val.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_py_file_val))); // Browse m_btn_py_file_browse.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_btn_py_file_browse)]); m_btn_py_file_browse.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_py_file_browse))); m_btn_py_file_browse.Update(true); //--- // Label m_label_log_pyfile.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_log_pyfile)]); m_label_log_pyfile.Update(true); // Val m_label_log_pyfile_val.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_log_pyfile_val))); // Browse m_btn_logpyfile_browse.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_btn_logpyfile_browse)]); m_btn_logpyfile_browse.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_logpyfile_browse))); m_btn_logpyfile_browse.Update(true); //--- Actulziamos el edit del py const string key = GUIBASE_COMPONENT_NAME(m_edit_py_max_tiemout); m_edit_py_max_tiemout.LabelText(m_language[key]); m_edit_py_max_tiemout.Tooltip(m_language.Tooltip(key)); const string texto = m_edit_py_max_tiemout.LabelText(); m_edit_py_max_tiemout.CanvasFontSet(); const int width = m_edit_py_max_tiemout.m_canvas.TextWidth(texto); // Ancho texto | Extra separacion entre texto y obj element| Ancho de elemento m_edit_py_max_tiemout.XSize(width + 10 + 200); m_edit_py_max_tiemout.Update(true); //--- m_btn_run_py.Tooltip(m_language[GUIBASE_COMPONENT_NAME(m_btn_run_py)]); // toltip solo cambios m_btn_run_py.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_btn_run_py) + (m_py_is_run ? "_running" : "")]); m_btn_run_py.Update(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabConfig::AddRunnerPy(IRunPy *runer) { //--- const uint8_t flags = runer.EventsFlags(); //--- if((flags & TRAINING_RUNNER_PY_FLAG_ON_INIT) != 0) { m_runer_py_on_init[ArrayResize(m_runer_py_on_init, (++m_runer_py_on_init_size)) - 1] = runer; } //--- if((flags & TRAINING_RUNNER_PY_FLAG_ON_TRAINIG) != 0) { m_runer_py_on_pass[ArrayResize(m_runer_py_on_pass, (++m_runer_py_on_pass_size)) - 1] = runer; } //--- if((flags & TRAINING_RUNNER_PY_FLAG_ON_DEINIT) != 0) { m_runer_py_on_deinit[ArrayResize(m_runer_py_on_deinit, (++m_runer_py_on_deinit_size)) - 1] = runer; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabConfig::OnTrainingStart() { //--- LogWarning("El entremianeto a empezado", FUNCION_ACTUAL); //--- Eliminamos los archvos anteriorres si es que existen ::FileDelete(m_path_to_lock_bin, m_extra_file_flags); ::FileDelete(m_path_to_config_json, m_extra_file_flags); //--- for(int i = 0; i < m_runer_py_on_init_size; i++) { m_runer_py_on_init[i].OnTrainingInit(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabConfig::OnTrainingFinish() { //--- m_py_is_run = false; //--- LogWarning("Training has finished", FUNCION_ACTUAL); //--- for(int i = 0; i < m_runer_py_on_deinit_size; i++) { m_runer_py_on_deinit[i].OnTrainingEnd(); } //--- const string run_key = GUIBASE_COMPONENT_NAME(m_btn_run_py) + (m_py_is_run ? "_running" : ""); m_btn_run_py.LabelText(m_language[run_key]); m_btn_run_py.Update(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabConfig::OnTimerEvent() { if(!m_py_is_run) return; static int8_t ct = 0; if(ct++ > AIDATATASKRUNNER_TRAINING_NUM_C) { //--- ct = 0; //--- if(::FileIsExist(m_path_to_lock_bin, m_extra_file_flags)) { //--- Reinicio primero procemos luego // Lo eliminamos denuevo para que esperemos la siguiente entrega ::FileDelete(m_path_to_lock_bin, m_extra_file_flags); //--- LogInfo("Nuevo pase recibido de py", FUNCION_ACTUAL); //--- CJson* json = new CJson(); //--- ::ResetLastError(); const int fh = ::FileOpen(m_path_to_config_json, FILE_READ | FILE_BIN | m_extra_file_flags); if(fh == INVALID_HANDLE) { LogWarning(::StringFormat("Fallo al abrir el archivo =%s, ultimo error = %d", m_path_to_config_json, ::GetLastError()), FUNCION_ACTUAL); delete json; // Borramos el json return; } //--- const ulong file_size = FileSize(fh); string file_content = ::FileReadString(fh, int(file_size)); if(file_content.GetChar(0) == 0xFEFF) // check si el primero es boom file_content.SetChar(0, ' '); //Print(file_content); //--- if(json.Parse(file_content)) { //--- ::FileClose(fh); //--- if(json["finish"].IsValid()) { const int res = int(json["finish"].ToInt()); if(res != AIDATATASKRUNNNER_TRAINIG_OUT_EXITO) // no es igual a exito hubo un fallo { const string str = AiDataTaskRunnerTrainingGetErr(res); LogFatalError(StringFormat("Fallo al ejecutar el py, el EA launcher retonrno valor no igual a 0, valor de finish = %I64d, str = %s", res, str), FUNCION_ACTUAL); } OnTrainingFinish(); delete json; } else { for(int i = 0; i < m_runer_py_on_pass_size; i++) { m_runer_py_on_pass[i].OnTrainingNewResult(json); } // Nota: // Se garnatiza que en la otra tab haya un hook que vayue guradadno los json asi que noe s enceiso eliminar esa // tab hook se encarga de eso } } else { ::FileClose(fh); LogError(::StringFormat("Fallo al parsear json ultimo error = %s", ::EnumToString(EnumJsonError(json.GetLastError()))), FUNCION_ACTUAL); delete json; } } } } //--- #endif // AIDATATASKRUNER_UI_TRAINING_CONFIGTAB_MQH //+------------------------------------------------------------------+