2322 lines
35 KiB
Plaintext
2322 lines
35 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Seriallize Library
|
|
// ---------------------------------------
|
|
// Name: XPOILib
|
|
// Description: All models related to POIs ...
|
|
//
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property library
|
|
#property copyright "Copyright `023, SaherElm IT Center"
|
|
#property link "https://www.saherelm.ir"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//
|
|
// Imports ...
|
|
#include "../Libraries/x-saherelm.x-poi.lib.mq5"
|
|
|
|
//
|
|
// Extensions ...
|
|
|
|
template <typename T>
|
|
bool ToBox(
|
|
T *&source[],
|
|
XBoxZone &dest[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *item = source[i];
|
|
|
|
//
|
|
if (item != NULL)
|
|
{
|
|
//
|
|
XBoxZone iBox;
|
|
bool hasBox = ToBox(
|
|
iBox,
|
|
item //
|
|
);
|
|
|
|
//
|
|
if (hasBox)
|
|
{
|
|
//
|
|
AddRef(
|
|
iBox,
|
|
dest //
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
int destCount = ArraySize(dest);
|
|
result = IsValidSize(destCount);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetOldest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetOldest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetYoungest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetYoungest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetLowest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetLowest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
int GetHighest(
|
|
T *&source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone boxes[];
|
|
bool isConverted = ToBox(
|
|
source,
|
|
boxes //
|
|
);
|
|
if (!isConverted)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int boxesCount = ArraySize(boxes);
|
|
|
|
//
|
|
if (count != boxesCount)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = GetHighest(boxes);
|
|
|
|
//
|
|
Clean(boxes);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsSame(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = sourceBox.IsSameAs(destBox);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxBelow(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
T *source,
|
|
T *dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxAbove(
|
|
sourceBox,
|
|
destBox,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInside(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInsideOr(
|
|
T *source,
|
|
T *dest //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone destBox;
|
|
result = ToBox(
|
|
destBox,
|
|
dest //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBoxInsideOr(
|
|
sourceBox,
|
|
destBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool FindIndex(
|
|
int &index,
|
|
T *item,
|
|
T *&items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
XBoxZone itemBox;
|
|
result = ToBox(
|
|
itemBox,
|
|
item //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone itemsBox[];
|
|
result = ToBox(
|
|
items,
|
|
itemsBox //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = FindBoxIndex(
|
|
index,
|
|
itemBox,
|
|
itemsBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsInside(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsInsideBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsAbove(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsAboveBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
bool IsBelow(
|
|
double value,
|
|
T *source //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XBoxZone sourceBox;
|
|
result = ToBox(
|
|
sourceBox,
|
|
source //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsBelowBox(
|
|
value,
|
|
sourceBox //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Specified Box Index inside a Collection of Boxes ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param boxes: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
bool FindBoxIndex(
|
|
int &index,
|
|
XBoxZone &box,
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
int count = ArraySize(boxes);
|
|
result = box.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = boxes[i];
|
|
|
|
//
|
|
bool isSame = box.IsSameAs(iBox);
|
|
if (isSame)
|
|
{
|
|
//
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a BaxHas Valid Place for Specified Bar ...
|
|
*
|
|
* @param bar: XOHCL instance reference, Specified Bar ...
|
|
* #param box: XBoxZone instance reference, Specified Box ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxPlaceValidForBar(
|
|
XOHCL &bar,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = bar.IsValid() &&
|
|
box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
box.IsBullish()
|
|
? bar.low > box.upper
|
|
: bar.high < box.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Below Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBelow(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.upper < dest.lower;
|
|
}
|
|
else
|
|
{
|
|
result = (source.upper < dest.lower ||
|
|
source.upper >= dest.upper) &&
|
|
source.lower < dest.lower;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Above Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param ignoreInside: bool ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxAbove(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool ignoreInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!ignoreInside)
|
|
{
|
|
result = source.lower > dest.upper;
|
|
}
|
|
else
|
|
{
|
|
result = (source.lower > dest.upper ||
|
|
source.lower <= dest.upper) &&
|
|
source.upper > dest.upper;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Source Box is Inside Dest ...
|
|
*
|
|
* @param source: XBoxZone instance Reference ...
|
|
* @param dest: XBoxZone instance Reference ...
|
|
* @param forceSideOut: bool, force check Box has One Side Out ...
|
|
* @param ignoreSideOut: bool, Accept if source Box one Side is out of Dest Box ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxInside(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool forceSideOut = false, //
|
|
bool ignoreSideOut = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(dest.dir);
|
|
|
|
//
|
|
if (!forceSideOut)
|
|
{
|
|
//
|
|
if (ignoreSideOut)
|
|
{
|
|
//
|
|
result = source.lower >= dest.lower &&
|
|
source.upper <= dest.upper;
|
|
}
|
|
else
|
|
{
|
|
result = source.lower >= dest.lower ||
|
|
source.upper <= dest.upper;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
bool hasSideIn =
|
|
isBullish
|
|
? source.lower >= dest.lower
|
|
: source.upper <= dest.upper;
|
|
bool hasSideOut =
|
|
isBullish
|
|
? source.upper >= dest.upper
|
|
: source.lower <= dest.lower;
|
|
result =
|
|
hasSideIn &&
|
|
hasSideOut;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Detect source BoX is Inside Dest Box or Have a Side Out on it ...
|
|
*
|
|
* @param source: XBoxZone instance, source box which checks by dest ...
|
|
* @param dest: XBoxZone instance, dest Box which compares source with it ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxInsideOr(
|
|
XBoxZone &source,
|
|
XBoxZone &dest,
|
|
bool forceInside = false //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
dest.IsValid() &&
|
|
!source.IsSameAs(dest);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isInside =
|
|
source.upper <= dest.upper &&
|
|
source.upper >= dest.lower &&
|
|
source.lower >= dest.lower &&
|
|
source.lower <= dest.upper;
|
|
bool isUpperInside =
|
|
source.upper <= dest.upper &&
|
|
source.upper >= dest.lower;
|
|
bool isLowerInside =
|
|
source.lower >= dest.lower &&
|
|
source.lower <= dest.upper;
|
|
|
|
//
|
|
result =
|
|
forceInside
|
|
? isInside
|
|
: (isInside ||
|
|
isLowerInside ||
|
|
isUpperInside);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Inside Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInsideBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value <= box.upper &&
|
|
value >= box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Bar is Inside Specified Box ...
|
|
*
|
|
* @param bar: XOHCL instance reference, Specified Bar ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsInsideBox(
|
|
XOHCL &bar,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
result = bar.IsValid() &&
|
|
box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
bar.close <= box.upper &&
|
|
bar.close >= box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Above Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsAboveBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value > box.upper;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Value is Below Specified Box ...
|
|
*
|
|
* @param value: double ...
|
|
* @param box: XCBozZone instance Reference ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBelowBox(
|
|
double value,
|
|
XBoxZone &box //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = value > 0 &&
|
|
box.IsValid() &&
|
|
value < box.lower;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Box is Used or not ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param fromIndex: int ...
|
|
* @param toIndex: int
|
|
* @param forPeriod: Specified Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxUsed(
|
|
XBoxZone &box,
|
|
int fromIndex,
|
|
int toIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (toIndex < 0)
|
|
{
|
|
toIndex = 0;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
box.IsValid() &&
|
|
fromIndex > 0 &&
|
|
fromIndex > toIndex
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
bool isTouched = false;
|
|
for (int i = fromIndex; i >= toIndex; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
|
|
//
|
|
isTouched =
|
|
isInited &&
|
|
(isBullish
|
|
? iBar.low > box.upper
|
|
: iBar.high < box.lower);
|
|
if (!isTouched)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = isTouched;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Validate Box ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
* @param barIndex: int, Current Bar Index ...
|
|
* @param forPeriod: Testing Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxValid(
|
|
XBoxZone &box,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
int toIndex = iBarShift(
|
|
box.symbol,
|
|
forPeriod,
|
|
box.to //
|
|
);
|
|
result = IsValidIndex(toIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isBullish = box.IsBullish();
|
|
for (int i = barIndex; i < toIndex; i++)
|
|
{
|
|
//
|
|
result = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? iBar.low > box.upper
|
|
: iBar.high < box.lower;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check Box Breaked ...
|
|
*
|
|
* @param box: XBoxZone instance ...
|
|
* @param barIndex: int, Current Bar Index ...
|
|
* @param forPeriod: Testing Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBreaked(
|
|
XBoxZone &box,
|
|
int barIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = box.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (barIndex < 0)
|
|
{
|
|
barIndex = 0;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
int toIndex = iBarShift(
|
|
box.symbol,
|
|
forPeriod,
|
|
box.to //
|
|
);
|
|
result = IsValidIndex(toIndex);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XOHCL iBar;
|
|
bool isBullish = box.IsBullish();
|
|
for (int i = barIndex; i < toIndex; i++)
|
|
{
|
|
//
|
|
result = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? iBar.high < box.lower
|
|
: iBar.low > box.upper;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Box is Breaked or not ...
|
|
*
|
|
* @param box: XBoxZone instance Reference ...
|
|
* @param fromIndex: int ...
|
|
* @param toIndex: int
|
|
* @param forPeriod: Specified Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsBoxBreaked(
|
|
XBoxZone &box,
|
|
int fromIndex,
|
|
int toIndex = 0,
|
|
ENUM_TIMEFRAMES forPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (toIndex < 0)
|
|
{
|
|
toIndex = 0;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
box.IsValid() &&
|
|
fromIndex > 0 &&
|
|
fromIndex > toIndex
|
|
//
|
|
;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValid(forPeriod))
|
|
{
|
|
forPeriod = box.period;
|
|
}
|
|
|
|
//
|
|
ENUM_X_DIRECTION forDir = box.dir;
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
bool isBreaked = false;
|
|
for (int i = fromIndex; i >= toIndex; i--)
|
|
{
|
|
//
|
|
XOHCL iBar;
|
|
bool isInited = iBar.Init(
|
|
box.symbol,
|
|
forPeriod,
|
|
i //
|
|
);
|
|
|
|
//
|
|
isBreaked =
|
|
isInited &&
|
|
(isBullish
|
|
? iBar.high <= box.lower
|
|
: iBar.low >= box.upper);
|
|
if (!isBreaked)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
iBar.Clean();
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = isBreaked;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find an Inside Box of source in a Collection ...
|
|
*
|
|
* @param index: int, Founded Index ...
|
|
* @param source: XBoxZone instance ...
|
|
* @param dest: XBoxZone instance Collection ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool HasInsideBox(
|
|
int &index,
|
|
XBoxZone &source,
|
|
XBoxZone &dest[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
index = -1;
|
|
|
|
//
|
|
result = source.IsValid() &&
|
|
HasChild(dest);
|
|
|
|
//
|
|
int count = ArraySize(dest);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = dest[i];
|
|
|
|
//
|
|
bool isInside = !iBox.IsSameAs(source) &&
|
|
IsBoxInsideOr(
|
|
iBox,
|
|
source //
|
|
);
|
|
if (isInside)
|
|
{
|
|
//
|
|
index = i;
|
|
iBox.Clean();
|
|
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Remove Specified Box from Collection ...
|
|
*/
|
|
bool RemoveBox(
|
|
XBoxZone &box,
|
|
XBoxZone &boxes[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
box.IsValid() &&
|
|
HasChild(boxes);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int idx = -1;
|
|
result = FindBoxIndex(
|
|
idx,
|
|
box,
|
|
boxes //
|
|
);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArrayRemove(
|
|
boxes,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Oldest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetOldest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
int GetOldest(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from > iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Youngest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetYoungest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
int GetYoungest(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.from < iBox.from;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Highest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetHighest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < iBox.upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
int GetHighest(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.upper < iBox.upper;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Lowest Box Index ...
|
|
*
|
|
* @param source: XBoxZone instance Reference Collection ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetLowest(
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
int GetLowest(
|
|
XOHCL &bar,
|
|
XBoxZone &source[] //
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
if (!bar.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(source);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XBoxZone selected;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XBoxZone iBox = source[i];
|
|
|
|
//
|
|
bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox);
|
|
if (!isBoxValidForBar)
|
|
{
|
|
//
|
|
iBox.Clean();
|
|
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool canSet =
|
|
!selected.IsValid()
|
|
? true
|
|
: selected.lower > iBox.lower;
|
|
if (canSet)
|
|
{
|
|
//
|
|
result = i;
|
|
selected = iBox;
|
|
}
|
|
|
|
//
|
|
iBox.Clean();
|
|
}
|
|
|
|
//
|
|
selected.Clean();
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
template <typename T>
|
|
void SortZones(
|
|
T *&source[],
|
|
ENUM_X_DIRECTION forDir,
|
|
bool ignoreInside = true //
|
|
)
|
|
{
|
|
//
|
|
int idx = -1;
|
|
int count = 0;
|
|
bool has = false;
|
|
|
|
//
|
|
has = HasDirection(forDir);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(forDir);
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
T *tmpItems[];
|
|
T *last = NULL;
|
|
bool hasLast = false;
|
|
while (HasChild(source))
|
|
{
|
|
//
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
idx = GetOldest(source);
|
|
hasLast = IsValidIndex(idx);
|
|
if (hasLast)
|
|
{
|
|
//
|
|
last = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
Add(
|
|
last,
|
|
tmpItems //
|
|
);
|
|
}
|
|
|
|
//
|
|
count = ArraySize(source);
|
|
has = IsValidSize(count);
|
|
if (!has)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
break;
|
|
}
|
|
}
|
|
if (!hasLast)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
break;
|
|
}
|
|
|
|
//
|
|
T *item = NULL;
|
|
idx = GetOldest(source);
|
|
has = IsValidIndex(idx);
|
|
if (!has)
|
|
{
|
|
//
|
|
ZeroMemory(last);
|
|
ZeroMemory(item);
|
|
break;
|
|
}
|
|
item = source[idx];
|
|
ArrayRemove(
|
|
source,
|
|
idx,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
bool isAbove = IsAbove(
|
|
item,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
bool isBelow = IsBelow(
|
|
item,
|
|
last,
|
|
ignoreInside //
|
|
);
|
|
|
|
//
|
|
has =
|
|
isBullish
|
|
? isAbove
|
|
: isBelow;
|
|
if (has)
|
|
{
|
|
//
|
|
Add(
|
|
item,
|
|
tmpItems //
|
|
);
|
|
|
|
//
|
|
last = item;
|
|
hasLast = item != NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(source);
|
|
Copy(
|
|
tmpItems,
|
|
source //
|
|
);
|
|
|
|
//
|
|
Clean(tmpItems);
|
|
}
|
|
|
|
/**
|
|
* Extract all Zones Which provided bar is Inside it ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
template <typename T>
|
|
int ExtractInsideZones(
|
|
XOHCL &bar, // Bar ...
|
|
T *&zones[], // Source of Zones ...
|
|
T *&dest[] // Dest (all inside Zones) ...
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(dest);
|
|
|
|
//
|
|
int count = ArraySize(zones);
|
|
bool isValid = bar.IsValid() &&
|
|
IsValidSize(count);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T *iZone = zones[i];
|
|
|
|
//
|
|
bool isHighInside = IsInside(
|
|
bar.high,
|
|
iZone //
|
|
);
|
|
|
|
//
|
|
bool isLowInside = IsInside(
|
|
bar.low,
|
|
iZone //
|
|
);
|
|
|
|
//
|
|
bool isInside =
|
|
isLowInside &&
|
|
isHighInside;
|
|
|
|
//
|
|
if (isInside)
|
|
{
|
|
//
|
|
Add(
|
|
iZone,
|
|
dest //
|
|
);
|
|
}
|
|
|
|
//
|
|
ZeroMemory(iZone);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(dest);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add Specific Item into a Collection Reference only if it's not Exists ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
template <typename T>
|
|
bool AddIfNotExists(
|
|
T *item,
|
|
T *&items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = item != NULL;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(items);
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
item,
|
|
items //
|
|
);
|
|
bool has = IsValidIndex(idx);
|
|
result = !has;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
item,
|
|
items //
|
|
);
|
|
|
|
//
|
|
int after = ArraySize(items);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool AddIfNotExists(
|
|
XConsolidationZone &item,
|
|
XConsolidationZone &items[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = item.IsValid();
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(items);
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
item,
|
|
items //
|
|
);
|
|
bool has = IsValidIndex(idx);
|
|
result = !has;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
item,
|
|
items //
|
|
);
|
|
|
|
//
|
|
int after = ArraySize(items);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Add items Collection reference Members into source Collection only if it's not Exists ...alignas
|
|
* @return ( int )
|
|
*/
|
|
template <typename T>
|
|
int AddIfNotExists(
|
|
T *&items[],
|
|
T *&sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(sources);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = AddIfNotExists(
|
|
items[i],
|
|
sources //
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(sources);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
int AddIfNotExists(
|
|
XConsolidationZone &items[],
|
|
XConsolidationZone &sources[] //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(sources);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
has = AddIfNotExists(
|
|
items[i],
|
|
sources //
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(sources);
|
|
|
|
//
|
|
result = after > before;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Update to Time of Specifiex Collection ...
|
|
*
|
|
* @param items: XOBFVG instance Collection ...
|
|
* @param value: datetime ...
|
|
*/
|
|
template <typename T>
|
|
void SpecifiedUpdateTo(
|
|
T *&items[],
|
|
datetime value = NULL //
|
|
)
|
|
{
|
|
//
|
|
value = NormalizeTime(value);
|
|
|
|
//
|
|
int count = ArraySize(items);
|
|
bool has = HasChild(items);
|
|
if (!has)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
items[i].To(value);
|
|
}
|
|
}
|
|
|
|
// |