AiDataGenByLeo/GenericData/Parser/Parser.mqh

384 lines
28 KiB
MQL5
Raw Permalink Normal View History

2026-01-30 08:38:10 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| 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 AIDATAGENBYLEO_GENERIC_DATA_PARSER_PARSER_MQH
#define AIDATAGENBYLEO_GENERIC_DATA_PARSER_PARSER_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//--- Clasificador
#include "Clasifier\\Main.mqh"
//--- Factory
#include "..\\Factory\\Main.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CAiDataLeoFeaturesParser : public CLoggerBase
{
public:
CAiDataLeoFeaturesParser(void) {}
~CAiDataLeoFeaturesParser(void) {}
2026-02-02 17:45:09 -05:00
bool Parse(const string& src, CAiDataLeoFeature* &features[], int &features_size, ENUM_AIDATA_GEN_TYPE &type, ulong& cols, ulong &rows);
2026-01-30 08:38:10 -05:00
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
2026-02-02 17:45:09 -05:00
// Notas
// - Tener cudidad con que cols no sea mayor a int.. (valor) para evitar overflow.. aunque es muy improbable que pase
// - Uso ulong para compatilbidad con el tipo nativo matrix y vector (Cols, Rows, Size, retornrnan valores UL)
bool CAiDataLeoFeaturesParser::Parse(const string& src, CAiDataLeoFeature* &features[], int &features_size, ENUM_AIDATA_GEN_TYPE &type, ulong& cols, ulong &rows)
2026-01-30 08:38:10 -05:00
{
//---
string msg = "";
AiDataByLeoClasifierToken tokens[];
if(!CAiDataLeoFeaturesClasifiers::Clasificar(src, tokens, msg))
{
LogError(msg, FUNCION_ACTUAL);
return false;
}
//---
2026-02-06 11:25:48 -05:00
if(IsInfoLogEnabled())
CAiDataLeoFeaturesClasifiers::PrintTokens(tokens);
//---
2026-01-30 08:38:10 -05:00
const int total = ArraySize(tokens);
int last_feature_idx = -1;
2026-02-02 17:45:09 -05:00
// En caso que el contexto global sea MATRIX entonces deberemos de alamcnar el numero de filas EXACTo
// Que cada contexto local requiere
int mtx_global_row_size = 0;
int mtx_local_row_c = 0;
// Indices
2026-01-30 08:38:10 -05:00
int last_idx_arr[];
2026-02-02 17:45:09 -05:00
int last_idx_arr_size = -1;
// Contador en caso se use custom
int last_idx_arr_c = 0;
// Tipo final.. por defecto vector
2026-01-30 08:38:10 -05:00
type = AIDATALEO_GEN_VECTOR;
2026-02-02 17:45:09 -05:00
// Contexto global
int8_t ctx = -1;
// Este entero indica el numero de modelos que se VA ocupando en el contexto global
ulong counter_f = 0ULL;
// Este booleano indica si en este contexto local.. las varaibles se apilan
// Es algo complejo de explicar.. no encuntro las palabras
// Pero a este concepto lo llame custom (ver el clasificador) a difertencia de los "contextos" basicos aqui
// En vez de pasr indices como tal... "acoplamos" vairos modelos y les damos indices CUSTOM a cada uno..
// Esto es util por jemeplo si se quiere en un MATRIX una fila con diferentes modelos (normalmente todos compartiran el mismo INDEXES)
bool multi_f = false;
2026-02-06 11:25:48 -05:00
//--- Valores por defecto
rows = 0;
cols = 0;
2026-02-02 17:45:09 -05:00
2026-01-30 08:38:10 -05:00
//---
for(int i = 0; i < total; i++)
{
switch(tokens[i].type)
{
2026-02-02 17:45:09 -05:00
//--- Configuracion
2026-01-30 08:38:10 -05:00
case AIDATABYLEO_CLASIFIER_TOKEN_INIT:
{
cols = int(tokens[i].text);
break;
}
2026-02-02 17:45:09 -05:00
//--- Inicio de contexto
2026-01-30 08:38:10 -05:00
case AIDATABYLEO_CLASIFIER_TOKEN_CONTEXT:
{
//---
2026-02-06 11:25:48 -05:00
if(StringSplit(tokens[i].text, AIDATAFEATURES_PARSER_SEP_CHAR_U, g_ai_data_fetaures_leo_str_arr) < 2)
2026-01-30 08:38:10 -05:00
{
2026-02-06 11:25:48 -05:00
LogError("Contexto debe de tener como minimo 2 parametros", FUNCION_ACTUAL);
2026-01-30 08:38:10 -05:00
return false;
}
//---
2026-02-02 17:45:09 -05:00
const int8_t abarca = int8_t(g_ai_data_fetaures_leo_str_arr[0]);
2026-02-06 11:25:48 -05:00
Print(abarca);
2026-02-02 17:45:09 -05:00
if(abarca == AIDATAFEATURE_CTX_GBL)
2026-01-30 08:38:10 -05:00
{
2026-02-02 17:45:09 -05:00
ctx = int8_t(g_ai_data_fetaures_leo_str_arr[1]); // Vecotr o Matrix
//---
if(ctx == AIDATAFEATURE_ROW_TYPE_ARRAY) // Matrix
{
mtx_global_row_size = int(g_ai_data_fetaures_leo_str_arr[2]) ; // Numero de filas que debera de tener cada matrix creada
// En este contexto
rows += mtx_global_row_size;
}
else
if(ctx == AIDATAFEATURE_ROW_TYPE_BASIC)
{
rows++;
}
//---
counter_f = 0; // Restablecemos el contador al numero de cols
}
else // Contexto local
{
//--- Check context
if(ctx < 0 || ctx > 1)
{
LogError(StringFormat("Contexto global = %d, es invalido", ctx), FUNCION_ACTUAL);
return false;
}
//--- Es custom
if((multi_f = bool(int(g_ai_data_fetaures_leo_str_arr[1])))) // Continee si es multi o basic
last_idx_arr_c = 0; // En caso se multiple indice sutom reiniciamos contador
//--- Matrix
if(ctx == AIDATAFEATURE_ROW_TYPE_ARRAY) // Contexto global matrix
{
last_idx_arr_size = StringSplit(g_ai_data_fetaures_leo_str_arr[2], ',', g_ai_data_leo_dyn_arr);
if(last_idx_arr_size <= 0)
{
LogError("Fallo al hacer split no hay data", FUNCION_ACTUAL);
return false;
}
//--- Reiniciamos el contador de rows
mtx_local_row_c = int(rows) - mtx_global_row_size; // Fila de inicio
//---
// El numero de datos esperados filas es invlaido
// Dado que debe de ser IGUAL al del matrix ctx global
if(mtx_global_row_size != last_idx_arr_size)
{
LogError(StringFormat("El contexto global mtx requiere = %d filas, el contexto local mtx tiene = %d, modifque el codigo",
mtx_global_row_size, last_idx_arr_size), FUNCION_ACTUAL);
return false;
}
}
else // Vector
if(ctx == AIDATAFEATURE_ROW_TYPE_BASIC) // Contexto global vector
{
//--- Convertimos los indices a array
// Aqui no verificamo el numero de indices en vecotr dado qeu peuyde ser variable
last_idx_arr_size = StringSplit(g_ai_data_fetaures_leo_str_arr[2], ',', g_ai_data_leo_dyn_arr);
if(last_idx_arr_size == -1)
{
LogError("Fallo al hacer split en row de vector", FUNCION_ACTUAL);
return false;
}
}
//--- Str -> int array
2026-02-06 11:25:48 -05:00
Print("Tama<00>o de el: ", last_idx_arr_size);
2026-02-02 17:45:09 -05:00
ArrayResize(last_idx_arr, last_idx_arr_size);
2026-02-06 11:25:48 -05:00
for(int k = 0; k < last_idx_arr_size; k++)
2026-02-02 17:45:09 -05:00
{
2026-02-06 11:25:48 -05:00
last_idx_arr[k] = int(g_ai_data_leo_dyn_arr[k]);
if(last_idx_arr[k] < 0) // Check de valor
2026-02-02 17:45:09 -05:00
{
2026-02-06 11:25:48 -05:00
LogError(StringFormat("Valor invalido en [%d], valor = %d, el valor del indice debe de ser > 0", k, last_idx_arr[k]), FUNCION_ACTUAL);
2026-02-02 17:45:09 -05:00
return false;
}
}
2026-01-30 08:38:10 -05:00
}
//---
break;
}
2026-02-02 17:45:09 -05:00
//--- Fin de contexto
2026-01-30 08:38:10 -05:00
case AIDATABYLEO_CLASIFIER_TOKEN_END_CONTEXT:
{
break;
}
2026-02-02 17:45:09 -05:00
//--- Datos (features)
2026-01-30 08:38:10 -05:00
case AIDATABYLEO_CLASIFIER_TOKEN_DATA:
{
//---
2026-02-06 11:25:48 -05:00
if(counter_f >= cols) // Invalido ya no se permiten mas modelos en este contexto local
2026-02-02 17:45:09 -05:00
{
2026-02-06 11:25:48 -05:00
LogCriticalError(StringFormat("En el contexto local solo se permiten = %I64u modelos, usted puso mas de ese numero [%I64u] reduzcalo", cols, counter_f), FUNCION_ACTUAL);
2026-02-02 17:45:09 -05:00
return false; // SEREMOS estrictors no habra advertencias ni ocultaremos simplemente no se permite
}
//--- Split
2026-01-30 08:38:10 -05:00
if(StringSplit(tokens[i].text, AIDATAFEATURES_PARSER_SEP_CHAR_U, g_ai_data_fetaures_leo_str_arr) != 3)
{
2026-02-06 11:25:48 -05:00
LogError(StringFormat("Feature debe de tener 3 valores [Name][Prefijo][Parametros] feauture:\n%s", tokens[i].text), FUNCION_ACTUAL);
2026-01-30 08:38:10 -05:00
return false;
}
2026-02-02 17:45:09 -05:00
//--- Creacion del puntero
2026-01-30 08:38:10 -05:00
CAiDataLeoFeature* ptr = CAiDataGenFeatureFactory::GetFeature(g_ai_data_fetaures_leo_str_arr[0], last_feature_idx);
if(ptr == NULL)
{
LogError(StringFormat("Se obtuvo un puntero NULL, para la feature con nombre = %s", g_ai_data_fetaures_leo_str_arr[0]), FUNCION_ACTUAL);
return false;
}
2026-02-02 17:45:09 -05:00
//--- Soporta idx?
2026-01-30 08:38:10 -05:00
const bool support_idx = g_ai_data_leo_factory[last_feature_idx].support_idx;
2026-02-02 17:45:09 -05:00
//--- Evaluacion (MATRIX o VECTOR dependeido del contexto)
if(ctx == AIDATAFEATURE_ROW_TYPE_ARRAY) // MATRIX
2026-01-30 08:38:10 -05:00
{
2026-02-02 17:45:09 -05:00
//--- Nueva fil
if(mtx_local_row_c >= int(rows)) // Si es mayor o igual al rows
2026-01-30 08:38:10 -05:00
{
2026-02-02 17:45:09 -05:00
LogError(StringFormat("No se permiten mas de %d lenth por cada matrix local", mtx_global_row_size), FUNCION_ACTUAL);
2026-01-30 08:38:10 -05:00
return false;
}
2026-02-02 17:45:09 -05:00
//---
if(multi_f) // Se necestia atencion
2026-01-30 08:38:10 -05:00
{
2026-02-02 17:45:09 -05:00
//--- Indice
const int idx = multi_f ? (last_idx_arr[last_idx_arr_c++]) : (last_idx_arr[0]);
//--- Checkeo
if(!support_idx)
{
if(idx > 1) // Error
{
LogError(StringFormat("La feature con nombre = %s, no soporta indices > 1", g_ai_data_fetaures_leo_str_arr[0]), FUNCION_ACTUAL);
delete ptr; // Lo eliminamos
return false;
}
}
//--- Inicilizar
if(!ptr.Initialize(g_ai_data_fetaures_leo_str_arr[2], idx))
{
delete ptr;
LogError(StringFormat("Fallo al inicio la feature = %s\nParametros:\n%s", g_ai_data_fetaures_leo_str_arr[0], g_ai_data_fetaures_leo_str_arr[2]), FUNCION_ACTUAL);
return false;
}
//--- Seteamos
ptr.SetExtra(counter_f, ulong(mtx_local_row_c), ulong(mtx_local_row_c)); // Solo 1 dato aqui
}
else
{
//--- Checkeo
// Iteramos sobre todas los indices que debera de generar dicha feature
// SOlo en caso que NO se soporte vairos infdices, osea que si la feautre no puede soportar varios inices ocustom
// Haremos esa revision en caso se encuntren esos idnices, retonraremos false
if(!support_idx)
{
2026-02-06 11:25:48 -05:00
for(int k = 0; k < last_idx_arr_size; k++)
2026-02-02 17:45:09 -05:00
{
2026-02-06 11:25:48 -05:00
if(last_idx_arr[k] > 1)
2026-02-02 17:45:09 -05:00
{
LogError(StringFormat("La feature con nombre = %s, no soporta indices > 1", g_ai_data_fetaures_leo_str_arr[0]), FUNCION_ACTUAL);
delete ptr; // Lo eliminamos
return false;
}
}
}
//--- Inicilizar
if(!ptr.Initialize(g_ai_data_fetaures_leo_str_arr[2], last_idx_arr)) // Le pasamos el array esta vez generara un vector
{
delete ptr;
LogError(StringFormat("Fallo al inicio la feature = %s\nParametros:\n%s", g_ai_data_fetaures_leo_str_arr[0], g_ai_data_fetaures_leo_str_arr[2]), FUNCION_ACTUAL);
return false;
}
//--- Seteamos
// Aqui geenramos desde una columan y desde el inciio de fila hasta el ultimo valor posible indice fila
ptr.SetExtra(counter_f, ulong(rows - last_idx_arr_size), ulong(rows - 1)); //
2026-01-30 08:38:10 -05:00
}
2026-02-02 17:45:09 -05:00
//--- Aumentamos el contador
mtx_local_row_c++;
2026-01-30 08:38:10 -05:00
}
2026-02-02 17:45:09 -05:00
else // VECTOR
{
//--- Obtencion del indice
// El indice es en base a multi_f
// Si es true entonces se coje el indice dado
// Si es false entonces es un indcei "constante"
const int idx = multi_f ? (last_idx_arr[last_idx_arr_c++]) : (last_idx_arr[0]);
2026-01-30 08:38:10 -05:00
2026-02-02 17:45:09 -05:00
//--- Checkeo
if(!support_idx)
{
if(idx > 1) // Error
{
LogError(StringFormat("La feature con nombre = %s, no soporta indices > 1", g_ai_data_fetaures_leo_str_arr[0]), FUNCION_ACTUAL);
delete ptr; // Lo eliminamos
return false;
}
}
2026-01-30 08:38:10 -05:00
2026-02-02 17:45:09 -05:00
//--- Inicilizar
if(!ptr.Initialize(g_ai_data_fetaures_leo_str_arr[2], idx))
{
delete ptr;
LogError(StringFormat("Fallo al inicio la feature = %s\nParametros:\n%s", g_ai_data_fetaures_leo_str_arr[0], g_ai_data_fetaures_leo_str_arr[2]), FUNCION_ACTUAL);
return false;
}
}
2026-02-02 20:21:53 -05:00
//---
ptr.SetExtra(counter_f, (rows - 1), (rows - 1)); // Siempre la ultima fila para vector (todo este grupo)
2026-02-02 17:45:09 -05:00
//--- Nueva feautre
2026-01-30 08:38:10 -05:00
features[ArrayResize(features, (++features_size)) - 1] = ptr;
2026-02-02 17:45:09 -05:00
//--- Para la siguiente
counter_f++;
2026-01-30 08:38:10 -05:00
//---
break;
}
default:
LogFatalError("Token desconocido", FUNCION_ACTUAL);
return false;
}
}
2026-02-02 17:45:09 -05:00
//--- Chekeo final
// Numero de features valido
if(features_size < 1)
{
LogError("No hay features", FUNCION_ACTUAL);
return false;
}
// Obtenemos el tipo
2026-02-06 11:25:48 -05:00
/*Print("---- Tipo");
Print(rows);
Print(cols);*/
2026-02-02 17:45:09 -05:00
if(rows > 1) // Mas de un row
type = AIDATALEO_GEN_MATRIX; // Ahora sera del tipo MATRIX
2026-01-30 08:38:10 -05:00
//---
return true;
}
2026-02-02 20:21:53 -05:00
//--- Obejeto global
CAiDataLeoFeaturesParser g_ai_data_features_parser;
2026-01-30 08:38:10 -05:00
//+------------------------------------------------------------------+
#endif // AIDATAGENBYLEO_GENERIC_DATA_PARSER_PARSER_MQH