/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class // ------------------------------------------------- // Name: XCXFIMAPoiDetector ... // Description: XFIMA POI Detector Class ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XFIMA POI Detector Class" #property strict // // Imports ... #include "../../Classes/x-saherelm.base.class.mq5" #include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../../Classes/x-saherelm.x-market.pattern.class.mq5" #include "../Libraries/x-saherelm.xfima.lib.mq5" // // Definitions ... enum ENUM_XFIMA_PIVOTS { XFIMA_PIVOT_NONE = 0, XFIMA_PIVOT_PV = 1, XFIMA_PIVOT_ZIGZAG = 2, XFIMA_PIVOT_MA_CROSS = 3, XFIMA_PIVOT_HK_SWITCH = 4, XFIMA_PIVOT_SAR_SWITCH = 5, XFIMA_PIVOT_BOUNDARY_SWITCH = 6, }; bool IsXValid(ENUM_XFIMA_PIVOTS value) { // bool result = false; // result = value != XFIMA_PIVOT_NONE; // return result; } string ToXString(ENUM_XFIMA_PIVOTS value) { // string result = NULL; // if (!IsXValid(value)) { return result; } // switch (value) { // case XFIMA_PIVOT_NONE: result = "NONE"; break; // case XFIMA_PIVOT_PV: result = "XPV"; break; // case XFIMA_PIVOT_ZIGZAG: result = "XZGP"; break; // case XFIMA_PIVOT_MA_CROSS: result = "XMACRS"; break; // case XFIMA_PIVOT_HK_SWITCH: result = "XHKSWCH"; break; // case XFIMA_PIVOT_SAR_SWITCH: result = "XSARSWCH"; break; // case XFIMA_PIVOT_BOUNDARY_SWITCH: result = "XBNDSWCH"; break; } // return result; } ENUM_XFIMA_PIVOTS ToXFIMAPivots(string value) { // ENUM_XFIMA_PIVOTS result = XFIMA_PIVOT_NONE; // if (!IsXValid(value)) { return result; } // if (value == ToXString(XFIMA_PIVOT_NONE)) { result = XFIMA_PIVOT_NONE; } else if (value == ToXString(XFIMA_PIVOT_PV)) { result = XFIMA_PIVOT_PV; } else if (value == ToXString(XFIMA_PIVOT_ZIGZAG)) { result = XFIMA_PIVOT_ZIGZAG; } else if (value == ToXString(XFIMA_PIVOT_MA_CROSS)) { result = XFIMA_PIVOT_MA_CROSS; } else if (value == ToXString(XFIMA_PIVOT_HK_SWITCH)) { result = XFIMA_PIVOT_HK_SWITCH; } else if (value == ToXString(XFIMA_PIVOT_SAR_SWITCH)) { result = XFIMA_PIVOT_SAR_SWITCH; } else if (value == ToXString(XFIMA_PIVOT_BOUNDARY_SWITCH)) { result = XFIMA_PIVOT_BOUNDARY_SWITCH; } // return result; } // // Implementation ... class XCXFIMAPOIDetector : public XCMarketPatternDetector { // // Public ... public: // // Props ... // string symbol; ENUM_TIMEFRAMES period; // XCBarAnalyser *barAnalyser; // Bar Analyser ... XCXFIMAHelper *fimaHelper; // XFIMA Helper ... XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... // // Constructor ... XCXFIMAPOIDetector( XCXFIMAHelper *_fimaHelper, XCXFIMAHelperParser *_fimaParser // ) : XCMarketPatternDetector() { // barAnalyser = new XCBarAnalyser(); fimaHelper = _fimaHelper; fimaParser = _fimaParser; // symbol = fimaHelper.GetSymbol(); period = fimaHelper.GetPeriod(); } // // Deconstructor ... ~XCXFIMAPOIDetector() { Destroy(); } // // Actions and Tools ... // // Detectors ... // // XPV ... /** * Check Conditions to Detecte XPV based Consolidation Zone ... * * @param zone: XBoxZone, reference to holds detected zone ... * @param barIndex: int, Specified Bar Index ... * @param forcePVBreak: bool, force to has PV Side Break ... * @param forceHasSarSwitch: bool, force to has SAR Switche ... * * @return ( bool ) */ bool DetectPVConsolidationZone( XBoxZone &zone, int barIndex = 0, bool forcePVBreak = false, bool forceHasSarSwitch = false // ) { // bool result = false; // // Prepare ... zone.Clean(); // // Normalize ... barIndex = fimaParser.NormalizeBarIndex(barIndex); // // Validate ... result = fimaParser.IsValid(); if (!result) { return result; } // // Do ... // bool isPeakSame = fimaParser.IsPeakSame(barIndex); bool isValeSame = fimaParser.IsValeSame(barIndex); result = !(isPeakSame && isValeSame); if (!result) { return result; } // double iPeak = EMPTY_VALUE; double iVale = EMPTY_VALUE; // int idx = barIndex; bool canLookup = true; while (canLookup) { // idx++; isPeakSame = fimaParser.IsPeakSame(idx); isValeSame = fimaParser.IsValeSame(idx); result = isPeakSame && isValeSame; if (!result) { // zone.from = GetBarTime(symbol, period, idx); break; } // if (idx == barIndex + 1) { // zone.to = GetBarTime( symbol, period, idx // ); } // zone.from = GetBarTime( symbol, period, idx // ); // iPeak = fimaHelper.GetPeak(idx); iVale = fimaHelper.GetVale(idx); // zone.lower = !NotEmptyZero(zone.lower) ? iVale : MathMin(zone.lower, iVale); // zone.upper = !NotEmptyZero(zone.upper) ? iPeak : MathMax(zone.upper, iPeak); } // // Validating Zone Params ... result = // IsXValid(zone.to) && IsXValid(zone.from) && zone.from < zone.to && // NotEmptyZero(zone.lower) && NotEmptyZero(zone.upper) && zone.upper > zone.lower // ; // // Prepare Zone ... if (result) { // iPeak = fimaHelper.GetPeak(barIndex); iVale = fimaHelper.GetVale(barIndex); bool isPeakOverLast = fimaParser.IsPeakOverLast(barIndex); bool isValeUnderLast = fimaParser.IsValeUnderLast(barIndex); bool isValeBreak = iVale < zone.lower; bool isPeakBreak = iPeak > zone.upper; bool isPVBreak = isPeakBreak || isValeBreak; // zone.at = GetBarTime(symbol, period, barIndex); zone.symbol = symbol; zone.period = period; zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak) ? X_DIRECTION_BULLISH : (isValeUnderLast && !isPeakOverLast && isPVBreak) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); // // Refine Zone Upper and Lower ... if (zone.IsValid()) { // XOHCL iBar; int zoneLoopback = zone.FromIndex() - zone.ToIndex(); result = zone.ToBar(iBar) && IsValidSize(zoneLoopback); if (result) { // double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW); double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH); result = NotEmptyZero(zoneLL) && NotEmptyZero(zoneHH); if (result) { // zone.lower = zone.lower == zoneLL ? zone.lower : MathMax(zone.lower, zoneLL); // zone.upper = zone.upper == zoneHH ? zone.upper : MathMin(zone.upper, zoneHH); } } // iBar.Clean(); } // // Validate ... result = zone.IsValid(); } // // Validate Zones From ... if (result) { // int idx = zone.FromIndex(); // iPeak = fimaHelper.GetPeak(idx); iVale = fimaHelper.GetVale(idx); // bool isValeOverLast = fimaParser.IsValeOverLast(idx); bool isPeakUnderLast = fimaParser.IsPeakUnderLast(idx); // result = result && (zone.IsBullish() ? !isPeakUnderLast : zone.IsBearish() ? !isValeOverLast : false); } // // Apply Forces ... // // PV Break ... // Peak or Vale must Breaked at Bar ... if (result && forcePVBreak) { // bool isPVBreaked = (zone.IsBullish() && fimaParser.IsPeakOverLast(barIndex)) || (zone.IsBearish() && fimaParser.IsValeUnderLast(barIndex)); // result = result && isPVBreaked; } // // Other Loop based Forces ... if (result && (forceHasSarSwitch)) { // bool hasSarSwitch = false; // int start = zone.ToIndex(); int end = zone.FromIndex(); for (int i = start; i <= end; i++) { // // Check Sar Switches ... if (forceHasSarSwitch && !hasSarSwitch) { // hasSarSwitch = zone.IsBullish() ? fimaParser.IsSARSwitchedToBullish(i) : fimaParser.IsSARSwitchedToBearish(i); } } // // Validate Forces ... if (forceHasSarSwitch) { // result = result && hasSarSwitch; } } // // Cleanup ... if (!result) { zone.Clean(); } // return result; } // // Analysors ... /** * Analyse Market ... * * @param structure: XFIMAMarketStructure, reference to holds Market Strucutre ... * @param config: XFIMAMarketStructureConfig, reference to Provide Structure Analyse Config ... * @param barIndex: int, Specified Bar Index ... * * @return ( bool ) */ bool AnalyseMarket( XFIMAMarketStructure &structure, XFIMAMarketStructureConfig &config, int barIndex = 0 // ) { // bool result = false; // // Prepare ... structure.Clean(); // // Normalize ... barIndex = fimaParser.NormalizeBarIndex(barIndex); // // Validate ... result = fimaParser.IsValid(); if (!result) { return result; } // // Do ... int idx = -1; XOHCL tmpBar; datetime fromTime = NULL; XPatternAnalysis tmpBarAnalysis; // // Initialize Indexed Bar ... result = structure.bar.Init(symbol, period, barIndex); // // Analyse Bar Patterns ... if (result) { // result = AnalyseBarPatterns( structure.bar, structure.barAnalysis, config.barsAnalysisConfig // ); } // // Analyse Pivots ... // // XPV ... CollectPVPivots( structure.pvPivots, barIndex, config.requiredPivots, config.loopback // ); // // XMA ... CollectMAPivots( structure.maPivots, barIndex, config.requiredPivots, config.loopback // ); // // XZG ... CollectZGPivots( structure.zgPivots, barIndex, config.requiredPivots, config.loopback // ); // // XHK ... CollectHKPivots( structure.hkPivots, barIndex, config.requiredPivots, config.loopback // ); // // XSAR ... CollectSARPivots( structure.sarPivots, barIndex, config.requiredPivots, config.loopback // ); // // XPV Analysis ... if (result && config.analysePVPivots) { // result = HasChild(structure.pvPivots); // // Check Oldest ... idx = GetOldest(structure.pvPivots); result = IsValidIndex(idx); if (result) { // fromTime = !IsXValid(fromTime) ? structure.pvPivots[idx].time : MathMin(fromTime, structure.pvPivots[idx].time); } // // Initialize Analysis ... if (result) { // result = structure.pvAnalysis.Init( ToXString(XFIMA_PIVOT_PV), symbol, period, structure.pvPivots // ); } } // // XZG Analysis ... if (result && config.analyseZGPivots) { // result = HasChild(structure.zgPivots); // // Check Oldest ... idx = GetOldest(structure.zgPivots); result = IsValidIndex(idx); if (result) { // fromTime = !IsXValid(fromTime) ? structure.zgPivots[idx].time : MathMin(fromTime, structure.zgPivots[idx].time); } // // Initialize Analysis ... if (result) { // result = structure.zgAnalysis.Init( ToXString(XFIMA_PIVOT_ZIGZAG), symbol, period, structure.zgPivots // ); } } // // XHK Analysis ... if (result && config.analyseHKPivots) { // result = HasChild(structure.hkPivots); // // Check Oldest ... idx = GetOldest(structure.hkPivots); result = IsValidIndex(idx); if (result) { // fromTime = !IsXValid(fromTime) ? structure.hkPivots[idx].time : MathMin(fromTime, structure.hkPivots[idx].time); } // // Initialize Analysis ... if (result) { // result = structure.hkAnalysis.Init( ToXString(XFIMA_PIVOT_HK_SWITCH), symbol, period, structure.hkPivots // ); } } // // XMA Analysis ... if (result && config.analyseMAPivots) { result = HasChild(structure.maPivots); // // Check Oldest ... idx = GetOldest(structure.maPivots); result = IsValidIndex(idx); if (result) { // fromTime = !IsXValid(fromTime) ? structure.maPivots[idx].time : MathMin(fromTime, structure.maPivots[idx].time); } // // Initialize Analysis ... if (result) { // result = structure.maAnalysis.Init( ToXString(XFIMA_PIVOT_MA_CROSS), symbol, period, structure.maPivots // ); } } // // XSAR Analysis ... if (result && config.analyseSARPivots) { // result = HasChild(structure.sarPivots); // // Check Oldest ... idx = GetOldest(structure.sarPivots); result = IsValidIndex(idx); if (result) { // fromTime = !IsXValid(fromTime) ? structure.sarPivots[idx].time : MathMin(fromTime, structure.sarPivots[idx].time); } // // Initialize Analysis ... if (result) { // result = structure.sarAnalysis.Init( ToXString(XFIMA_PIVOT_SAR_SWITCH), symbol, period, structure.sarPivots // ); } } // // Order Flow ... if (result && config.detectOrderFlow) { // HasOrderFlow( structure.bar, structure.orderFlowDir, structure.orderFlow, config.orderFlowValidation, config.orderFlowUseOB, config.orderFlowUseFVG, config.orderFlowUseSupportAndResistance, config.barsAnalysisConfig.supportAndResistanceLoopbackLength, config.barsAnalysisConfig.supportAndResistanceValidationLength, config.loopback // ); } // // Analyse Bar Patterns ... if (result && config.analyseBarPatterns) { // // Collect Pivots ... XPivot tmps[]; Copy(structure.pvPivots, tmps, false); Copy(structure.zgPivots, tmps, false); Copy(structure.hkPivots, tmps, false); Copy(structure.maPivots, tmps, false); Copy(structure.sarPivots, tmps, false); // XPivot sames[]; XPivot tmpPivot; int samesCount = 0; while (HasChild(tmps)) { // tmpPivot.Clean(); tmpPivot = tmps[0]; ArrayRemove(tmps, 0, 1); // XClean(sames); samesCount = ExtractSameTimePivots(tmpPivot, sames, tmps); if (HasChild(sames)) { // tmpBar.Clean(); if (sames[0].GetBar(tmpBar)) { // tmpBarAnalysis.Clean(); if (AnalyseBarPatterns(tmpBar, tmpBarAnalysis, config.barsAnalysisConfig)) { // AddRef(tmpBarAnalysis, structure.barsAnalysis); } } // Removes(sames, tmps); } } // // Bars Analysis Exists ... result = HasChild(structure.barsAnalysis); // // Cleanup ... XClean(tmps); XClean(sames); tmpPivot.Clean(); } // // Cleanup ... if (!result) { structure.Clean(); } // return result; } // // Collectors ... /** * Collect ZigZag Pivots ... * * @param pivots: XPivot, reference collection to holds Detected Pivots ... * @param barIndex: int, Specified Start Bar Index ... * @param count: int, Specified number of required Pivots ... * @param loopback: int, Max Allowed Loopback length for Detection ... * * @return ( int ) */ int CollectZGPivots( XPivot &pivots[], int barIndex = 0, int count = 50, int loopback = 500 // ) { // int result = 0; // // Prepare ... XClean(pivots); // // Normalize ... count = NormalizeInt(count, 0); loopback = NormalizeInt(loopback, 50); barIndex = fimaParser.NormalizeBarIndex(barIndex); // // Validate ... bool has = fimaParser.IsValid(); if (!has) { return result; } // // Do ... XOHCL bar; XPivot pivot; int start = barIndex; bool isBullish = false; bool isBearish = false; int end = start + loopback; ENUM_X_DIRECTION dir = X_DIRECTION_NONE; for (int i = start; i < end; i++) { // isBullish = fimaParser.IsZGLow(i); isBearish = fimaParser.IsZGHigh(i); // has = isBullish || isBearish; if (has) { // // Specified Direction ... dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Initialize Indexed Bar ... // Validate it, and Converts it to Pivot ... bar.Clean(); has = bar.Init(symbol, period, i); has = has && ToPivot( bar, pivot, dir, ToXString(XFIMA_PIVOT_ZIGZAG) // ); if (has) { // // Add Detected Pivot ... AddIfNotExists(pivot, pivots); } // has = count <= 0 ? false : ArraySize(pivots) >= count; if (has) { break; } } // // Cleanup ... bar.Clean(); pivot.Clean(); } // result = ArraySize(pivots); // // Cleanup ... bar.Clean(); pivot.Clean(); // return result; } /** * Collect MA Pivots ... * * @param pivots: XPivot, reference collection to holds Detected Pivots ... * @param barIndex: int, Specified Start Bar Index ... * @param count: int, Specified number of required Pivots ... * @param loopback: int, Max Allowed Loopback length for Detection ... * * @return ( int ) */ int CollectMAPivots( XPivot &pivots[], int barIndex = 0, int count = 50, int loopback = 500 // ) { // int result = 0; // // Prepare ... XClean(pivots); // // Normalize ... count = NormalizeInt(count, 0); loopback = NormalizeInt(loopback, 50); barIndex = fimaParser.NormalizeBarIndex(barIndex); // // Validate ... bool has = fimaParser.IsValid(); if (!has) { return result; } // // Do ... XOHCL bar; XPivot pivot; int start = barIndex; bool isBullish = false; bool isBearish = false; int end = start + loopback; ENUM_X_DIRECTION dir = X_DIRECTION_NONE; for (int i = start; i < end; i++) { // isBullish = fimaParser.IsMAFastCrossedOverSlow(i); isBearish = fimaParser.IsMAFastCrossedUnderSlow(i); // has = isBullish || isBearish; if (has) { // // Specified Direction ... dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Initialize Indexed Bar ... // Validate it, and Converts it to Pivot ... bar.Clean(); has = bar.Init(symbol, period, i); has = has && ToPivot( bar, pivot, dir, ToXString(XFIMA_PIVOT_MA_CROSS) // ); if (has) { // // Replace MA Values ... pivot.value = isBullish ? fimaHelper.GetMASlow(barIndex) : fimaHelper.GetMAFast(barIndex); // // Add Detected Pivot ... AddIfNotExists(pivot, pivots); } // has = count <= 0 ? false : ArraySize(pivots) >= count; if (has) { break; } } // // Cleanup ... bar.Clean(); pivot.Clean(); } // result = ArraySize(pivots); // // Cleanup ... bar.Clean(); pivot.Clean(); // return result; } /** * Collect HK Pivots ... * * @param pivots: XPivot, reference collection to holds Detected Pivots ... * @param barIndex: int, Specified Start Bar Index ... * @param count: int, Specified number of required Pivots ... * @param loopback: int, Max Allowed Loopback length for Detection ... * * @return ( int ) */ int CollectHKPivots( XPivot &pivots[], int barIndex = 0, int count = 50, int loopback = 500 // ) { // int result = 0; // // Prepare ... XClean(pivots); // // Normalize ... count = NormalizeInt(count, 0); loopback = NormalizeInt(loopback, 50); barIndex = fimaParser.NormalizeBarIndex(barIndex); // // Validate ... bool has = fimaParser.IsValid(); if (!has) { return result; } // // Do ... XOHCL bar; XPivot pivot; int start = barIndex; bool isBullish = false; bool isBearish = false; int end = start + loopback; ENUM_X_DIRECTION dir = X_DIRECTION_NONE; for (int i = start; i < end; i++) { // isBullish = fimaParser.IsHKSwitchedToBullish(i); isBearish = fimaParser.IsHKSwitchedToBearish(i); // has = isBullish || isBearish; if (has) { // // Specified Direction ... dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Initialize Indexed Bar ... // Validate it, and Converts it to Pivot ... bar.Clean(); has = bar.Init(symbol, period, i); has = has && ToPivot( bar, pivot, dir, ToXString(XFIMA_PIVOT_HK_SWITCH) // ); if (has) { // // Replace Value ... pivot.value = isBullish ? fimaHelper.GetHKLow(i) : fimaHelper.GetHKHigh(i); // // Add Detected Pivot ... AddIfNotExists(pivot, pivots); } // has = count <= 0 ? false : ArraySize(pivots) >= count; if (has) { break; } } // // Cleanup ... bar.Clean(); pivot.Clean(); } // result = ArraySize(pivots); // // Cleanup ... bar.Clean(); pivot.Clean(); // return result; } /** * Collect PV Pivots ... * * @param pivots: XPivot, reference collection to holds Detected Pivots ... * @param barIndex: int, Specified Start Bar Index ... * @param count: int, Specified number of required Pivots ... * @param loopback: int, Max Allowed Loopback length for Detection ... * * @return ( int ) */ int CollectPVPivots( XPivot &pivots[], int barIndex = 0, int count = 50, int loopback = 500 // ) { // int result = 0; // // Prepare ... XClean(pivots); // // Normalize ... count = NormalizeInt(count, 0); loopback = NormalizeInt(loopback, 50); barIndex = fimaParser.NormalizeBarIndex(barIndex); // // Validate ... bool has = fimaParser.IsValid(); if (!has) { return result; } // // Do ... XOHCL bar; XPivot pivot; int start = barIndex; bool isBullish = false; bool isBearish = false; int end = start + loopback; ENUM_X_DIRECTION dir = X_DIRECTION_NONE; for (int i = start; i < end; i++) { // isBullish = fimaParser.IsPeakOverLast(i); isBearish = fimaParser.IsValeUnderLast(i); // has = isBullish || isBearish; if (has) { // // Specified Direction ... dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Initialize Indexed Bar ... // Validate it, and Converts it to Pivot ... bar.Clean(); has = bar.Init(symbol, period, i); has = has && ToPivot( bar, pivot, dir, ToXString(XFIMA_PIVOT_PV) // ); if (has) { // // Replace Value ... pivot.value = isBullish ? fimaHelper.GetHKLow(i) : fimaHelper.GetHKHigh(i); // // Add Detected Pivot ... AddIfNotExists(pivot, pivots); } // has = count <= 0 ? false : ArraySize(pivots) >= count; if (has) { break; } } // // Cleanup ... bar.Clean(); pivot.Clean(); } // result = ArraySize(pivots); // // Cleanup ... bar.Clean(); pivot.Clean(); // return result; } /** * Collect SAR Pivots ... * * @param pivots: XPivot, reference collection to holds Detected Pivots ... * @param barIndex: int, Specified Start Bar Index ... * @param count: int, Specified number of required Pivots ... * @param loopback: int, Max Allowed Loopback length for Detection ... * * @return ( int ) */ int CollectSARPivots( XPivot &pivots[], int barIndex = 0, int count = 50, int loopback = 500 // ) { // int result = 0; // // Prepare ... XClean(pivots); // // Normalize ... count = NormalizeInt(count, 0); loopback = NormalizeInt(loopback, 50); barIndex = fimaParser.NormalizeBarIndex(barIndex); // // Validate ... bool has = fimaParser.IsValid(); if (!has) { return result; } // // Do ... XOHCL bar; XPivot pivot; int start = barIndex; bool isBullish = false; bool isBearish = false; int end = start + loopback; ENUM_X_DIRECTION dir = X_DIRECTION_NONE; for (int i = start; i < end; i++) { // isBullish = fimaParser.IsSARSwitchedToBullish(i); isBearish = fimaParser.IsSARSwitchedToBearish(i); // has = isBullish || isBearish; if (has) { // // Specified Direction ... dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Initialize Indexed Bar ... // Validate it, and Converts it to Pivot ... bar.Clean(); has = bar.Init(symbol, period, i); has = has && ToPivot( bar, pivot, dir, ToXString(XFIMA_PIVOT_SAR_SWITCH) // ); if (has) { // // Add Detected Pivot ... AddIfNotExists(pivot, pivots); } // has = count <= 0 ? false : ArraySize(pivots) >= count; if (has) { break; } } // // Cleanup ... bar.Clean(); pivot.Clean(); } // result = ArraySize(pivots); // // Cleanup ... bar.Clean(); pivot.Clean(); // return result; } // // Others ... /** * Destroy ... */ void Destroy() { // delete barAnalyser; ZeroMemory(barAnalyser); // ZeroMemory(fimaHelper); ZeroMemory(fimaParser); } // // Testers ... // // Protected ... protected: // // Props ... // // Private ... private: // // }; //