/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Library // ------------------------------------------------- // Name: XCXFIMAEALib ... // Description: XFIMAEA Library ... // // // 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 XFIMAEA Library" #property strict // // Imports ... #include "../../Classes/x-saherelm.x-cobject.class.mq5" #include "../../Helpers/x-saherelm.xfima.helper.mq5" // // Definitions ... // // Enumerations ... // // ZigZag Point Type ... enum ENUM_X_ZIGZAG_POINT_TYPE { X_ZIGZAG_PIVOT_TYPE_NONE = 0, // None X_ZIGZAG_PIVOT_TYPE_PEAK = 1, // PEAK X_ZIGZAG_PIVOT_TYPE_VALE = 2, // VALE }; /** * Validate ... * * @param value: ENUM_X_ZIGZAG_POINT_TYPE ... * * @return ( bool ) */ bool IsXValid(ENUM_X_ZIGZAG_POINT_TYPE value) { // bool result = false; // result = value != X_ZIGZAG_PIVOT_TYPE_NONE; // return result; } /** * Represent Specified ZigZag Point Type as String ... * * @param value: ENUM_X_ZIGZAG_POINT_TYPE ... * * @return ( string ) */ string ToXString(ENUM_X_ZIGZAG_POINT_TYPE value) { return EnumToString(value); } // // Structs ... /** * Specified ZigZag Point ... **/ struct XZigZagPivot { // // Props ... double value; // Value datetime time; // Time string symbol; // Symbol ENUM_X_DIRECTION dir; // Direction ENUM_TIMEFRAMES period; // Period ENUM_X_ZIGZAG_POINT_TYPE type; // Type // // Constructor ... XZigZagPivot() { Clean(); } // // Init ... /** * Initialize Structure ... * * @param _value: double, value of point ... * @param _time: datetime, time of point ... * @param _symbol: string, Symbol ... * @param _dir: ENUM_X_DIRECTION, direction of point ... * @param _period: ENUM_TIMEFRAMES, period ... * @param _type: ENUM_X_ZIGZAG_POINT_TYPE, point type ... * * @return ( bool ) */ bool Init( double _value, datetime _time, string _symbol, ENUM_X_DIRECTION _dir, ENUM_TIMEFRAMES _period, ENUM_X_ZIGZAG_POINT_TYPE _type // ) { // bool result = false; // dir = _dir; time = _time; type = _type; value = _value; symbol = _symbol; period = _period; // result = IsValid(); if (!result) { Clean(); } // return result; } // // Tools ... /** * Cleanup Model ... */ void Clean() { // value = 0; time = NULL; symbol = NULL; period = NULL; dir = X_DIRECTION_NONE; type = X_ZIGZAG_PIVOT_TYPE_NONE; // ZeroMemory(this); } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = value > 0 && IsXValid(type) && HasDirection(dir) && IsSpecifiedValid(time) && IsSpecifiedValid(symbol) && IsSpecifiedValid(period); // return result; } /** * Check Point is Bullish or not ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = IsValid() && IsSpecifiedBullish(dir); // return result; } /** * Check Point is Bearish or not ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = IsValid() && IsSpecifiedBearish(dir); // return result; } /** * Check two Struct are Same or not ... * * @param item: XZigZagPivot ... * * @return ( bool ) */ bool IsSameAs(XZigZagPivot &item) { // bool result = false; // result = IsValid() && item.IsValid() && dir == item.dir && type == item.type && time == item.time && value == item.value && symbol == item.symbol && period == item.period; // return result; } /** * Check Structure Exists in Specified Collection or not ... * * @param items: XZigZagPivot, reference Array ... * @param index: int, reference to Holds Founded Index ... * * @return ( bool ) */ bool IsExists( XZigZagPivot &items[], int &index // ) { // bool result = false; // // Prepare ... index = -1; // // Validate ... result = IsValid() && HasChild(items); if (!result) { return result; } // int count = ArraySize(items); for (int i = 0; i < count; i++) { // result = IsSameAs(items[i]); if (result) { // index = i; // break; } } // result = result && IsValidIndex(index); // return result; } /** * Add Structure to Specified Collection only if not Exists ... * * @param items: XZigZagPivot, reference Array ... */ void AddIfNotExists(XZigZagPivot &items[]) { // // Validate ... if (!IsValid()) { return; } // if (!HasChild(items)) { // AddRef( this, items // ); // return; } // int index = -1; bool isExists = IsExists(items, index); if (!isExists) { // AddRef( this, items // ); } } /** * Calculate Pivot Age ... * * @return ( int ) */ int GetAge() { // int result = -1; // if (!IsValid()) { return result; } // result = GetBarIndex( symbol, period, time // ); // return result; } /** * Check to model Has Same Symbol ... * * @param item: XZigZagXZigZagPivotAXZigZagPivotnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameSymbolAs(XZigZagPivot &item) { // bool result = false; // result = IsValid() && item.IsValid() && symbol == item.symbol; // return result; } /** * Check to model Has Same Period ... * * @param item: XZigZagPivot, dest model for Checking ... * * @return ( bool ) */ bool IsSamePeriodAs(XZigZagPivot &item) { // bool result = false; // result = IsValid() && item.IsValid() && period == item.period; // return result; } /** * Check to model Has Same Symbol/Period ... * * @param item: XZigZagPivot, dest model for Checking ... * * @return ( bool ) */ bool IsSameMarketAs(XZigZagPivot &item) { // bool result = false; // result = IsValid() && item.IsValid() && IsSameSymbolAs(item) && IsSamePeriodAs(item); // return result; } /** * Check to model Has Same Type ... * * @param item: XZigZagPivot, dest model for Checking ... * * @return ( bool ) */ bool IsSameTypeAs(XZigZagPivot &item) { // bool result = false; // result = IsValid() && item.IsValid() && type == item.type; // return result; } /** * Check to model Has Same Direction ... * * @param item: XZigZagPivot, dest model for Checking ... * * @return ( bool ) */ bool IsSameDirectionAs(XZigZagPivot &item) { // bool result = false; // result = IsValid() && item.IsValid() && dir == item.dir; // return result; } // // Logging Tools ... /** * Extract Specified Token of Struct ... * * @return ( string ) */ string GetTag() { return GetToken(this); } /** * Represent an String Unique Identifier for Chart Objects ... * * @return ( string ) */ string GetObjectID() { // string result = ""; // if (!IsValid()) { return result; } // result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(type) + "_" + ToXString(TimeToSeconds(time)); // return result; } /** * Represent a Point as String ... * * @param spacer: string, How to Represent Spaces ... * * @return ( string ) */ string GetMessage(string spacer = NULL) { // string result = ""; // // Normalize Spacer ... if (!IsSpecifiedValid(spacer)) { spacer = " "; } // // Validate ... if (!IsValid()) { return result; } // result = ToXString(dir) + spacer + GetTag() + ":" + spacer + "Symbol: " + symbol + spacer + "Period: " + ToXString(period) + spacer + "Type: " + ToXString(type) + spacer + "Direction: " + ToXString(dir) + spacer + "Value: " + ToXString(value) + spacer + "Time: " + ToXString(time) + spacer; // return result; } }; /** * Specified ZigZag based Market Analysis ... **/ struct XZigZagAnalysis { // // Props ... string symbol; // Symbol ... datetime time; // Time ... ENUM_TIMEFRAMES period; // Period ... XZigZagPivot pivots[]; // ZigZag Pivots ... // ENUM_X_DIRECTION dir; // Direction ... // // Constructor ... XZigZagAnalysis() { Clean(); } // // Initialize ... /** * Analyse Market Structure ... * * @param bar: XOHCL, Specified Bar ... * @param _pivots: XZigZagPivot, Specified ZigZag Points Collection ... * * @return ( bool ) */ bool Analyse( XOHCL &bar, XZigZagPivot &_pivots[] // ) { // bool result = false; // // Validate ... result = bar.IsValid() && HasChild(_pivots) && bar.symbol == _pivots[0].symbol; if (!result) { // Clean(); return result; } // // AssignSymbol and Period ... time = bar.time; symbol = bar.symbol; period = bar.period; // // Extracting Pivots ... int numberOfPivots = 2; // // Reading Recent Peaks ... XZigZagPivot recentPeaks[]; int recentPeaksCount = GetRecent( _pivots, recentPeaks, numberOfPivots, X_ZIGZAG_PIVOT_TYPE_PEAK // ); // // Reading Recent Vales ... XZigZagPivot recentVales[]; int recentValesCount = GetRecent( _pivots, recentVales, numberOfPivots, X_ZIGZAG_PIVOT_TYPE_VALE // ); // // Validate Pivots ... result = recentPeaksCount >= numberOfPivots && recentValesCount >= numberOfPivots; if (!result) { // Clean(); SpecifiedClean(recentPeaks); SpecifiedClean(recentVales); // return result; } // // Detect Direction ... // int zIdx = 0; int pIdx = numberOfPivots - 1; // bool isBullish = recentPeaks[zIdx].value > recentPeaks[pIdx].value && recentVales[zIdx].value > recentVales[pIdx].value; // bool isBearish = recentPeaks[zIdx].value < recentPeaks[pIdx].value && recentVales[zIdx].value < recentVales[pIdx].value; // result = isBullish || isBearish; if (!result) { // Clean(); SpecifiedClean(recentPeaks); SpecifiedClean(recentVales); // return result; } // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // Copy(_pivots, pivots); // // Calculate Support and Resistance ... // // Validate ... result = IsValid(); if (!result) { Clean(); } // SpecifiedClean(recentPeaks); SpecifiedClean(recentVales); // return result; } // // Tools ... /** * Cleanup Model ... */ void Clean() { // time = NULL; symbol = NULL; period = NULL; dir = X_DIRECTION_NONE; SpecifiedClean(pivots); // ZeroMemory(this); } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // HasChild(pivots) && HasDirection(dir) && IsSpecifiedValid(time) && IsSpecifiedValid(symbol) && IsSpecifiedValid(period) // ; // return result; } /** * Calculate Analysis Age, based on Specified Time Frame ... * * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... * * @return ( int ) */ int GetAge( ENUM_TIMEFRAMES forPeriod = NULL // ) { // int result = -1; // // Validate ... if (!IsValid()) { return result; } // // Normalize ... if (!IsSpecifiedValid(forPeriod)) { forPeriod = period; } // result = GetBarIndex( symbol, forPeriod, time // ); // return result; } /** * Check Market Direction is Bullish or not ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = IsValid() && IsSpecifiedBullish(dir); // return result; } /** * Check Market Direction is Bearish or not ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = IsValid() && IsSpecifiedBearish(dir); // return result; } /** * Check two item is Same or not ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && time == item.time && IsSameMarketAs(item); // return result; } /** * Check to model Has Same Symbol ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameSymbolAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && symbol == item.symbol; // return result; } /** * Check to model Has Same Period ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSamePeriodAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && period == item.period; // return result; } /** * Check to model Has Same Symbol/Period ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameMarketAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && IsSameSymbolAs(item) && IsSamePeriodAs(item); // return result; } /** * Check to model Has Same Direction ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameDirectionAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && dir == item.dir; // return result; } /** * Check to model Has Analysis Trend ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameTrendAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && IsSameMarketAs(item) && IsSameDirectionAs(item); // return result; } // // Pivots Tools ... /** * Get Highest Specified Pivot ... * * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Pivot Type ... * * @return ( int ) */ int GetHighestPivot( ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // if (!IsValid()) { return result; } // bool has = false; XZigZagPivot iPivot; int count = ArraySize(pivots); for (int i = 0; i < count; i++) { // // Check Type ... has = !IsXValid(type) || (IsXValid(type) && type == pivots[i].type); if (!has) { continue; } // // Check Relation based on last Detected Pivot ... has = !iPivot.IsValid() || (iPivot.IsValid() && iPivot.value < pivots[i].value); if (has) { // result = i; iPivot = pivots[i]; } } // has = iPivot.IsValid() && IsValidIndex(result); iPivot.Clean(); // return result; } /** * Get Lowest Specified Pivot ... * * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Pivot Type ... * * @return ( int ) */ int GetLowestPivot( ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // if (!IsValid()) { return result; } // bool has = false; XZigZagPivot iPivot; int count = ArraySize(pivots); for (int i = 0; i < count; i++) { // // Check Type ... has = !IsXValid(type) || (IsXValid(type) && type == pivots[i].type); if (!has) { continue; } // // Check Relation based on last Detected Pivot ... has = !iPivot.IsValid() || (iPivot.IsValid() && iPivot.value > pivots[i].value); if (has) { // result = i; iPivot = pivots[i]; } } // has = iPivot.IsValid() && IsValidIndex(result); iPivot.Clean(); // return result; } /** * Get Oldest Specified Pivot ... * * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Pivot Type ... * * @return ( int ) */ int GetOldestPivot( ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // if (!IsValid()) { return result; } // bool has = false; XZigZagPivot iPivot; int count = ArraySize(pivots); for (int i = 0; i < count; i++) { // // Check Type ... has = !IsXValid(type) || (IsXValid(type) && type == pivots[i].type); if (!has) { continue; } // // Check Relation based on last Detected Pivot ... has = !iPivot.IsValid() || (iPivot.IsValid() && iPivot.time > pivots[i].time); if (has) { // result = i; iPivot = pivots[i]; } } // has = iPivot.IsValid() && IsValidIndex(result); iPivot.Clean(); // return result; } /** * Get Youngest Specified Pivot ... * * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Pivot Type ... * * @return ( int ) */ int GetYoungestPivot( ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!IsValid()) { return result; } // bool has = false; XZigZagPivot iPivot; int count = ArraySize(pivots); for (int i = 0; i < count; i++) { // // Check Type ... has = !IsXValid(type) || (IsXValid(type) && type == pivots[i].type); if (!has) { continue; } // // Check Relation based on last Detected Pivot ... has = !iPivot.IsValid() || (iPivot.IsValid() && iPivot.time > pivots[i].time); if (has) { // result = i; iPivot = pivots[i]; } } // has = iPivot.IsValid() && IsValidIndex(result); iPivot.Clean(); // return result; } /** * Get Recent Number of Specified Type of Pivots ... * * @param recent: XZigZagPivot, Collection reference as result ... * @param numberOfRequiredPivots: int, required number of Pivots ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, type of Pivot ... * * @return ( int ) */ int GetRecentPivots( XZigZagPivot &recent[], int numberOfRequiredPivots = 2, ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // result = GetRecent( pivots, recent, numberOfRequiredPivots, type // ); // return result; } // // Loggint Tools ... /** * Extract Specified Token of Struct ... * * @return ( string ) */ string GetTag() { return GetToken(this); } /** * Represent an String Unique Identifier for Chart Objects ... * * @return ( string ) */ string GetObjectID() { // string result = ""; // if (!IsValid()) { return result; } // result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(TimeToSeconds(time)); // return result; } /** * Represent a Point as String ... * * @param spacer: string, How to Represent Spaces ... * * @return ( string ) */ string GetMessage(string spacer = NULL) { // string result = ""; // // Normalize Spacer ... if (!IsSpecifiedValid(spacer)) { spacer = " "; } // // Validate ... if (!IsValid()) { return result; } // result = ToXString(dir) + spacer + GetTag() + ":" + spacer + "Symbol: " + symbol + spacer + "Period: " + ToXString(period) + spacer + "Direction: " + ToXString(dir) + spacer + "Time: " + ToXString(time) + spacer; // return result; } // }; /** * XZigZagAnalysis Chart Object ... **/ class XCZigZagAnalysisObject : public XCBaseObject { // public: // /** * Create Object ... * * @param chart_id: Long, Specified Chart ID ... * @param window: Integer, Specified Chart Window ID ... * @param model: XZigZagAnalysis, reference model ... * * @return ( bool ) */ bool Create( long chart_id, int window, XZigZagAnalysis &model, int numberOfPivots = 2 // ) { // bool result = false; // // Normalize ... numberOfPivots = NormalizeInt(numberOfPivots, 2); // // Validate ... result = model.IsValid(); if (!result) { return result; } // // Generate Object ID ... string objID = model.GetObjectID(); string upperName = "Upper_" + objID; string lowerName = "Lower_" + objID; // // Extract Recent Pivots ... // // Peaks ... XZigZagPivot rPeaks[]; int count = model.GetRecentPivots( rPeaks, numberOfPivots, X_ZIGZAG_PIVOT_TYPE_PEAK // ); // // Vales ... XZigZagPivot rVales[]; count = model.GetRecentPivots( rVales, numberOfPivots, X_ZIGZAG_PIVOT_TYPE_VALE // ); // // Creating Upper ... result = mUpper.Create( chart_id, upperName, window, rPeaks[0].time, rPeaks[0].value, rPeaks[numberOfPivots - 1].time, rPeaks[numberOfPivots - 1].value // ); if (!result) { return result; } // // Create Lower ... result = mLower.Create( chart_id, lowerName, window, rVales[0].time, rVales[0].value, rVales[numberOfPivots - 1].time, rVales[numberOfPivots - 1].value // ); if (!result) { // mUpper.Detach(); mUpper.Delete(); // return result; } // // Setting Object Name ... if (result) { ObjName(objID); } // return result; } // // Virtuals ... /** * Retrieve Object Type ... * * @return ( ENUM_XCHARTOBJECTS ) */ virtual int Type() { return 9860; } // // Styling ... /** * Set Width ... * * @param value: Integer ... */ void UpperWidth(int value) { // if (value < 1) { value = 1; } // mUpper.Width(value); } /** * Set Color ... * * @param value: Color ... */ void UpperColor(color value) { // mUpper.Color(value); } /** * Set Style ... * * @param value: ENUM_LINE_STYLE member ... */ void UpperStyle(ENUM_LINE_STYLE value) { // mUpper.Style(value); } /** * Specified Upper Ray to Left or not ... * * @param value: bool */ void UpperRayLeft(bool value) { mUpper.RayLeft(value); } /** * Specified Upper Ray to Right or not ... * * @param value: bool */ void UpperRayRight(bool value) { mUpper.RayRight(value); } /** * Set Width ... * * @param value: Integer ... */ void LowerWidth(int value) { // if (value < 1) { value = 1; } // mLower.Width(value); } /** * Set Color ... * * @param value: Color ... */ void LowerColor(color value) { // mLower.Color(value); } /** * Set Style ... * * @param value: ENUM_LINE_STYLE member ... */ void LowerStyle(ENUM_LINE_STYLE value) { // mLower.Style(value); } /** * Specified Lower Ray to Left or not ... * * @param value: bool */ void LowerRayLeft(bool value) { mLower.RayLeft(value); } /** * Specified Lower Ray to Right or not ... * * @param value: bool */ void LowerRayRight(bool value) { mLower.RayRight(value); } // private: // CChartObjectTrend mUpper; CChartObjectTrend mLower; }; // // Extensions ... /** * Get Highest ZigZagPoint Index in Specified Collection ... * * @param items: XZigZagPivot, Specified Points Collection to Search ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetHighest( XZigZagPivot &items[], ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(items)) { return result; } // bool has = false; XZigZagPivot iPoint; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == items[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && items[i].value > iPoint.value)); if (has) { // result = i; iPoint = items[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } /** * Get Lowest ZigZagPoint Index in Specified Collection ... * * @param items: XZigZagPivot, Specified Points Collection to Search ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetLowest( XZigZagPivot &items[], ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(items)) { return result; } // bool has = false; XZigZagPivot iPoint; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == items[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && items[i].value < iPoint.value)); if (has) { // result = i; iPoint = items[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } /** * Get Oldest ZigZagPoint Index in Specified Collection ... * * @param items: XZigZagPivot, Specified Points Collection to Search ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetOldest( XZigZagPivot &items[], ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(items)) { return result; } // bool has = false; XZigZagPivot iPoint; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == items[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && items[i].GetAge() > iPoint.GetAge())); if (has) { // result = i; iPoint = items[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } /** * Get Youngest ZigZagPoint Index in Specified Collection ... * * @param items: XZigZagPivot, Specified Points Collection to Search ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetYoungest( XZigZagPivot &items[], ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(items)) { return result; } // bool has = false; XZigZagPivot iPoint; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == items[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && items[i].GetAge() < iPoint.GetAge())); if (has) { // result = i; iPoint = items[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } /** * Get Recent Number of Specified Type of Pivots ... * * @param source: XZigZagPivot, Collection reference as Data Source ... * @param recent: XZigZagPivot, Collection reference as result ... * @param numberRequiredItems: int, required number of Pivots ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, type of Pivot ... * * @return ( int ) */ int GetRecent( XZigZagPivot &source[], XZigZagPivot &recent[], int numberRequiredItems = 2, ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_PIVOT_TYPE_NONE // ) { // int result = 0; // int idx = -1; bool has = false; // // Prepare ... SpecifiedClean(recent); // // Normalize ... numberRequiredItems = NormalizeInt(numberRequiredItems, 1); // result = ArraySize(recent); // XZigZagPivot tmp[]; Copy( source, tmp // ); // // Looping to Detect Recent Pivots ... XZigZagPivot iPoint; while (ArraySize(tmp) > 0 && ArraySize(recent) < numberRequiredItems) { // // Find Youngest of Type Index ... idx = GetYoungest( tmp, type // ); has = IsValidIndex(idx); if (!has) { continue; } // // Extract Item ... iPoint = tmp[idx]; // // Remove Item ... ArrayRemove( tmp, idx, 1 // ); // // Validate Item and Add it to Recent ... has = iPoint.IsValid(); if (has) { // AddRef( iPoint, recent // ); } // // Check For Breaking Loop ... // // If Detect Recent is Passed ... has = ArraySize(recent) == numberRequiredItems; if (has) { break; } // // If not anymore items ... has = ArraySize(tmp) > 0; if (!has) { break; } } // result = ArraySize(recent); // // Cleanup Resources ... iPoint.Clean(); SpecifiedClean(tmp); // return result; } //