//+------------------------------------------------------------------+ //| 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) {} bool Parse(const string& src, CAiDataLeoFeature* &features[], int &features_size, ENUM_AIDATA_GEN_TYPE &type, ulong& cols, ulong &rows); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // 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) { //--- string msg = ""; AiDataByLeoClasifierToken tokens[]; if(!CAiDataLeoFeaturesClasifiers::Clasificar(src, tokens, msg)) { LogError(msg, FUNCION_ACTUAL); return false; } //--- if(IsInfoLogEnabled()) CAiDataLeoFeaturesClasifiers::PrintTokens(tokens); //--- const int total = ArraySize(tokens); int last_feature_idx = -1; // 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 int last_idx_arr[]; int last_idx_arr_size = -1; // Contador en caso se use custom int last_idx_arr_c = 0; // Tipo final.. por defecto vector type = AIDATALEO_GEN_VECTOR; // 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; //--- Valores por defecto rows = 0; cols = 0; //--- for(int i = 0; i < total; i++) { switch(tokens[i].type) { //--- Configuracion case AIDATABYLEO_CLASIFIER_TOKEN_INIT: { cols = int(tokens[i].text); break; } //--- Inicio de contexto case AIDATABYLEO_CLASIFIER_TOKEN_CONTEXT: { //--- if(StringSplit(tokens[i].text, AIDATAFEATURES_PARSER_SEP_CHAR_U, g_ai_data_fetaures_leo_str_arr) < 2) { LogError("Contexto debe de tener como minimo 2 parametros", FUNCION_ACTUAL); return false; } //--- const int8_t abarca = int8_t(g_ai_data_fetaures_leo_str_arr[0]); Print(abarca); if(abarca == AIDATAFEATURE_CTX_GBL) { 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 Print("Tamaño de el: ", last_idx_arr_size); ArrayResize(last_idx_arr, last_idx_arr_size); for(int k = 0; k < last_idx_arr_size; k++) { last_idx_arr[k] = int(g_ai_data_leo_dyn_arr[k]); if(last_idx_arr[k] < 0) // Check de valor { LogError(StringFormat("Valor invalido en [%d], valor = %d, el valor del indice debe de ser > 0", k, last_idx_arr[k]), FUNCION_ACTUAL); return false; } } } //--- break; } //--- Fin de contexto case AIDATABYLEO_CLASIFIER_TOKEN_END_CONTEXT: { break; } //--- Datos (features) case AIDATABYLEO_CLASIFIER_TOKEN_DATA: { //--- if(counter_f >= cols) // Invalido ya no se permiten mas modelos en este contexto local { LogCriticalError(StringFormat("En el contexto local solo se permiten = %I64u modelos, usted puso mas de ese numero [%I64u] reduzcalo", cols, counter_f), FUNCION_ACTUAL); return false; // SEREMOS estrictors no habra advertencias ni ocultaremos simplemente no se permite } //--- Split if(StringSplit(tokens[i].text, AIDATAFEATURES_PARSER_SEP_CHAR_U, g_ai_data_fetaures_leo_str_arr) != 3) { LogError(StringFormat("Feature debe de tener 3 valores [Name][Prefijo][Parametros] feauture:\n%s", tokens[i].text), FUNCION_ACTUAL); return false; } //--- Creacion del puntero 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; } //--- Soporta idx? const bool support_idx = g_ai_data_leo_factory[last_feature_idx].support_idx; //--- Evaluacion (MATRIX o VECTOR dependeido del contexto) if(ctx == AIDATAFEATURE_ROW_TYPE_ARRAY) // MATRIX { //--- Nueva fil if(mtx_local_row_c >= int(rows)) // Si es mayor o igual al rows { LogError(StringFormat("No se permiten mas de %d lenth por cada matrix local", mtx_global_row_size), FUNCION_ACTUAL); return false; } //--- if(multi_f) // Se necestia atencion { //--- 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) { for(int k = 0; k < last_idx_arr_size; k++) { if(last_idx_arr[k] > 1) { 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)); // } //--- Aumentamos el contador mtx_local_row_c++; } 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]); //--- 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; } } //--- ptr.SetExtra(counter_f, (rows - 1), (rows - 1)); // Siempre la ultima fila para vector (todo este grupo) //--- Nueva feautre features[ArrayResize(features, (++features_size)) - 1] = ptr; //--- Para la siguiente counter_f++; //--- break; } default: LogFatalError("Token desconocido", FUNCION_ACTUAL); return false; } } //--- Chekeo final // Numero de features valido if(features_size < 1) { LogError("No hay features", FUNCION_ACTUAL); return false; } // Obtenemos el tipo /*Print("---- Tipo"); Print(rows); Print(cols);*/ if(rows > 1) // Mas de un row type = AIDATALEO_GEN_MATRIX; // Ahora sera del tipo MATRIX //--- return true; } //--- Obejeto global CAiDataLeoFeaturesParser g_ai_data_features_parser; //+------------------------------------------------------------------+ #endif // AIDATAGENBYLEO_GENERIC_DATA_PARSER_PARSER_MQH