2026-04-05 08:26:30 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Def.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 WORKFLOWSBYLEO_SRC_CORE_DEF_MQH
|
|
|
|
|
#define WORKFLOWSBYLEO_SRC_CORE_DEF_MQH
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-04-06 13:04:47 -05:00
|
|
|
//| Include |
|
2026-04-05 08:26:30 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#include <TSN\\MQLArticles\\Utils\\Basic.mqh>
|
2026-04-09 15:47:36 -05:00
|
|
|
#include <TSN\\MQLArticles\\Utils\\Dict.mqh>
|
2026-04-05 08:26:30 -05:00
|
|
|
#include <TSN\\YAML\\Yaml.mqh>
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-04-06 13:04:47 -05:00
|
|
|
//| Callback |
|
2026-04-05 08:26:30 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2026-04-06 13:04:47 -05:00
|
|
|
#define WORKFLOWBYLEO_CALLBACK_ON_START (1)
|
|
|
|
|
#define WORKFLOWBYLEO_CALLBACK_ON_STEP (2)
|
|
|
|
|
#define WORKFLOWBYLEO_CALLBACK_ON_END (4)
|
|
|
|
|
#define WORKFLOWBYLEO_CALLBACK_ALL_FLAGS (WORKFLOWBYLEO_CALLBACK_ON_START|WORKFLOWBYLEO_CALLBACK_ON_STEP|WORKFLOWBYLEO_CALLBACK_ON_END)
|
2026-04-07 08:55:55 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
//#define WORKFLOW_CALLBACK_PADRE CLoggerBase
|
|
|
|
|
|
2026-04-06 13:04:47 -05:00
|
|
|
//---
|
2026-04-07 08:55:55 -05:00
|
|
|
#ifdef WORKFLOW_CALLBACK_PADRE
|
|
|
|
|
class IWorkflowCallback : public WORKFLOW_CALLBACK_PADRE
|
|
|
|
|
#else
|
2026-04-06 13:04:47 -05:00
|
|
|
class IWorkflowCallback
|
2026-04-07 08:55:55 -05:00
|
|
|
#endif // WORKFLOW_CALLBACK_PADRE
|
2026-04-06 13:04:47 -05:00
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
virtual inline uint8_t FlagsCall() const = 0;
|
2026-04-08 20:49:21 -05:00
|
|
|
virtual bool OnWorkflowStart() { return true; }
|
2026-04-06 13:04:47 -05:00
|
|
|
virtual void OnWorkflowEnd(int code, int step_index) {} // en caso de exito contendra el ultimo paso de lo contraio el pase fallido
|
2026-04-07 08:55:55 -05:00
|
|
|
virtual void OnWorkflowStep(int code, int step_index) {}
|
2026-04-06 13:04:47 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Clase base de workflow |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
// Declaracion previa
|
|
|
|
|
class CWorkflowStep;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
class CWorkflow : public CSpecializedManager
|
2026-04-05 08:26:30 -05:00
|
|
|
{
|
|
|
|
|
private:
|
2026-04-06 13:04:47 -05:00
|
|
|
//---
|
|
|
|
|
CYmlParser m_yml;
|
|
|
|
|
bool m_initialized;
|
2026-04-05 08:26:30 -05:00
|
|
|
string m_name;
|
2026-04-06 13:04:47 -05:00
|
|
|
bool m_is_running;
|
|
|
|
|
|
2026-04-08 11:55:14 -05:00
|
|
|
//--- Hashamp
|
|
|
|
|
// Aqui se ubicaran las variables de entorno \ secreots
|
2026-04-09 15:47:36 -05:00
|
|
|
CDict m_hash_str_val_to_str;
|
|
|
|
|
// Vairables extra
|
|
|
|
|
CDict m_hash_str_to_val_env;
|
2026-04-08 11:55:14 -05:00
|
|
|
|
2026-04-06 13:04:47 -05:00
|
|
|
//---
|
|
|
|
|
CWorkflowStep* m_steps[];
|
|
|
|
|
int m_steps_size;
|
|
|
|
|
int m_step_curr_pos;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
IWorkflowCallback* m_call_on_step[];
|
|
|
|
|
int m_call_on_step_size;
|
|
|
|
|
|
|
|
|
|
IWorkflowCallback* m_call_on_start[];
|
|
|
|
|
int m_call_on_start_size;
|
|
|
|
|
|
|
|
|
|
IWorkflowCallback* m_call_on_end[];
|
|
|
|
|
int m_call_on_end_size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bool Procesar();
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// p = curr pos
|
|
|
|
|
void OnEnd(const int p, const int res);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CWorkflow(void);
|
|
|
|
|
~CWorkflow(void);
|
|
|
|
|
|
|
|
|
|
//--- Init
|
|
|
|
|
bool Init(const string& yml);
|
|
|
|
|
bool Init(const string& file_name, bool comon_flag); // solo utf16 le
|
|
|
|
|
|
|
|
|
|
//--- Callbacks
|
|
|
|
|
__forceinline int CallBackOnStartSize() const { return m_call_on_start_size; }
|
|
|
|
|
__forceinline int CallBackOnEndSize() const { return m_call_on_end_size; }
|
|
|
|
|
__forceinline int CallBackOnStepSize() const { return m_call_on_step_size; }
|
|
|
|
|
void AddCallBack(IWorkflowCallback* callback);
|
|
|
|
|
|
|
|
|
|
//--- Run
|
2026-04-08 20:49:21 -05:00
|
|
|
int First();
|
2026-04-06 13:04:47 -05:00
|
|
|
void _RecibedEvent(const int res, bool flag = false);
|
|
|
|
|
|
2026-04-07 07:02:30 -05:00
|
|
|
//---
|
|
|
|
|
__forceinline void ChartEvent(const int32_t id, const long& lparam, const double& dparam, const string& sparam);
|
2026-04-10 15:42:19 -05:00
|
|
|
__forceinline void TimerEvent();
|
2026-04-07 07:02:30 -05:00
|
|
|
|
2026-04-06 13:04:47 -05:00
|
|
|
|
|
|
|
|
//--- Initilized
|
|
|
|
|
__forceinline bool IsInitialized() const { return m_initialized; }
|
|
|
|
|
__forceinline int StepCount() const { return m_steps_size; }
|
|
|
|
|
__forceinline string Name() const { return m_name; }
|
|
|
|
|
__forceinline bool IsRuning() const { return m_is_running; }
|
|
|
|
|
__forceinline int CurrentStepIndex() const { return m_step_curr_pos; }
|
|
|
|
|
|
|
|
|
|
//--- Get pointers
|
2026-04-08 11:55:14 -05:00
|
|
|
CYmlParser* YmlParser() { return &m_yml; }
|
|
|
|
|
CWorkflowStep* GetStep(const int index) { return m_steps[index]; }
|
2026-04-09 15:47:36 -05:00
|
|
|
CDict* Variables() { return &m_hash_str_val_to_str; }
|
|
|
|
|
CDict* Env() { return &m_hash_str_to_val_env; }
|
2026-04-08 11:55:14 -05:00
|
|
|
|
2026-04-09 15:47:36 -05:00
|
|
|
//--- Translate
|
2026-04-08 11:55:14 -05:00
|
|
|
// node ya debe de ser el valor objetivo.. no key ni nada...
|
|
|
|
|
template <typename TNumber>
|
|
|
|
|
TNumber TranslateNumber(const CYmlNode& val, const string& def);
|
|
|
|
|
bool TranslateBool(const CYmlNode& val, const string& def);
|
|
|
|
|
string TranslateStr(const CYmlNode& val, const string& def);
|
2026-04-08 13:52:09 -05:00
|
|
|
template <typename TEnum> // Mencionar que el enum que se desea registar debe de estar regisrado en ENUM REG
|
|
|
|
|
TEnum TranslateEnum(const CYmlNode& val, const string& def);
|
|
|
|
|
|
|
|
|
|
// Assing
|
|
|
|
|
bool AssingMqlParam(MqlParam& param, CYmlNode& node, ENUM_DATATYPE force_type);
|
|
|
|
|
bool AssingMqlParam(MqlParam& param, CYmlNode& node, const string stype);
|
2026-04-09 15:47:36 -05:00
|
|
|
|
|
|
|
|
//--- Enviroment
|
|
|
|
|
__forceinline string EnvStr(const string& key);
|
|
|
|
|
__forceinline bool EnvBool(const string& key);
|
|
|
|
|
template<typename TNumber>
|
|
|
|
|
__forceinline TNumber EnvNumber(const string& key);
|
|
|
|
|
template<typename TPtr>
|
|
|
|
|
__forceinline TPtr* EnvPtr(const string& key);
|
2026-04-06 13:04:47 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Step |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-04-07 08:55:55 -05:00
|
|
|
#define WORKFLOWBYLEO_STEP_FLAG_ON_CHART_EVENT (1)
|
2026-04-10 15:42:19 -05:00
|
|
|
#define WORKFLOWBYLEO_STEP_FLAG_ON_TIMER_EVENT (2)
|
2026-04-07 07:02:30 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-04-06 13:04:47 -05:00
|
|
|
class CWorkflowStep : public CLoggerBase
|
|
|
|
|
{
|
2026-04-13 16:46:21 -05:00
|
|
|
private:
|
|
|
|
|
int m_allowed_res[];
|
|
|
|
|
bool m_allowd_any;
|
|
|
|
|
|
2026-04-07 08:55:55 -05:00
|
|
|
protected:
|
2026-04-06 13:04:47 -05:00
|
|
|
const string m_name;
|
|
|
|
|
const string m_namespace;
|
|
|
|
|
CWorkflow* m_wf;
|
2026-04-05 08:26:30 -05:00
|
|
|
|
2026-04-13 16:46:21 -05:00
|
|
|
|
2026-04-05 08:26:30 -05:00
|
|
|
public:
|
2026-04-07 07:02:30 -05:00
|
|
|
CWorkflowStep(const string& name, const string& _namespace, bool async, uint8_t async_f)
|
|
|
|
|
: m_name(name), m_namespace(_namespace), m_async_flags(async_f), m_async(async), m_wf(NULL) {}
|
|
|
|
|
|
2026-04-05 08:26:30 -05:00
|
|
|
~CWorkflowStep(void) {}
|
|
|
|
|
|
2026-04-07 07:02:30 -05:00
|
|
|
//---
|
|
|
|
|
const bool m_async;
|
|
|
|
|
const uint8_t m_async_flags;
|
|
|
|
|
|
2026-04-06 13:04:47 -05:00
|
|
|
//---
|
|
|
|
|
void MainPointer(CWorkflow* wf) { m_wf = wf; }
|
|
|
|
|
CWorkflow* MainPointer() { return m_wf; }
|
|
|
|
|
|
2026-04-05 08:26:30 -05:00
|
|
|
//---
|
|
|
|
|
virtual bool Init(const CYmlNode& parameters) = 0;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline string Name() const { return m_name; }
|
|
|
|
|
__forceinline string Namespace() const { return m_namespace; }
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
virtual int Run() = 0;
|
2026-04-07 07:02:30 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
virtual void ChartEvent(const int32_t id, const long& lparam, const double& dparam, const string& sparam) {}
|
2026-04-10 15:42:19 -05:00
|
|
|
virtual void OnTimerEvent() {}
|
2026-04-13 16:46:21 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline bool IsPassed(const int res) { return m_allowd_any || ArrayFindValue(m_allowed_res, res) >= 0; }
|
|
|
|
|
void ParseIndexes(CYmlNode& arr);
|
2026-04-05 08:26:30 -05:00
|
|
|
};
|
|
|
|
|
|
2026-04-13 16:46:21 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CWorkflowStep::ParseIndexes(CYmlNode &arr)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
//Print((arr.IsValid()) , " | " , arr.Size());
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
ArrayResize(m_allowed_res, 0);
|
|
|
|
|
m_allowd_any = false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const int t = arr.Size();
|
|
|
|
|
if(t == 0)
|
|
|
|
|
{
|
|
|
|
|
ArrayResize(m_allowed_res, 1);
|
|
|
|
|
m_allowed_res[0] = 0; //
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ArrayResize(m_allowed_res, t);
|
|
|
|
|
int k = 0;
|
|
|
|
|
CYmlIteratorArray it = arr.BeginArr();
|
|
|
|
|
while(it.IsValid())
|
|
|
|
|
{
|
|
|
|
|
CYmlNode val = it.Val();
|
|
|
|
|
ENUM_YML_CLASIFIER_TYPE_VAL val_type = val.GetType();
|
|
|
|
|
if(val_type == YML_CLASIFIER_TOKEN_TYPE_INTEGER)
|
|
|
|
|
{
|
|
|
|
|
m_allowed_res[k++] = int(val.ToInt(0)); // 0 siempre pased
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Any (ya con uno basta)
|
|
|
|
|
//Print("aa");
|
|
|
|
|
m_allowd_any = true;
|
|
|
|
|
}
|
|
|
|
|
it.Next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-05 08:26:30 -05:00
|
|
|
|
2026-04-07 08:55:55 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Creacdor (para factory) |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
class CWorflowStepCreator
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
CWorflowStepCreator(void) {}
|
|
|
|
|
~CWorflowStepCreator(void) {}
|
|
|
|
|
virtual CWorkflowStep* Create() = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Factory |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
class CWorflowsFactory
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
CWorflowsFactory(void) {}
|
|
|
|
|
~CWorflowsFactory(void) {}
|
2026-04-07 09:06:54 -05:00
|
|
|
//---
|
|
|
|
|
static CHashMap<string, CWorflowStepCreator*> s_hash_str_to_creator;
|
2026-04-07 08:55:55 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-04-07 09:06:54 -05:00
|
|
|
static void Deinit(const int reason);
|
2026-04-07 08:55:55 -05:00
|
|
|
static CWorkflowStep* GetWorkflowStep(const string& module, const string& name);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
static CWorkflowStep* CWorflowsFactory::GetWorkflowStep(const string &module, const string &name)
|
|
|
|
|
{
|
|
|
|
|
CWorflowStepCreator* creator = NULL;
|
2026-04-07 09:06:54 -05:00
|
|
|
if(s_hash_str_to_creator.TryGetValue(module + "\\" + name, creator))
|
2026-04-07 08:55:55 -05:00
|
|
|
return creator.Create();
|
|
|
|
|
else
|
2026-04-07 09:06:54 -05:00
|
|
|
{
|
2026-04-07 08:55:55 -05:00
|
|
|
return NULL;
|
2026-04-07 09:06:54 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
static void CWorflowsFactory::Deinit(const int reason)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
string temp[];
|
|
|
|
|
CWorflowStepCreator* vals[];
|
|
|
|
|
const int t = s_hash_str_to_creator.CopyTo(temp, vals);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int i = 0; i < t; i++)
|
|
|
|
|
delete vals[i];
|
2026-04-07 08:55:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CHashMap<string, CWorflowStepCreator*> CWorflowsFactory::s_hash_str_to_creator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Adder |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//---
|
|
|
|
|
//bool g_worflow_boolean_dummy = true;
|
|
|
|
|
//---
|
2026-04-07 09:06:54 -05:00
|
|
|
#define WORKFLOWS_FACTORY_DEFINE_CREATOR(class_name, prefix, name, module) \
|
2026-04-07 08:55:55 -05:00
|
|
|
class CWorkflowStepCreator_##prefix : public CWorflowStepCreator \
|
|
|
|
|
{ \
|
|
|
|
|
public: \
|
|
|
|
|
CWorkflowStepCreator_##prefix(void) {} \
|
|
|
|
|
~CWorkflowStepCreator_##prefix(void) {} \
|
|
|
|
|
CWorkflowStep* Create() override final { return new class_name(); } \
|
|
|
|
|
}; \
|
2026-04-07 09:06:54 -05:00
|
|
|
const bool g_worflow_b_dummy_##prefix = CWorflowsFactory::s_hash_str_to_creator.Add(((module) + "\\" + (name)), new CWorkflowStepCreator_##prefix());
|
2026-04-07 08:55:55 -05:00
|
|
|
|
2026-04-05 08:26:30 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2026-04-06 13:04:47 -05:00
|
|
|
#endif // WORKFLOWSBYLEO_SRC_CORE_DEF_MQH
|