#include "ELMDataPrepare.h"
#include "TrainDataManage.h"
#include "AxisSectionConfigDataManage.h"
#include "LinkConfigDataManage.h"
#include "AxisConfigDataManage.h"
#include "dquCbtcConfigData.h"
#include "dquEmapInit.h"
#include "AxisSort_api.h"
#include "SystemParameterManage.h"
#include "LinkConfigDataManage.h"
#include "TrainOnAcManage.h"
#include "dquCIInterFace.h"
#include "CiSystemDefine.h"
#include <stdarg.h>

UINT16 OutEnvelopeStrLen = 0U;  /*需要打印的包络数据长度*/
UINT8 OutEnvelopeStr[MAX_ENVELOPE_LOG_NUM] = { 0U };  /*需要打印的包络数据*/

/**
* @brief 打印包络信息 
* @param[in] const EnvelopeStruct* PEnvelpe 包络指针
* @return 无
* @note 调用日志打印库函数进行日志打印
*/
void elm_PrintfEnvelope(const EnvelopeStruct* PEnvelpe)
{
UINT8 cycle = 0U;
UINT8 rrmRequst = 0U;
UINT8 curAct = 0U;
UINT16 nextSta = 0U;
UINT8 runDir = 0U;
UINT8 lastAct = 0U;
UINT8 rrmReply = 0U;
UINT8 rrmReason = 0U;

if (NULL != PEnvelpe)
{
	ShortToChar(PEnvelpe->id, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 2U;
	OutEnvelopeStr[OutEnvelopeStrLen++] = PEnvelpe->envelopeType;
	ShortToChar(PEnvelpe->headTrainID, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 2U;
	ShortToChar(PEnvelpe->tailTrainID, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 2U;

	OutEnvelopeStr[OutEnvelopeStrLen++] = PEnvelpe->trianCnt;

	for (cycle = 0u; cycle < PEnvelpe->trianCnt; cycle++)
	{
		ShortToChar(PEnvelpe->trainID[cycle], &OutEnvelopeStr[OutEnvelopeStrLen]);
		OutEnvelopeStrLen += 2U;
	}

	for (cycle = 0u; cycle < PEnvelpe->trianCnt; cycle++)
	{
		rrmRequst = GetTrainRrmRqst(PEnvelpe->trainID[cycle]);
		curAct = GetTrainActive(PEnvelpe->trainID[cycle]);
		nextSta = GetTrainAtsLgcStation(PEnvelpe->trainID[cycle]);
		runDir = GetTrainDir(PEnvelpe->trainID[cycle]);
		lastAct = PEnvelpe->ACTPort[cycle];
		rrmReply = GetTrainRrmState(PEnvelpe->trainID[cycle]);
		rrmReason = GetTrainRrmReson(PEnvelpe->trainID[cycle]);

		ShortToChar(PEnvelpe->trainID[cycle], &OutEnvelopeStr[OutEnvelopeStrLen]);
		OutEnvelopeStrLen += 2U;

		OutEnvelopeStr[OutEnvelopeStrLen++] = rrmRequst;
		OutEnvelopeStr[OutEnvelopeStrLen++] = curAct;
		ShortToChar(nextSta, &OutEnvelopeStr[OutEnvelopeStrLen]);
		OutEnvelopeStrLen += 2U;
		OutEnvelopeStr[OutEnvelopeStrLen++] = runDir;
		OutEnvelopeStr[OutEnvelopeStrLen++] = lastAct;
		OutEnvelopeStr[OutEnvelopeStrLen++] = rrmReply;
		OutEnvelopeStr[OutEnvelopeStrLen++] = rrmReason;
	}
	ShortToChar(PEnvelpe->startPos.Lnk, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 2U;
	LongToChar(PEnvelpe->startPos.Off, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 4U;
	OutEnvelopeStr[OutEnvelopeStrLen++] = PEnvelpe->startPos.Dir;

	ShortToChar(PEnvelpe->endPos.Lnk, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 2U;
	LongToChar(PEnvelpe->endPos.Off, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 4U;
	OutEnvelopeStr[OutEnvelopeStrLen++] = PEnvelpe->endPos.Dir;

	OutEnvelopeStr[OutEnvelopeStrLen++] = PEnvelpe->ACCnt;
	for (cycle = 0u; cycle < PEnvelpe->ACCnt; cycle++)
	{
		ShortToChar(PEnvelpe->ACID[cycle], &OutEnvelopeStr[OutEnvelopeStrLen]);
		OutEnvelopeStrLen += 2U;
	}

	LongToChar(PEnvelpe->dwUCTToUKTStartCycNum, &OutEnvelopeStr[OutEnvelopeStrLen]);
	OutEnvelopeStrLen += 4U;
}
else
{
	/*不处理*/
}

#if (kPLATFORM!=kVXWORKS)
if (NULL != PEnvelpe)
{
	debug_infor_printf((const)"Envelop id:%d,type:%d,H:%d,T:%d,", PEnvelpe->id, PEnvelpe->envelopeType, PEnvelpe->headTrainID, PEnvelpe->tailTrainID);
	debug_infor_printf((const)"Tcnt:%d,TId[", PEnvelpe->trianCnt);

	for (cycle = 0u; cycle < PEnvelpe->trianCnt; cycle++)
	{
		debug_infor_printf((const)"%d,", PEnvelpe->trainID[cycle]);
	}

	debug_infor_printf((const)"],rrm[");
	for (cycle = 0u; cycle < PEnvelpe->trianCnt; cycle++)
	{
		rrmRequst = GetTrainRrmRqst(PEnvelpe->trainID[cycle]);
		curAct = GetTrainActive(PEnvelpe->trainID[cycle]);
		nextSta = GetTrainAtsLgcStation(PEnvelpe->trainID[cycle]);
		runDir = GetTrainDir(PEnvelpe->trainID[cycle]);
		lastAct = PEnvelpe->ACTPort[cycle];
		rrmReply = GetTrainRrmState(PEnvelpe->trainID[cycle]);
		rrmReason = GetTrainRrmReson(PEnvelpe->trainID[cycle]);

		debug_infor_printf((const)"%d-%02x-%d-%d-%02x-%d-%02x-%d,", PEnvelpe->trainID[cycle], rrmRequst, curAct, nextSta, runDir, lastAct, rrmReply, rrmReason);
	}

	debug_infor_printf((const)"],S:%d-%d-%d,E:%d-%d-%d,ACCnt:%d,ACID[", PEnvelpe->startPos.Lnk, PEnvelpe->startPos.Off, PEnvelpe->startPos.Dir, \
		PEnvelpe->endPos.Lnk, PEnvelpe->endPos.Off, PEnvelpe->endPos.Dir, PEnvelpe->ACCnt);

	for (cycle = 0u; cycle < PEnvelpe->ACCnt; cycle++)
	{
		debug_infor_printf((const)"%d,", PEnvelpe->ACID[cycle]);
	}
	debug_infor_printf((const)"]\n");
}
#endif
}


/**
* @brief 打印Debug信息
* @param[in] UINT8 level 日志级别
* @param[in] const char *fmt 打印信息
* @return 无
* @note 通过调用外部接口，实现本模块的打印
*/
void elm_PrintDebugInfo(UINT8 level,const char *fmt, ...)
{
va_list para;
CHAR tmpPrintBuf[ELM_PRINT_LEN] = {'\0'};

if (ELM_LOG_LEVEL >= level)
{
	va_start(para,fmt);
	(void)vsnprintf(tmpPrintBuf, ELM_PRINT_LEN, fmt, para);
	va_end(para);

	debug_infor_printf((const)"%s",tmpPrintBuf);
}
else
{
	/** 日志级别不够*/
}	
}


/**
* @brief 通过列车ID准备列车的安全包络信息
* @param[in] UINT16 trainID 列车ID
* @param[out] INOUT TrainSafeLocStruct* pTrainSafeLoc 列车安全包络
* @return CI_SUCCESS 需要操作的内存区正确，返回成功
*         CI_ERROR   需要操作的内存区错误，返回失败
* @note 
*/
UINT8 elm_PrepareTrainSafeLoc(UINT16 trainID,INOUT ELM_TrainSafeLocStruct* pTrainSafeLoc)
{
UINT8 chRtnVal = CI_ERROR;
UINT16 wTrainID = (UINT16)(0x1400u + (trainID & 0x00ffu));

if (NULL != pTrainSafeLoc)
{
	pTrainSafeLoc->startPos.Lnk = GetTrainSafeTailLink(wTrainID);
	pTrainSafeLoc->startPos.Off = GetTrainSafeTailOffset(wTrainID);
	pTrainSafeLoc->startPos.Dir = GetTrainSafeTailDir(wTrainID);
	pTrainSafeLoc->endPos.Lnk = GetTrainSafeHeadLink(wTrainID);
	pTrainSafeLoc->endPos.Off = GetTrainSafeHeadOffset(wTrainID);
	pTrainSafeLoc->endPos.Dir = GetTrainSafeHeadDir(wTrainID);
	chRtnVal = CI_SUCCESS;
}
return chRtnVal;
}



/**
* @brief 获取本OC范围有共管区内计轴区段的数组索引
* @param[out] OUT UINT16** pACIdBuff 计轴区段ID数缓存
* @return 0 查询错误
        1~AXIS_SECTION_SUM_MAX 查询正确
* @note 由于OC支持计轴区段ID和索引的映射关系，故直接获取即可
*/
UINT16 elm_PrepareACBuffIndexs(OUT const UINT16** pACIdBuff)
{
/*- 局部变量定义 */
UINT16 ret = 0u;      /*函数返回值*/
UINT16 tempACCnt = 0u;
UINT32 errorCode = 0u;

/** 入口参数校验 */
ASSERT_RET_VALUE(NULL == pACIdBuff,ret,0x80000000u);
	
/** 获取计轴区段数组索引 */
tempACCnt = GetLocalCiAxisSectionIdBuf(pACIdBuff);

/** 判断是否查询成功 */
if ((0u == tempACCnt) || (AXIS_SECTION_SUM_MAX <= tempACCnt))
{
	/** 设置错误码 */
	(*pACIdBuff) = NULL;
	errorCode = 0x40000000u;
}
else
{
	/** 处理正常 */
	ret = tempACCnt;
}

/** 设置返回值 */
ASSERT_SETRET(0u == errorCode,ret,tempACCnt,0u);

/** 函数返回 */
return ret;
}


/**
* @brief 通过计轴区段的数组索引获取计轴区段ID
* @param[in] UINT16 ACBuffIndex 计轴区段缓存索引
* @return 计轴区段ID
* @note 
*/
UINT16 elm_PrepareACID(UINT16 ACBuffIndex)
{
UINT16 wRtnVal = UINT16_MAX;
wRtnVal = GetAxisSecId(ACBuffIndex);
return wRtnVal;
}

/**
* @brief 通过计轴区段ID获取计轴区段的数组索引
* @param[in] UINT16 ACId 计轴区段ID
* @return 计轴区段缓存索引
* @note 无
*/
UINT16 elm_PrepareACIndex(UINT16 ACId)
{
return GetLocalCiAxisSectionIndex(ACId);
}


/**
* @brief 通过计轴ID获取计轴状态
* @param[in] UINT16 ACID 计轴区段ID
* @return ELM_AC_OCC 计轴占用
		ELM_AC_FREE 计轴空闲
* @note 集成 bug 20220420 wqm 物理区段占用，计轴区段上道岔数量不合法，计轴区段占用
*/
UINT8 elm_PrepareACStatus(UINT16 ACID)
{
	UINT8 ret = ELM_AC_OCC;
	UINT8 chRtnVal = AXIS_SECTION_OCCUPY_YES;

	chRtnVal = GetAxisOccupyState(ACID);
	ASSERT_SETRET(AXIS_SECTION_OCCUPY_NO == chRtnVal, ret, ELM_AC_FREE, ELM_AC_OCC);
	return ret;
}

/**
* @brief 通过计轴ID查询当属于岔区不连通时，所处物理区段占用情况
* @param[in] UINT16 ACID 计轴区段ID
* @return SECTION_OCCUPY_YES 物理区段占用
		SECTION_OCCUPY_NO 物理区段空闲
*/
UINT8 elm_PrepareACofSwichPhyStatus(UINT16 ACID)
{
	UINT8 ret = SECTION_OCCUPY_YES;
	UINT8 retValIsSwitch = CI_ERROR;		/*计轴区段是否在岔区标志*/
	UINT8 retSwitchCheckSuccess = CI_ERROR;		/*岔区计轴区段道岔是否在期望位置*/

	retValIsSwitch = elm_PrepareACIsSwitchZone(ACID);

	if (CI_SUCCESS == retValIsSwitch)
	{
		retSwitchCheckSuccess = elm_PrepareCheckACofSwichPos(ACID);
		if (CI_SUCCESS == retSwitchCheckSuccess)
		{
			ret = SECTION_OCCUPY_NO;	/*道岔在期望位置，计轴连通，直接返回空闲，无需考虑物理区段*/
		}
		else
		{
			ret = elm_PrepareACRelPhyStatus(ACID);/*道岔不在期望位置，计轴不连通，则需要返回对应计轴区段所处物理区段的占用状态*/
		}
	}
	else
	{
		ret = SECTION_OCCUPY_NO;	/*当计轴区段不在道岔区段时返回无占压*/
	}
	return ret;
}

/**
* @brief 通过计轴区段ID查找计轴区段位置
* @param[in] UINT16 ACID 计轴区段ID
* @param[in] UINT8 chDir 起点指向终点的方向
* @param[out] ELM_AxisLocStruct* pACLoc 计轴区段位置
* @return CI_SUCCESS 查询正确，返回成功
*         CI_ERROR   查询错误，返回失败
* @note 
*/
UINT8 elm_PrepareACLoc(UINT16 ACID, UINT8 chDir, ELM_AxisLocStruct* pACLoc)
{
/*- 局部变量定义 */
UINT8 ret = CI_ERROR;
struct_PathPoint strStart = { 0u };
struct_PathPoint strEnd = { 0u };

UINT32 errorCode = 0u;
UINT16* pLinkIDBuf = NULL;
UINT16 pLinkSum = 0U;


/*- 获取计轴区段包含的Link信息*/
pLinkSum = GetAxisLinkSum(ACID);
pLinkIDBuf = GetAxisLinkIdBuf(ACID);
/** 入口参数校验 */
ASSERT_RET_VALUE(NULL == pACLoc,ret,0x80000000u);
ASSERT_RET_VALUE((ELM_DIR_SAME != chDir) && (ELM_DIR_CONVERT != chDir),ret,0x40000000u);
ASSERT_RET_VALUE(0U == pLinkSum, ret, 0x08000000u);
ASSERT_RET_VALUE(NULL == pLinkIDBuf, ret, 0x04000000u);

/*- 获取起终点位置*/
strStart.wLinkId = pLinkIDBuf[0];
strStart.dwOffset = 0u;
strEnd.wLinkId = pLinkIDBuf[pLinkSum-1U];
strEnd.dwOffset = GetLinkLengthById(strEnd.wLinkId);

	
/** 判断位置是否正确 */
if (((0u != strStart.wLinkId) && (UINT16_MAX != strStart.wLinkId)) || 
	((0u != strEnd.wLinkId) && (UINT16_MAX != strEnd.wLinkId)))
{
	/*- 位置查询成功，设置位置信息--假定计轴区段内无方向变化点*/
	if (ELM_DIR_SAME == chDir)
	{
		pACLoc->dir = chDir;
		pACLoc->startPos.Lnk = strStart.wLinkId;
		pACLoc->startPos.Off = strStart.dwOffset;
		pACLoc->startPos.Dir = chDir;
		pACLoc->endPos.Lnk = strEnd.wLinkId;
		pACLoc->endPos.Off = strEnd.dwOffset;
		pACLoc->endPos.Dir = chDir;
	}
	else
	{
		pACLoc->dir = chDir;
		pACLoc->endPos.Lnk = strStart.wLinkId;
		pACLoc->endPos.Off = strStart.dwOffset;
		pACLoc->endPos.Dir = chDir;
		pACLoc->startPos.Lnk = strEnd.wLinkId;
		pACLoc->startPos.Off = strEnd.dwOffset;
		pACLoc->startPos.Dir = chDir;
	}

	ret = CI_SUCCESS;
}
else
{
	/** 数据错误 */
	ASSER_ERROR(CI_ERROR == ret,errorCode,0x40000000u);
}
	
/** 设置函数返回值 */
ASSERT_SETRET(0u == errorCode,ret,CI_SUCCESS,CI_ERROR);

/** 函数返回 */
return ret;
}

/**
* @brief 通过计轴区段ID查找列车前方对应计轴器：
* @param[in] UINT16 ACID 计轴区段ID
* @param[in] UINT8 chDir 起点指向终点的方向
* @param[out] UINT16* AxisId 前方查询计轴器Id
* @return CI_SUCCESS 查询正确，返回成功
*         CI_ERROR   查询错误，返回失败
* Create: fan 2024 3.2
*/
UINT8 elm_PrepareACHeadAxisId(UINT16 ACID, UINT8 chDir, UINT16* AxisId)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT16 tmpAxis = 0U;
	UINT32 errorCode = 0u;

	/*入口参数校验*/
	if (((ELM_DIR_SAME == chDir) || (ELM_DIR_CONVERT == chDir))
		&&(NULL != AxisId))
	{
		if (ELM_DIR_SAME == chDir)
		{
			tmpAxis = GetAxisTmnlAxisId(ACID);
		}
		else
		{
			tmpAxis = GetAxisOrgnAxisId(ACID);
		}
		if (0U != tmpAxis)
		{
			*AxisId = tmpAxis;
			ret = CI_SUCCESS;
		}
		else
		{
			ret = CI_ERROR;
		}
	}
	else
	{
		/** 数据错误 */
		ASSER_ERROR(CI_ERROR == ret, errorCode, 0x40000000u);
	}
	return ret;
}

/**
* @brief 通过计轴区段ID查找列车后方对应计轴器：
* @param[in] UINT16 ACID 计轴区段ID
* @param[in] UINT8 chDir 起点指向终点的方向
* @param[out] UINT16* AxisId 后方查询计轴器Id
* @return CI_SUCCESS 查询正确，返回成功
*         CI_ERROR   查询错误，返回失败
* Create: fan 2024 3.2
*/
UINT8 elm_PrepareACTailAxisId(UINT16 ACID, UINT8 chDir, UINT16* AxisId)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT16 tmpAxis = 0U;
	UINT32 errorCode = 0u;

	/*入口参数校验*/
	if (((ELM_DIR_SAME == chDir) || (ELM_DIR_CONVERT == chDir))
		&& (NULL != AxisId))
	{
		if (ELM_DIR_SAME == chDir)
		{
			tmpAxis = GetAxisOrgnAxisId(ACID);			
		}
		else
		{
			tmpAxis = GetAxisTmnlAxisId(ACID);
		}
		if (0U != tmpAxis)
		{
			*AxisId = tmpAxis;
			ret = CI_SUCCESS;
		}
		else
		{
			ret = CI_ERROR;
		}
	}
	else
	{
		/** 数据错误 */
		ASSER_ERROR(CI_ERROR == ret, errorCode, 0x40000000u);
	}
	return ret;
}


/**
* @brief 通过计轴区段ID和查询方向查询计轴包含的link
* @param[in] UINT16 ACID 计轴ID
* @param[out] UINT16 linkID[] 计轴包含的link
* @return  0 非法
        非0 包含的link数量
* @note link返回时按照查询方向顺序返回
*/
UINT8 elm_PrepareACrelLink(UINT16 ACID,UINT8 dir, INOUT UINT16 linkID[])
{
UINT8 chRtnVal = CI_ERROR;
UINT8 chLinkNum = 0u;
UINT16 * pLinkIdBuf = NULL;
UINT8 chIndex = 0u;

chLinkNum = GetAxisLinkSum(ACID);
pLinkIdBuf = GetAxisLinkIdBuf(ACID);
if(((EMAP_CONVER_DIR != dir) && (EMAP_SAME_DIR != dir)) || (0u == chLinkNum) 
	|| (NULL == linkID))
{
	;
}
else
{
	for (chIndex = 0u; chIndex < chLinkNum; chIndex++)
	{
		if (EMAP_SAME_DIR == dir)
		{
			linkID[chIndex] = pLinkIdBuf[chIndex];
		}
		else
		{
			linkID[chLinkNum - 1u - chIndex] = pLinkIdBuf[chIndex];
		}
	}
	chRtnVal = CI_SUCCESS;
}

return chRtnVal;
}

/**
* @brief 根据两点查询两点之间的link区段
* @param[in] LOD_STRU pointA 位置点A
* @param[in] LOD_STRU pointB 位置点B
* @param[out] UINT16 linkID[] 两点之间包含的link
* @return 两点之间的link数量
* @note pointA位置点的方向为指向pointB的方向
*/
UINT16 elm_PrepareLinkBtwPoints(LOD_STRU pointA,LOD_STRU pointB,INOUT UINT16 linkID[])
{
UINT16 chLinkNum = 0u;
UINT8 chDir = 0u;
UINT32 dwLen = UINT32_MAX;
if(NULL == linkID)
{
	;
}
else
{
	dwLen = dsuLenByPoint(&pointA, &pointB, &chLinkNum, linkID, &chDir);
	if (UINT32_MAX != dwLen)
	{
		;
	}
	else
	{
		chLinkNum = 0u;
	}
}
return chLinkNum;
}



/**
* @brief 根据两点查询两点之间的计轴区段
* @param[in] LOD_STRU pointA 位置点A
* @param[in] LOD_STRU pointB 位置点B
* @param[out] UINT16 ACID[] 两点之间包含的计轴区段
* @return 两点之间的计轴数量
* @note pointA位置点的方向为指向pointB的方向
*/
UINT8 elm_PrepareACBtwPoints(LOD_STRU pointA,LOD_STRU pointB,INOUT UINT16 ACID[SECTION_IN_ENVELOPE_SUM_MAX])
{
UINT16 wLinkNum = 0u;
UINT8 chDir = 0u;
UINT32 dwLen = UINT32_MAX;
UINT16 wAcNum = 0u;
UINT8 chFunRtn = CI_ERROR;
UINT16 szLink[LINK_SUM_MAX] = {0u};
	

if (NULL == ACID)
{
	;/* 入参或数据错误 */
}
else
{
	/* 获取link序列 */
	dwLen = dsuLenByPoint(&pointA, &pointB, &wLinkNum, szLink, &chDir);
	if (UINT32_MAX != dwLen)
	{
		;
	}
	else
	{
		wLinkNum = 0u;
	}

	if (0u != wLinkNum)
	{/* 根据link序列获取计轴区段序列 */
		chFunRtn = GetAxisSeqFromLinkSeq(szLink, wLinkNum, ACID, &wAcNum,SECTION_IN_ENVELOPE_SUM_MAX);
		if ((CI_ERROR == chFunRtn )|| (SECTION_IN_ENVELOPE_SUM_MAX < wAcNum))
		{
			wAcNum = 0u;
		}
		else
		{
			; /*无操作*/
		}
	}
	else
	{
	}
}

/** 两点之间的计轴不超过SECTION_IN_ENVELOPE_SUM_MAX，故进行类型强转 */
return (UINT8)wAcNum;
}


/**
* @brief 获取当前OC所有的通信车列车ID
* @param[out] UINT16 trainID[TRAIN_SUM_MAX_IN_OC] 列车ID缓存
* @return OC范围内通信列车数量
* @note 集成 bug 20220420 wqm 更正注释
*/
UINT8 elm_PrepareCommTrainID(INOUT UINT16 trainID[TRAIN_SUM_MAX_IN_OC])
{
/*- 局部变量定义 */
UINT8 chTrainNum = 0u;
UINT8 chIndex = 0u;
UINT16 wTrainId = 0u;
UINT8 chTransmitState = 0u;
UINT32 errorCode = 0u;

/** 入口参数校验*/
if (NULL == trainID)
{
	/** 入口参数错误 */
	ASSER_ERROR(NULL == trainID,errorCode,0x80000000u);
}
else
{
	/** 获取通信列车 */
	for (chIndex = 0u; chIndex < TRAIN_SUM_MAX; chIndex++)

	{
		/** 获取列车类型 + ID*/
		wTrainId = GetTrainId(chIndex);

		/** 获取列车通信状态*/
		chTransmitState = elm_PrepareTrainCommStatus(wTrainId);

		/** 判断通信状态是否良好*/
		if ((ELM_COM_STATUS_OK == chTransmitState) && (chTrainNum < TRAIN_SUM_MAX_IN_OC))
		{
			trainID[chTrainNum++] = (UINT16)(wTrainId & 0x00ffu);
		}
		else
		{
			/** 非通信车，不处理 */
		}
	}
}

/** 函数返回 */
return chTrainNum;

}


/**
* @brief 获取列车的通信状态
* @param[in] UINT16 trainid
* @param[out] 无
* @return ELM_COM_STATUS_OK 通信正常
*         ELM_COM_STATUS_ERROR 通信异常
* @note 无
*/
UINT8 elm_PrepareTrainCommStatus(IN UINT16 trainID)
{
UINT8 ret = ELM_COM_STATUS_ERROR;
UINT8 comStatus = TRAIN_COMM_STATE_BAD;
UINT8 chSleepState = TRAIN_SLEEP_NO;
UINT8 trainPosValid = CI_ERROR;

/** 获取列车通信状态*/
comStatus = GetTrainTransitmitStat(trainID);

/** 获取列车休眠状态*/
chSleepState = elm_PrepareTrainSleepStatus(trainID);

/** 获取列车位置是否有效 */
trainPosValid = IsTrainPosValid(trainID);

if (((TRAIN_COMM_STATE_GOOD == comStatus) && (CI_SUCCESS == trainPosValid)) ||
		((TRAIN_SLEEP_YES == chSleepState) && (TRAIN_COMM_STATE_BAD == comStatus)))
{
	ret = ELM_COM_STATUS_OK;
}
else
{
	/** 通信异常 */
}

return ret;
}

/**
* @brief 获取通信正常的列车位置是否有效
* @param[in] UINT16 trainid
* @param[out] 无
* @return CI_SUCCESS 位置有效
*         CI_ERROR   位置无效
* @note 无
*/
UINT8 elm_PrepareTrainPosValid(IN UINT16 trainID)
{
return IsTrainPosValid(trainID);
}

/**
* @brief 获取两点的位置关系
* @param[in] LOD_STRU pointA 位置A
* @param[in] UINT8 dirAtoB 位置A指向位置B
* @param[in] LOD_STRU pointB 位置B
* @return LOC_BEFORE 位置B在位置A前
        LOC_SAME 位置A与位置B重合
        LOC_AFTER 位置A在位置B后
		其他 非法
* @note 无
*/
UINT8 elm_PrepareRelationBtwPoint(LOD_STRU pointA,UINT8 dirAtoB, LOD_STRU pointB)
{
UINT16 wLinkNum = 0u;
UINT8 chDir = 0u;
UINT32 dwLen = UINT32_MAX;
UINT16 szLink[LINK_SUM_MAX] = { 0u };
UINT8 chRtnVal = 0u;

dwLen = dsuLenByPoint(&pointA, &pointB, &wLinkNum, szLink, &chDir);
if (UINT32_MAX != dwLen)
{
	if (0u == dwLen)
	{
		chRtnVal = LOC_SAME;
	}
	else if (chDir == dirAtoB)
	{
		chRtnVal = LOC_BEFORE;
	}
	else
	{
		chRtnVal = LOC_AFTER;
	}
}
else
{
	;
}

return chRtnVal;
}


/**
* @brief 查询计轴前/后方计轴
* @param[in] UINT16 ACID 基准计轴ID
* @param[in] UINT8 dir 查询方向
* @param[out] UINT16 arACID[AC_MAXCNT_IN_SWITCH] 相邻计轴ID
* param[out] UINT8* DirectionPointFlag  是否有方向变化点 DIRECTIONPOINT_FLAG_VALID
* @return UINT8_MAX 查询失败
        0~AC_MAXCNT_IN_SWITCH  查询成功
* @note 无
*/
UINT8 elm_PrepareAdjacentAC(UINT16 ACID, UINT8 dir, INOUT UINT16 arACID[AC_MAXCNT_IN_SWITCH], UINT8* DirectionPointFlag)
{
/*- 局部变量定义 */
UINT8 ret = (UINT8)UINT8_MAX;
UINT8 funRtn = CI_ERROR;
UINT8 tmpLinkcnt = 0u;
const UINT16 *pLinkIdBuf = NULL;
UINT16 wBaseLink = 0u;
UINT16 tmpACCnt = 0u;
UINT16 wNextLink = 0u;
UINT16 wSwitchId = 0u;
UINT16 tmpACid[AC_MAXCNT_IN_SWITCH] = {0u};
UINT8 cDirectionPointFlag = 0U;			/*是否具有方向变化点标志*/

/*- 获取计轴包含的link信息 */
tmpLinkcnt = GetAxisLinkSum(ACID);
pLinkIdBuf = GetAxisLinkIdBuf(ACID);

/** 入口参数判断 */
if ((0u == tmpLinkcnt) || (NULL == arACID)
	|| ((EMAP_CONVER_DIR != dir) && (EMAP_SAME_DIR != dir))||(NULL == DirectionPointFlag))
{
	/** 入口参数错误 */
}
else
{
	/** 清除输出数组*/
	(void)CommonMemSet(arACID, (UINT32)(sizeof(UINT16)*AC_MAXCNT_IN_SWITCH),0u, (UINT32)(sizeof(UINT16)*AC_MAXCNT_IN_SWITCH));

	/* 获取计轴区段沿输入方向的最后一个link */
	if (EMAP_SAME_DIR == dir)
	{
		wBaseLink = pLinkIdBuf[tmpLinkcnt - 1u];
	}
	else
	{
		wBaseLink = pLinkIdBuf[0];
	}

	/* 获取计轴区段下一link所属计轴区段 */
	wNextLink = FindAdjacentLinkIDSafe(wBaseLink, dir, &wSwitchId, &cDirectionPointFlag);

	*DirectionPointFlag = cDirectionPointFlag;

	if (0u == wNextLink)
	{
		/** 线路尽头，查询成功 */
		ret = 0u;
	}
	else if (UINT16_MAX == wNextLink)
	{
		/** 数据错误，返回失败 */
	}
	else
	{
		/** 查询link序列中包含的计轴区段 */
		funRtn = GetAxisSeqFromLinkSeq(&wNextLink,1u,tmpACid,&tmpACCnt,AC_MAXCNT_IN_SWITCH);

		/** 判断查询是否成功 */
		if ((CI_SUCCESS == funRtn) && (0u != tmpACCnt) && (tmpACCnt <= AC_MAXCNT_IN_SWITCH))
		{
			(void)CommonMemCpy(arACID, (UINT32)(sizeof(UINT16) * AC_MAXCNT_IN_SWITCH),tmpACid, (UINT32)(sizeof(UINT16) * tmpACCnt));
			ret = (UINT8)tmpACCnt;
		}
		else
		{
			/** 查询失败*/
		}
	}
}

return ret;
}


/**
* @brief 合并UINT16数组
* @param[in] UINT16 dstBuffSize 目的缓冲区大小
* @param[in] UINT16 startIndex 目的缓冲区拷贝起始地址
* @param[in] const UINT16 srcArray[] 源缓冲区地址
* @param[in] UINT16 srcBuffSize 源缓冲区大小
* @param[in] UINT16 mergeSize 合并大小
* @param[out] UINT16 dstArray[] 目的缓冲区
* @return 目的合并后的索引地址
* @note 如果合并失败，返回目的缓冲区大小
*/
UINT16 elm_PrepareMergeUINT16Array(INOUT UINT16 dstArray[], UINT16 dstBuffSize, UINT16 startIndex, IN const UINT16 srcArray[], UINT16 srcBuffSize,UINT16 mergeSize)
{
/*- 局部变量定义*/
UINT16 wRtnVal = (UINT16)UINT16_MAX;
UINT16 wMergeIndex = startIndex;
UINT16 wIndex = 0u;

/** 入口参数校验*/
if ((NULL == dstArray) || (NULL == srcArray) || ((UINT16_MAX - startIndex) < mergeSize) ||
	(srcBuffSize < mergeSize) || (dstBuffSize < startIndex + mergeSize))
{
	/** 入口参数错误 */
}
else
{
	/*- 合并数组 */
	for (wIndex = 0u; wIndex < mergeSize; wIndex++)
	{
		dstArray[wMergeIndex++] = srcArray[wIndex];
	}
	wRtnVal = wMergeIndex;
}

/** 函数返回*/
return wRtnVal;
}


/**
* @brief 比较两个包络的前后关系
* @param[in] const EnvelopeStruct pEnvelopeA 包络A
* @param[in] const LOD_STRU* strPointA 基准包络起点
* @param[in] const EnvelopeStruct* pEnvelopeB 包络B
* @return 0x01 包络A在包络B前
        0x02 包络B在包络A前
		0x03 包络A包含与包络B，包括如下关系：(()  )、(    ()) 和（  ()   ） 
		0x04 包络B包含与包络A，包括如下关系：(()  )、(    ()) 和（  ()   ） 
		0x00 无法比较位置关系
* @note 无
*/
UINT8 elm_PrepareRelationBtwEnvelope(IN const EnvelopeStruct* pEnvelopeA, const LOD_STRU strPointBase,IN const EnvelopeStruct* pEnvelopeB)
{
UINT8 ret = 0u;
UINT8 funRtn = 0u;
UINT8 cABSameDirFlag = 0U;

funRtn = CheckLinkValid(strPointBase.Lnk, strPointBase.Off);
if ((NULL == pEnvelopeA) || (NULL == pEnvelopeB) || (CI_SUCCESS != funRtn))
{
	/** 入口参数错误*/
}
else 
{
	funRtn = as_CalcEnvelopeOrder(pEnvelopeA,pEnvelopeB);

	if ((0x01u == funRtn) || (0x02u == funRtn))
	{
		cABSameDirFlag = IsPointABSameDir(pEnvelopeA->startPos, strPointBase);  /*判断两点方向是否同向*/
		if(FLAG_SET == cABSameDirFlag)
		{
			ret = (0x01u == funRtn) ? 0x02u : 0x01u;
		}
		else if(FLAG_UNSET == cABSameDirFlag)
		{
			ret = funRtn;
		}
		else
		{
			ret = 0u;
		}
	}
	else
	{
		ret = funRtn;
	}
}
return ret;
}


/**
* @brief 判断数值是否存在UINT16数值中 
* @param[in] UINT16 targetValue 待查询的值
* @param[in] const UINT16 arValue[] 冲突范围
* @param[in] UINT16 buffsize 冲突范围大小
* @return CI_SUCCESS 指定值在冲突范围内
*         CI_ERROR   指定值不在冲突范围内
* @note 无
*/
UINT8 elm_PrepareInUINT16Array(UINT16 targetValue,const UINT16 arValue[],UINT16 buffsize)
{
/*- 局部变量定义 */
UINT8 cRetVal = CI_ERROR;
UINT16 cycle = 0u;

/** 入口参数校验 */
if (NULL == arValue)
{
	/** 入口参数错误 */
}
else
{
	/*- 目标值是否在指定范围内 */
	for (cycle = 0u; cycle < buffsize; cycle++)
	{
		if (targetValue == arValue[cycle])
		{
			cRetVal = CI_SUCCESS;
			break;
		}
	}
}

/** 函数返回*/
return cRetVal;
}

/**
* @brief 通过两点获取两点之间的距离
* @param[in] LOD_STRU pointA 位置A
* @param[in] LOD_STRU pointB 位置B
* @return 两点之间的距离（cm）
* @note  pointA为起点 pointB为终点
*/
UINT32 elm_PrepareDistanceBtwPoints(LOD_STRU pointA, LOD_STRU pointB)
{
	UINT32 dwLen = UINT32_MAX;
	struct_PathPoint strPointA = { 0u };
	struct_PathPoint strPointB = { 0u };
	UINT8 chDir = 0u;
	strPointA.wLinkId = pointA.Lnk;
	strPointA.dwOffset = pointA.Off;
	strPointB.wLinkId = pointB.Lnk;
	strPointB.dwOffset = pointB.Off;
	dwLen = DsuAPointToBPoint(&strPointA, &strPointB, &chDir);
	if ((EMAP_CONVER_DIR != chDir) && (EMAP_SAME_DIR != chDir))
	{
		dwLen = UINT32_MAX;
	}
	else
	{
		;
	}
	return dwLen;
}

/**
* @brief 通过列车ID获取列车车长
* @param[in] 
* @param[out]
* @return 列车车长（cm）
* @note 1、如果查询成功，返回列车车长，否则返回线路上最短车长
*/
UINT32 elm_PrepareTrainLength(UINT16 trainid)
{
	CBTC_TRAIN_INFO_STRU strTrainInfo = { 0u };
	UINT8 chTrainType = 0u;
	UINT8 chFunRtn = CI_ERROR;
	UINT32 dwRtnVal = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));

	/*获取列车类型*/
	chFunRtn = dquGetTrainType(wTrainID, &chTrainType);
	if (CI_SUCCESS == chFunRtn)
	{
	/*获取列车性能参数*/
	(void)dquGetCbtcTrainInfo(chTrainType, &strTrainInfo);
	dwRtnVal = (UINT32)strTrainInfo.TrainLength;
	}
	else
	{
		dwRtnVal = GetShortestTrainLen();
	}
	return dwRtnVal;
}

/** 
* @brief 获取列车运行方向
* @param[in] UINT16 trainid 列车ID
* @param[out] 无
* @return ELM_DIR_SAME 处理成功
*         ELM_DIR_CONVERT 处理失败
        其他，非法
* @note 
*/
UINT8 elm_PrepareTrainDir(UINT16 trainid)
{
	UINT8 ret = 0u;
	UINT8 chDir = 0u;
	chDir = GetTrainDir(trainid);

	if ((ELM_DIR_SAME == chDir) || (ELM_DIR_CONVERT == chDir))
	{
		ret = chDir;
	}
	else
	{
		/** 方向非法 */
	}

	return ret;
}

/**
* @brief 查询列车最小安全前前方计轴
* @param[in] UINT16 trainid 列车ID
* @param[out] UINT16 acID[AC_MAXCNT_IN_SWITCH] 计轴数量
* @return AC_MAXCNT_IN_SWITCH 查找失败
		0~AC_MAXCNT_IN_SWITCH 查找成功
* @note
*/
UINT8 elm_PrepareNextAcMinSafeHeadLoc(UINT16 trainid, OUT UINT16 acID[AC_MAXCNT_IN_SWITCH])
{
	UINT16 wAcId = 0u;
	UINT16 wBaseLink = 0u;
	UINT16 wNextLink = 0u;
	UINT8 chDir = 0u;
	UINT8 chNum = 0u;
	UINT8 chFunRtn = CI_ERROR;
	LinkPointDataStru strPoint = { 0u };
	UINT16 wSwitchId = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));
	UINT8 cDirectionPointFlag = 0U;			/*是否具有方向变化点标志*/


	chDir = GetTrainDir_MinHead(wTrainID);
	wBaseLink = GetTrainMinHeadLink(wTrainID);
	chFunRtn = IsLinkIdValid(wBaseLink);
	if (((DIR_SAME != chDir) && (DIR_CONVERT != chDir)) || (CI_ERROR == chFunRtn))
	{/* 入参不合法 */
		chFunRtn = CI_ERROR;
	}
	else
	{
		chFunRtn = GetLinkPointInfo(chDir, wBaseLink, &strPoint);
	}

	if (CI_SUCCESS == chFunRtn)
	{/* 找到计轴区段沿列车走行方向最后link */
		while ((EMAP_POINT_DOT == strPoint.wPointType) && (CI_SUCCESS == chFunRtn))
		{
			/*非计轴点，不考虑方向点*/
			wBaseLink = FindAdjacentLinkIDSafe(wBaseLink, chDir, &wSwitchId, &cDirectionPointFlag);
			chFunRtn = GetLinkPointInfo(chDir, wBaseLink, &strPoint);
		}

	}
	else
	{
		;
	}

	if (CI_SUCCESS == chFunRtn)
	{/* 获取下一link计轴区段 */
		wNextLink = FindAdjacentLinkIDSafe(wBaseLink, chDir, &wSwitchId, &cDirectionPointFlag);

		wAcId = GetLinkBelongAcId(wNextLink);

		acID[chNum++] = wAcId;
	}
	else
	{
		;
	}

	return chNum;
}

/**
* @brief 获取列车最大安全前位置
* @param[in] UINT16 trainid 列车ID
* @param[out] LOD_STRU *pLoc 列车位置
* @return CI_SUCCESS 查询成功
*         CI_ERROR   查询失败
* @note 无
*/
UINT8 elm_PrepareMaxSafeHeadLoc(UINT16 trainid, OUT LOD_STRU *pLoc)
{
	UINT8 chRtn = CI_ERROR;
	UINT16 wLink = 0u;
	UINT32 dwOff = UINT32_MAX;
	UINT8 chDir = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));


	wLink = GetTrainMaxHeadLink(wTrainID);
	dwOff = GetTrainMaxHeadOffset(wTrainID);
	chDir = GetTrainDir_MaxHead(wTrainID);
	chRtn = CheckLinkValid(wLink, dwOff);
	if (CI_SUCCESS == chRtn)
	{
		pLoc->Dir = chDir;
		pLoc->Lnk = wLink;
		pLoc->Off = dwOff;
	}
	else
	{
		;
	}
	return chRtn;
}

/**
* @brief 获取列车最小安全前位置
* @param[in] UINT16 trainid 列车ID
* @param[out] LOD_STRU *pLoc 列车位置
* @return CI_SUCCESS 查询成功
*         CI_ERROR   查询失败
* @note 无
*/
UINT8 elm_PrepareMinSafeHeadLoc(UINT16 trainid, OUT LOD_STRU *pLoc)
{
	UINT8 chRtn = CI_ERROR;
	UINT16 wLink = 0u;
	UINT32 dwOff = UINT32_MAX;
	UINT8 chDir = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));


	wLink = GetTrainMinHeadLink(wTrainID);
	dwOff = GetTrainMinHeadOffset(wTrainID);
	chDir = GetTrainDir_MinHead(wTrainID);
	chRtn = CheckLinkValid(wLink, dwOff);
	if (CI_SUCCESS == chRtn)
	{
		pLoc->Dir = chDir;
		pLoc->Lnk = wLink;
		pLoc->Off = dwOff;
	}
	else
	{
		;
	}
	return chRtn;
}

/**
* @brief 获取列车最大安全前所属计轴
* @param[in] UINT16 trainid 列车ID
* @return 计轴ID
* @note 无
*/
UINT16 elm_PrepareACOfMaxSafeHeadLoc(UINT16 trainid)
{
	UINT16 wMinHeadLink = 0u;
	UINT8 chFunRtn = CI_ERROR;
	UINT16 wRtn = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));

	wMinHeadLink = GetTrainMaxHeadLink(wTrainID);
	chFunRtn = IsLinkIdValid(wMinHeadLink);
	if (CI_SUCCESS == chFunRtn)
	{
		wRtn = GetLinkBelongAcId(wMinHeadLink);
	}
	else
	{
		;
	}

	return wRtn;
}

/**
* @brief 获取列车最小安全前所属计轴
* @param[in] UINT16 trainid 列车ID
* @return 计轴ID
* @note 无
*/
UINT16 elm_PrepareACOfMinSafeHeadLoc(UINT16 trainid)
{
	UINT16 wMinHeadLink = 0u;
	UINT8 chFunRtn = CI_ERROR;
	UINT16 wRtn = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));

	wMinHeadLink = GetTrainMinHeadLink(wTrainID);
	chFunRtn = IsLinkIdValid(wMinHeadLink);
	if (CI_SUCCESS == chFunRtn)
	{
		wRtn = GetLinkBelongAcId(wMinHeadLink);
	}
	else
	{
		;
	}

	return wRtn;
}


/**
* @brief 查询列车最大安全后后方计轴
* @param[in] UINT16 trainid 列车ID
* @param[out] UINT16 acID[AC_MAXCNT_IN_SWITCH] 计轴数量
* @return 查找成功的计轴数量
* @note 集成 bug 20220420 wqm 应获取最大安全后端link ID
*/
UINT8 elm_PrepareNextAcMaxSafeTailLoc(UINT16 trainid, OUT UINT16 acID[AC_MAXCNT_IN_SWITCH])
{
	UINT16 wAcId = 0u;
	UINT16 wBaseLink = 0u;
	UINT16 wNextLink = 0u;
	UINT8 chDir = 0u;
	UINT8 chNum = 0u;
	UINT8 chFunRtn = CI_ERROR;
	LinkPointDataStru strPoint = { 0u };
	UINT16 wSwitchId = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));
	UINT8 cDirectionPointFlag = 0U;			/*是否具有方向变化点标志*/


	chDir = GetTrainDir_MaxTail(wTrainID);
	wBaseLink = GetTrainMaxTailLink(wTrainID); /* 集成 bug 20220420 wqm 应获取最大安全后端link ID*/
	chFunRtn = IsLinkIdValid(wBaseLink);
	if (((DIR_SAME != chDir) && (DIR_CONVERT != chDir)) || (CI_ERROR == chFunRtn))
	{/* 入参非法 */
		chFunRtn = CI_ERROR;		/*当chFunRtn为CI_SUCCESS时，方向非法，防止后面防不到方向，仍然在执行*/
	}
	else
	{
		chDir = (UINT8)(~chDir);
		chFunRtn = GetLinkPointInfo(chDir, wBaseLink, &strPoint);
	}

	if (CI_SUCCESS == chFunRtn)
	{/* 找到计轴区段沿列车运行方向反向的最后link */
		while ((EMAP_POINT_DOT == strPoint.wPointType) && (CI_SUCCESS == chFunRtn))
		{
			/*非计轴点，不考虑方向变化点*/
			wBaseLink = FindAdjacentLinkIDSafe(wBaseLink, chDir, &wSwitchId, &cDirectionPointFlag);
			chFunRtn = GetLinkPointInfo(chDir, wBaseLink, &strPoint);
		}
		 
	}
	else
	{
		;
	}

	if (CI_SUCCESS == chFunRtn)
	{/* 获取下一link所在计轴区段 */
		wNextLink = FindAdjacentLinkIDSafe(wBaseLink, chDir, &wSwitchId, &cDirectionPointFlag);

		wAcId = GetLinkBelongAcId(wNextLink);

		acID[chNum++] = wAcId;
	}
	else
	{
		;
	}

	return chNum;
}


/**
* @brief 获取列车最大安全后位置
* @param[in] UINT16 trainid 列车ID
* @param[out] LOD_STRU *pLoc 列车位置
* @return CI_SUCCESS 查询成功
*         CI_ERROR   查询失败
* @note 无
*/
UINT8 elm_PrepareMaxSafeTailLoc(UINT16 trainid, OUT LOD_STRU *pLoc)
{
	UINT8 chRtn = CI_ERROR;
	UINT16 wLink = 0u;
	UINT32 dwOff = UINT32_MAX;
	UINT8 chDir = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));

	wLink = GetTrainMaxTailLink(wTrainID);
	dwOff = GetTrainMaxTailOffset(wTrainID);
	chDir = GetTrainDir_MaxTail(wTrainID);
	chRtn = CheckLinkValid(wLink, dwOff);
	if (CI_SUCCESS == chRtn)
	{
		pLoc->Dir = chDir;
		pLoc->Lnk = wLink;
		pLoc->Off = dwOff;
	}
	else
	{
		;
	}
	return chRtn;
}

/**
* @brief 获取列车最小安全后位置
* @param[in] UINT16 trainid 列车ID
* @param[out] LOD_STRU *pLoc 列车位置
* @return CI_SUCCESS 查询成功
*         CI_ERROR   查询失败
* @note 无
*/
UINT8 elm_PrepareMinSafeTailLoc(UINT16 trainid, OUT LOD_STRU *pLoc)
{
	UINT8 chRtn = CI_ERROR;
	UINT16 wLink = 0u;
	UINT32 dwOff = UINT32_MAX;
	UINT8 chDir = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));

	wLink = GetTrainMinTailLink(wTrainID);
	dwOff = GetTrainMinTailOffset(wTrainID);
	chDir = GetTrainDir(wTrainID);
	chRtn = CheckLinkValid(wLink, dwOff);
	if (CI_SUCCESS == chRtn)
	{
		pLoc->Dir = chDir;
		pLoc->Lnk = wLink;
		pLoc->Off = dwOff;
	}
	else
	{
		;
	}
	return chRtn;
}

/**
* @brief 获取列车最大安全后所属计轴
* @param[in] UINT16 trainid 列车ID
* @return 计轴ID
* @note 无
*/
UINT16 elm_PrepareACOfMaxSafeTailLoc(UINT16 trainid)
{
	UINT16 wMaxTailLink = 0u;
	UINT8 chFunRtn = CI_ERROR;
	UINT16 wRtn = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));

	wMaxTailLink = GetTrainMaxTailLink(wTrainID);
	chFunRtn = IsLinkIdValid(wMaxTailLink);
	if (CI_SUCCESS == chFunRtn)
	{
		wRtn = GetLinkBelongAcId(wMaxTailLink);
	}
	else
	{
		;
	}

	return wRtn;
}

/**
* @brief 获取列车最小安全后所属计轴
* @param[in] UINT16 trainid 列车ID
* @return 计轴ID
* @note 无
*/
UINT16 elm_PrepareACOfMinSafeTailLoc(UINT16 trainid)
{
	UINT16 wMaxTailLink = 0u;
	UINT8 chFunRtn = CI_ERROR;
	UINT16 wRtn = 0u;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainid & 0x00ffu));

	wMaxTailLink = GetTrainMinTailLink(wTrainID);
	chFunRtn = IsLinkIdValid(wMaxTailLink);
	if (CI_SUCCESS == chFunRtn)
	{
		wRtn = GetLinkBelongAcId(wMaxTailLink);
	}
	else
	{
		;
	}

	return wRtn;
}

/**
* @brief 获取列车的休眠状态 
* @param[in] UINT16 trainid 列车ID
* @param[out] 无
* @return  TRAIN_SLEEP_YES 处于休眠状态
            TRAIN_SLEEP_NO 未处于休眠状态
			其他非法
* @note  
*/
UINT8 elm_PrepareTrainSleepStatus(UINT16 trainid)
{
	UINT8 ret = TRAIN_SLEEP_NO;
	ret = GetTrainSleepState(trainid);
	return ret;
}

/**
* @brief 获取计轴区段是否属于本OC 
* @param[in] UINT16 acID 计轴区段ID
* @param[out] UINT8 *pOCId 所属OCid
* @return ELM_BELONG_OTHER 属于相邻OC
        ELM_BELONG_OWNER 属于本OC
		其他，非法
* @note 无
*/
UINT8 elm_PrepareACIsSelf(UINT16 acID,UINT8 *pOCId)
{
	/*- 局部变量定义 */
	UINT8 ret = 0u;
	UINT8 localOCid = 0u;
	UINT8 acBelongOcid = 0u;

	/** 入口参数校验 */
	if (NULL == pOCId)
	{
		/** 入口参数错误 */
	}
	else
	{
		/** 获取本OCid */
		localOCid = GetSystemParaLocalCiId();

		/** 获取计轴所属OC id 不超过255*/
		acBelongOcid = (UINT8)GetAxisBelongTioc(acID);

		if ((0u == localOCid) || (0u == acBelongOcid))
		{
			/** 数据初始化错误 */
		}
		else if (localOCid == acBelongOcid)
		{
			/** 在一个OC*/
			(*pOCId) = acBelongOcid;
			ret = ELM_BELONG_OWNER;
		}
		else
		{
			/** 不在同一OC*/
			(*pOCId) = acBelongOcid;
			ret = ELM_BELONG_OTHER;
		}
	}

	return ret;
}
 
/**
* @brief 获取包络是否完全属于本OC
* @param[in] const EnvelopeStruct* Ptemp 
* @param[out] 无
* @return ELM_BELONG_OTHER 属于相邻OC
        ELM_BELONG_OWNER 属于本OC
		CI_ERROR，非法
* @note 无
*/
UINT8 elm_PrepareEnvelopeIsSelf(IN const EnvelopeStruct* ptemp)
{
	UINT8 ret = CI_ERROR;
	UINT16 localOCid = 0u;
	UINT16 pointABelongOcid = 0u;
	UINT16 pointBBelongOcid = 0u;

	/** 入口参数合法性校验 */
	ASSERT_RET_VALUE(NULL == ptemp,ret,0x80000000u);

	/** 获取本OCid */
	localOCid = GetSystemParaLocalCiId();

	/** 获取A点所属OC */
	pointABelongOcid = GetLinkManageTiocById(ptemp->startPos.Lnk);

	/** 获取B点所属OC */
	pointBBelongOcid = GetLinkManageTiocById(ptemp->endPos.Lnk);

	if ((localOCid == pointABelongOcid) && (localOCid == pointBBelongOcid))
	{
		/** 在一个OC*/
		ret = ELM_BELONG_OWNER;
	}
	else if((localOCid != pointABelongOcid) && (localOCid != pointBBelongOcid))
	{
		/** 不在同一OC*/
		ret = ELM_BELONG_OTHER;
	}
	else
	{
		/** 不可能走入的分支 */
	}

	return ret;
}

/**
* @brief 获取[A,B]范围内完全属于本OC的范围[A',B']
* @param[in] 无
* @param[out] LOD_STRU *pointA 截取到分界点
* @param[out] LOD_STRU *pointB 截取到分界点
* @param[out] UINT8* cutFlag 截取标志
* @return ELM_BELONG_OTHER 属于相邻OC
        ELM_BELONG_OWNER 属于本OC
		其他，非法
* @note 无
*/
UINT8 elm_PrepareCutZoneInSelf(INOUT LOD_STRU *pointA,INOUT LOD_STRU *pointB, INOUT UINT8* cutFlag)
{
	/*- 局部变量定义 */
	UINT8 ret = 0u;
	UINT8 funRtn = CI_ERROR;
	UINT16 localOCid = 0u;
	UINT16 pointABelongOcid = 0u;
	UINT16 pointBBelongOcid = 0u;
	LOD_STRU temp = {0u};

	/** 入口参数校验 */
	if ((NULL == pointA) || (NULL == pointB) || (NULL == cutFlag))
	{
		/** 入口参数错误 */
	}
	else
	{

		/** 获取本OCid */
		localOCid = GetSystemParaLocalCiId();

		/** 获取A点所属OC */
		pointABelongOcid = GetLinkManageTiocById(pointA->Lnk);

		/** 获取B点所属OC */
		pointBBelongOcid = GetLinkManageTiocById(pointB->Lnk);


		if ((0u == localOCid) || (0u == pointABelongOcid) || (0u == pointBBelongOcid))
		{
			/** 数据初始化错误 */
		}
		else if ((localOCid == pointABelongOcid) && (localOCid == pointBBelongOcid))
		{
			/** 在一个OC*/
			ret = ELM_BELONG_OWNER;
			(*cutFlag) = ELM_NO_CUT;
		}
		else if((localOCid != pointABelongOcid) && (localOCid != pointBBelongOcid))
		{
			/** 不在同一OC*/
			ret = ELM_BELONG_OTHER;
			(*cutFlag) = ELM_NO_CUT;
		}
		else if ((localOCid != pointABelongOcid) && (localOCid == pointBBelongOcid))
		{

			/** 说明跨着分界点 尾不属于本OC*/
			funRtn = GetCfpLocByTwoPointsEx((*pointA),(*pointB),&temp);
			(*cutFlag) = ELM_TAIL_CUT;
			 
			/** 根据查询结果设置出口参数 */
			ASSERT_SETRET(CI_SUCCESS == funRtn,(*pointA),temp,(*pointA));			
			 
		/** 根据查询结果设置返回值*/
			ASSERT_SETRET(CI_SUCCESS == funRtn,ret,ELM_BELONG_OWNER,0u);
		}
		else if ((localOCid == pointABelongOcid) && (localOCid != pointBBelongOcid))
		{
			/** 说明跨着分界点 头不属于本OC*/
			funRtn = GetCfpLocByTwoPointsEx((*pointA),(*pointB),&temp);
			(*cutFlag) = ELM_HEAD_CUT;

			/** 根据查询结果设置出口参数 */
			ASSERT_SETRET(CI_SUCCESS == funRtn,(*pointB),temp,(*pointB));
			 
		/** 根据查询结果设置返回值*/
			ASSERT_SETRET(CI_SUCCESS == funRtn,ret,ELM_BELONG_OWNER,0u);
		}
		else
		{
			/** 不可分支，返回值错误*/
		}
	}
	 
	/** 函数返回 */
	return ret;
}


/**
* @brief 获取本OC通信的OCid
* @param[out] UINT8 *pOCIDbuff OCid缓存
* @return 本OC通信数量
* @note 集成 bug 20220420 wqm 更正注释
*/
UINT8 elm_PrepareComOCID(IN const UINT8 **pOCIDbuff)
{
	/*- 局部变量定义 */
	UINT8 ret = 0u;

	/** 入口参数校验 */
	if (NULL == pOCIDbuff)
	{
		/** 入口参数错误，返回0,由外部处理*/
	}
	else
	{
		/** 获取本OC通信的OC数量 */
		ret = GetCiTransmitSpecifySysDevSum(CI_SYSTEM_TYPE_CI);

		/** 判断是否存在，不存在直接返回*/
		if (0u == ret)
		{
			/** 无相邻OC */
		}
		else
		{
			/** 获取相邻通信的TIOC ID */
			(*pOCIDbuff) = GetCiTransmitSpecifySysDevBuf(CI_SYSTEM_TYPE_CI);
		}
	}
	 
	return ret;
}


/**
* @brief 获取OC的通信状态
* @param[in] UINT8 OCID
* @return ELM_COM_STATUS_ERROR 通信状态错误
        ELM_COM_STATUS_OK 通信状态正确
* @note 
*/
UINT8 elm_PrepareOCCommStatus(UINT8 OCID)
{
	/*- 局部变量定义 */
	UINT8 ret = ELM_COM_STATUS_ERROR;
	UINT8 funRtn = TRANSMIT_STATE_BAD;

	/** 获取OC通信状态 */
	funRtn = GetCiTransmitState(CI_SYSTEM_TYPE_CI,OCID);
	 
	/** 设置函数返回值 */
	ASSERT_SETRET(TRANSMIT_STATE_GOOD == funRtn,ret,ELM_COM_STATUS_OK,ELM_COM_STATUS_ERROR)
     
/** 函数返回*/
return ret;
}

/**
* @brief 获取位置点所属OC
* @param[in] 
* @param[out]
* @return 
* @note 
*/
UINT8 elm_PreparePointIsSelf(IN const LOD_STRU *pointA,UINT8 *pOCId)
{
	/*- 局部变量定义 */
	UINT8 ret = 0u;
	UINT8 pointBelongOcid = 0u;
	UINT8 localOCid = 0u;

	/** 入口参数判断 */
	if ((NULL == pointA) || (NULL == pOCId))
	{
		/**入口参数错误 */
	}
	else
	{
		/** 获取本OCid */
		localOCid = GetSystemParaLocalCiId();

		/** 获取A点所属OCid,OCId不会超过255 */
		pointBelongOcid = (UINT8)GetLinkManageTiocById(pointA->Lnk);

		if ((0u != localOCid) && (0u != pointBelongOcid))
		{
			(*pOCId) = pointBelongOcid;
			ret = (localOCid == pointBelongOcid) ? ELM_BELONG_OWNER : ELM_BELONG_OTHER;
		}
		else
		{
			/** 查询错误*/
		}
	}
	return ret;
}


/**
* @brief 获取相邻OC发送的包络信息
* @param[in] UINT8 OCid
* @param[out] CfpEnvelopeStruct *pInfEnvelope 接口包络信息
* @return 
* @note 
*/
UINT8 elm_PrepareNextOcInfEnvelope(UINT8 OCid,CfpEnvelopeStruct *pInfEnvelope)
{
	return GetOtherOcEnvelope(OCid,pInfEnvelope);
}


/**
* @brief 获取计轴对应的诊断信息地址
* @param[in] 
* @param[out]
* @return 
* @note 
*/
const AxisAsserStruct* elm_PrepareAxisAssertInfoPtr(UINT16 ACID)
{
	return aam_GetAxisAssertInfoPtr(ACID);
}

/**
* @brief 获取安全位置的道岔位置是否不符合拓扑关系且占用标志
* @param[in] 列车ID
* @param[out]
* @return CI_SUCCESS 符合拓扑关系或不占用
*         CI_ERROR   不符合拓扑关系且占用
* @note 
*/
UINT8 elm_PrepareTrainSafeHeadFlag(UINT16 trainId)
{
	UINT8 ret = CI_ERROR;
	UINT16 funRtn = TRAIN_HEAD_FLAG_YES;
	UINT16 wTrainID = (UINT16)(0x1400u + (trainId & 0x00ffu));

	funRtn = GetTrainSafeHeadFlag(wTrainID);

	ret = (TRAIN_HEAD_FLAG_NO == funRtn) ? CI_SUCCESS : CI_ERROR;
	return ret;
}


/**
* @brief 获取计轴关联的物理区段ID
* @param[in] UINT16 ACID 计轴区段Id
* @param[out] 无
* @return 0 查询失败
        >0 查询成功
* @note 
*/
UINT16 elm_PrepareACRelPhyId(UINT16 ACID)
{
	return GetAxisSecRelativePhySecId(ACID);
}

/**
* @brief 获取计轴故障诊断状态
* @param[in] 计轴ID
* @param[out] 无
* @return AAM_API_AC_ARB 计轴ARB
        AAM_API_AC_REDUNARB 计轴ARB冗余
		AAM_API_AC_UT 计轴UT
		AAM_API_AC_REDUNUT 计轴UT冗余
* @note 
*/
UINT8 elm_PrepareACAssertStatus(UINT16 ACID)
{
	return aam_GetACAssertStatus(ACID);
}

/**
* @brief 获取计轴故障诊断状态
* @param[in] 计轴ID
* @param[out] 无
* @return AAM_UT_PASS 坏车通过
        AAM_CT_PASS 好车通过
* @note 
*/
UINT8 elm_PrepareACPassTrainFlag(UINT16 ACID)
{
	return aam_GetACPassTrainFlag(ACID);
}


/**
* @brief 判断计轴是否为岔区
* @param[in] UINT16 ACID 计轴ID
* @param[out]
* @return 
* @note CI_SUCCESS 为岔区
*       CI_ERROR   不为岔区
*/
UINT8 elm_PrepareACIsSwitchZone(UINT16 ACID)
{
	UINT8 ret = CI_ERROR;
	UINT8 switchCnt = 0u;

	/** 获取计轴区段包含的道岔数量 */
	switchCnt = GetAxisSwitchSum(ACID);

	/** 设置函数返回值 */
	ASSERT_SETRET(0u != switchCnt,ret,CI_SUCCESS,CI_ERROR);

	/** 函数返回 */
	return ret;
}

/**
* @brief 判断计轴所属岔区是否符合拓扑关系 
* @param[in] UINT16 ACID 计轴ID
* @param[out] 无
* @return CI_SUCCESS 计轴所属岔区符合拓扑关系
*         CI_ERROR   计轴所属岔区不符合拓扑关系
* @note 注，如果传入计轴不属于岔区，则返回符合拓扑关系
*/
UINT8 elm_PrepareCheckACofSwichPos(UINT16 ACID)
{
	UINT8 ret = CI_ERROR;
	UINT8 cycle = 0u;
	UINT8 switchCnt = 0u;
	UINT8 tmpSwPos = SWITCH_POSITION_INVALID;
	const AxisSwitchStruct* pSwitch = NULL;

	/** 获取计轴区段包含的道岔数量 */
	switchCnt = GetAxisSwitchSum(ACID);
	pSwitch = GetAxisSwitchIdStru(ACID);

	if (NULL != pSwitch)
	{
		/** 判断道岔是否符合预期*/
		for (cycle = 0u; cycle < switchCnt; cycle++)
		{
			tmpSwPos = GetSwitchCurPosition(pSwitch[cycle].SwitchId);

			if (tmpSwPos != pSwitch[cycle].SwitchPosition)
			{
				break;
			}
		}

		/** 设置函数返回值 */
		if (cycle == switchCnt)
		{
			ret = CI_SUCCESS;
		}
		else
		{
			ret = CI_ERROR;
		}
	}
	else
	{
		/** 数据查询错误，返回不符合拓扑关系 */
	}

	return ret;
}

/**
* @brief 清除岔区的好车通过标志位
* @param[in] UINT16 ACID 计轴ID
* @param[out] 无
* @return 无
* @note 无
*/
void elm_PrepareClearSwPassTrainFlag(UINT16 ACID)
{
	/*- 局部变量定义 */
	UINT16 phyId = 0u;
	UINT8 cycle = 0u;
	UINT8 acCnt = 0u;
	const UINT16* acIDBuff = NULL;

	/** 获取计轴区段对应的物理区段 */
	phyId = GetAxisSecRelativePhySecId(ACID);

	/** 获取物理区段包含的计轴区段 */
	acCnt = GetPAxisSectionSum(phyId);
	acIDBuff = GetPAxisSectionIdBuf(phyId);

	if  (NULL == acIDBuff)
	{
		(void)aam_ClearACPassTrainFlag(ACID);
	}
	else
	{
		for (cycle = 0u; cycle < acCnt; cycle++)
		{
			(void)aam_ClearACPassTrainFlag(acIDBuff[cycle]);
		}
	}
}

/**
* @brief 获取计轴所属物理区段的占用状态
* @param[in] UINT16 ACID 计轴ID
* @param[out] 无
* @return SECTION_OCCUPY_YES 物理区段占用
		SECTION_OCCUPY_NO 物理区段空闲
* @note 
*/
UINT8 elm_PrepareACRelPhyStatus(UINT16 ACID)
{
	/*- 局部变量定义 */
	UINT8 ret = SECTION_OCCUPY_YES;
	UINT16 phyId = 0u;
	phyId = elm_PrepareACRelPhyId(ACID);

	/** 查询物理区段状态 */
	ret = GetPhySecCurOccupyState(phyId);

	if (SECTION_OCCUPY_NO == ret)
	{
		/** 物理区段空闲，不处理*/
	}
	else
	{
		/** 其他情况都设置为占用 */
		ret = SECTION_OCCUPY_YES;
	}

	/** 函数返回 */
	return ret;
}

/**
* @brief 获取飞车冗余宕机时间
* @param[in] 无
* @param[out] 无
* @return 冗余时间
* @note 
*/
UINT8 elm_PrepareCTFlyingRedunTime(void)
{
	return GetCTFlyingRedunCount();
}

/**
* @brief 对外接口：获取计轴关联的物理区段是否存在好车通过计轴区段
* @param[in] UINT16 acID
* @param[out] 无
* @return AAM_CT_PASS 物理区段好车通过
AAM_UT_PASS 物理区段坏车通过
*/
UINT8 elm_PreparACRelPhyPasTrainFlag(UINT16 acID)
{
	return aam_GetACRelPhyPassTrainFlag(acID);
}

/**
* @brief 根据两点与道岔状态查询两点之间的计轴区段
* @param[in] LOD_STRU pointA 位置点A
* @param[in] LOD_STRU pointB 位置点B
* @param[out] UINT16 ACID[] 两点之间包含的计轴区段
* @return 两点之间的计轴数量
* @note pointA位置点的方向为指向pointB的方向
* creat by lxc 2022/6/17
*/
UINT8 elm_PrepACBtwPointsBySwitchSta(LOD_STRU pointA, LOD_STRU pointB, INOUT UINT16 ACID[MAX_AC_IN_TRAIN])
{
	UINT16 wLinkNum = 0u;
	UINT8 chDir = 0u;
	UINT32 dwLen = UINT32_MAX;
	UINT16 wAcNum = 0u;
	UINT8 chFunRtn = CI_ERROR;
	AxisSectionConfigDataStruct * pAxisTemp = NULL;
	UINT16 szLink[LINK_SUM_MAX] = { 0u };
	UINT8 cSwtichSum = 0u;	/* 道岔数量 */
	DQU_POINT_STATUS_STRU szSwitchInfo[50] = {0u};

	pAxisTemp = GetAxisSecConfigData();

	if (NULL == ACID)
	{
		;/* 入参或数据错误 */
	}
	else
	{

		/* 获取本控区的所有道岔状态 */
		cSwtichSum = GetLocalSwitchState(szSwitchInfo);

		if (UINT8_MAX != cSwtichSum)
		{
			/* 获取link序列 */
			dwLen = dsuLenByPointAndSwitch(&pointA, &pointB, cSwtichSum, szSwitchInfo, &wLinkNum, szLink, &chDir);
			if (UINT32_MAX != dwLen)
			{
				;
			}
			else
			{
				wLinkNum = 0u;
			}
		}
		else
		{
			; /* 获取失败 */
		}

		if (0u != wLinkNum)
		{/* 根据link序列获取计轴区段序列 */
			chFunRtn = GetAxisSeqFromLinkSeq(szLink, wLinkNum, ACID, &wAcNum, SECTION_IN_ENVELOPE_SUM_MAX);
			if ((CI_ERROR == chFunRtn )|| ( SECTION_IN_ENVELOPE_SUM_MAX < wAcNum))
			{
				wAcNum = 0u;
			}
			else
			{
				;
			}
		}
		else
		{
			;
		}
	}

	/** 两点之间的计轴不超过SECTION_IN_ENVELOPE_SUM_MAX，故进行类型强转 */
	return (UINT8)wAcNum;
}


/**
* @brief 判断UINT16数组是否存在UINT16数值中
* @param[in] const UINT16 szSrcArray[] 源数数组
* @param[in] const UINT16 wSrcArrayLen 长度
* @param[in] const UINT16 szDstArray[] 待判断的数组
* @param[in] const UINT16 wDstArrayLen 长度
* @return CI_SUCCESS 指定值在冲突范围内
*         CI_ERROR   指定值不在冲突范围内
* @note 无
*/
UINT8 elm_PrepareUINT16ArrayInArray(const UINT16 szSrcArray[],const UINT16 wSrcArrayLen, const UINT16 szDstArray[], const UINT16 wDstArrayLen)
{
	/*- 局部变量定义 */
	UINT8 cRetVal = CI_ERROR;
	UINT16 ii = 0u;

	/** 入口参数校验 */
	if ((NULL == szSrcArray) || (NULL == szDstArray) || (0u == wSrcArrayLen) || (0u == wDstArrayLen))
	{
		/** 入口参数错误 */
	}
	else
	{
		if (wDstArrayLen > wSrcArrayLen)
		{
			; /* 包不住返回失败 */
		}
		else
		{
			/*- 目标值是否在指定范围内 */
			for (ii = 0u; ii < wDstArrayLen; ii++)
			{
				cRetVal = elm_PrepareInUINT16Array(szDstArray[ii], szSrcArray, wSrcArrayLen);

				if (CI_ERROR == cRetVal)
				{
					break;
				}
			}

			if (ii == wDstArrayLen)
			{
				cRetVal = CI_SUCCESS;
			}
		}
	}

	/** 函数返回*/
	return cRetVal;
}


/**
* @brief 获取UCT功能开关
* @param[in] 无
* @param[out] 无
* @return CI_SUCCESS 功能打开
*         CI_ERROR 功能关闭
* @note 无
*/
UINT8 elm_PrepareUCTSwitch(void)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chSwitch = FUNC_SWITCH_OFF;
	chSwitch = GetCiFunctionSwitchConfig(FUNC_UCT_SWITCH);
	if (FUNC_SWITCH_ON == chSwitch)
	{
		chRtn = CI_SUCCESS;
	}
	else
	{
		;
	}
	return chRtn;
}


/**
* @brief 获取本控区分界点计轴区段
* @param[out] UINT16 szAcId[CUTOFF_POINT_SUM_MAX]
* @return 0~CUTOFF_POINT_SUM_MAX-1 分界点计轴区段数量
CUTOFF_POINT_SUM_MAX 失败
* @note 无
*/
UINT8 elm_PrepareCfpAc(UINT16 szAcId[CUTOFF_POINT_SUM_MAX])
{
	UINT16 wCfpNum = 0u;
	UINT16 wCfpIndex = 0u;
	UINT8 chAcNum = 0u;
	UINT16 wCfpId = 0u;
	UINT16 wLinkId = 0u;
	UINT16 wAcId = 0u;
	wCfpNum = GetCfpSum();
	for (wCfpIndex = 0u; wCfpIndex < wCfpNum; wCfpIndex++)
	{
		wCfpId = GetCfpId(wCfpIndex);
		wLinkId = GetCfpInFirstLink(wCfpId);
		wAcId = GetLinkBelongAcId(wLinkId);
		if (0u != wAcId)
		{
			szAcId[chAcNum++] = wAcId;
		}
		else
		{
			chAcNum = CUTOFF_POINT_SUM_MAX;
			break;
		}
	}
	return chAcNum;
}

/**
* @brief 获取计轴区段相邻控区的相邻计轴区段,并返回相邻控区驶向本控区的方向
* @param[in] const UINT16 wBaseAc 基准计轴区段
* @param[out] UINT8 * pDir 进入到本方区域的方向
* @param[out] pFindAc[AC_MAXCNT_IN_SWITCH] 相邻计轴区段
*             pDirChangePointFlag 方向变化点标志
* @return UINT8_MAX 查询失败
        0~AC_MAXCNT_IN_SWITCH  查询成功
* @note 无
*/
UINT8 elm_PrepareCfpOtherTiocAc(const UINT16 wBaseAc, UINT8 * pDir, UINT16 pFindAc[AC_MAXCNT_IN_SWITCH], UINT8* pDirChangePointFlag)
{
	UINT8 ret = UINT8_MAX;
	UINT8 cycle = 0u;
	UINT8 acCnt = 0u;
	UINT16 acIdbuff[AC_MAXCNT_IN_SWITCH] = {0u};
	UINT8 funRet = CI_ERROR;
	UINT8 OCId = 0;
	UINT8 chDir = 0u;
	UINT8 cDirectionPointFlag = 0U;			/*是否具有方向变化点标志*/

	/** 入口参数合法性校验 */
	ASSERT_RET_VALUE(NULL == pDir,ret,0x80000000u);
	ASSERT_RET_VALUE(NULL == pFindAc,ret,0x0000000u);

	/** 按照逻辑正方向查询 */
	chDir = ELM_DIR_SAME;
	acCnt = elm_PrepareAdjacentAC(wBaseAc, chDir, acIdbuff, &cDirectionPointFlag);

	if (UINT8_MAX == acCnt)
	{
		/** 查询失败，返回值失败 */
	}
	else
	{
		/** 判断计轴区段是否属于本OC */
		funRet = elm_PrepareACIsSelf(acIdbuff[0u],&OCId);

		if (ELM_BELONG_OTHER == funRet)
		{
			/** 相邻区段为分界点，设置返回值*/
			if (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag)
			{
				*pDir = chDir;
			}
			else
			{
				*pDir = ~chDir;
			}
			ret = acCnt;
			for (cycle = 0u;cycle < acCnt;cycle++)
			{
				pFindAc[cycle] = acIdbuff[cycle];
			}
		}
		else
		{
			for (cycle = 0u;cycle < AC_MAXCNT_IN_SWITCH;cycle++)
			{
				acIdbuff[cycle] = 0u;
			}

			/** 按照逻辑正方向查询 */
			chDir = ELM_DIR_CONVERT;
			acCnt = elm_PrepareAdjacentAC(wBaseAc, chDir, acIdbuff, &cDirectionPointFlag);

			if (UINT8_MAX == acCnt)
			{
				/** 查询失败，返回值失败 */
			}
			else
			{
				/** 判断计轴区段是否属于本OC */
				funRet = elm_PrepareACIsSelf(acIdbuff[0u],&OCId);

				if (ELM_BELONG_OTHER == funRet)
				{
					/** 相邻区段为分界点，设置返回值*/
					if (DIRECTIONPOINT_FLAG_VALID == cDirectionPointFlag)
					{
						*pDir = chDir;
					}
					else
					{
						*pDir = ~chDir;
					}
					ret = acCnt;
					for (cycle = 0u;cycle < acCnt;cycle++)
					{
						pFindAc[cycle] = acIdbuff[cycle];
					}
				}
				else
				{
					/** 此计轴区段不是分界点计轴，返回值失败*/
				}
			}
		}

		*pDirChangePointFlag = cDirectionPointFlag;
	}
	return ret;
}


/**
* @brief 获取列车位置位置所在区域是否具备免筛属性
* @param[in] UINT16 trainID 列车ID
* @param[out] 无
* @return ELM_TRAIN_IN_WLS_AREA 列车在免筛区域；ELM_TRAIN_OUT_WLS_AREA 列车不在免筛区域
* @note 无
*/
UINT8 elm_PrePareTrainLOCAreaType(UINT16 trainID)
{
	UINT8 ret = ELM_TRAIN_IN_WLS_AREA;
	UINT32 errorCode = 0u;
	UINT8 funRtn = CI_ERROR;
	UINT16 headOC = 0u;
	UINT16 tailOC = 0u;
	UINT8 headwlsAreaFlag = 0u;
	UINT8 tailwlsAreaFlag = 0u;
	LOD_STRU headLoc = {0u};
	LOD_STRU tailLoc = {0u};

	/** 获取最大安全前位置 */
	funRtn =  elm_PrepareMaxSafeHeadLoc(trainID, &headLoc);
	ASSER_ERROR(CI_ERROR == funRtn,errorCode,0x80000000u);

	/** 获取最小安全后位置 */
	funRtn =  elm_PrepareMinSafeTailLoc(trainID, &tailLoc);
	ASSER_ERROR(CI_ERROR == funRtn,errorCode,0x40000000u);

	if (0u == errorCode)
	{

		/** 获取最大安全前所属OC */
		headOC = GetLinkManageTiocById(headLoc.Lnk);

		/** 获取最小安全后所属OC */
		tailOC = GetLinkManageTiocById(tailLoc.Lnk);

		if ((0u == tailOC) || (0u == headOC))
		{
			/** 查询失败*/
		}
		else
		{
			headwlsAreaFlag = GetWLScreenTypeById((UINT8)headOC);
			tailwlsAreaFlag = GetWLScreenTypeById((UINT8)tailOC);

			if ((TIOC_WLSCTEEN_UNVALID == headwlsAreaFlag) && (TIOC_WLSCTEEN_UNVALID == tailwlsAreaFlag))
			{
				ret = ELM_TRAIN_OUT_WLS_AREA;
			}
			else
			{
				/** 仍在免筛区域 */
			}
		}
	}
	return ret;
}

/**
* @brief 获取列车包络是否可以转为UCT包络
* @param[in] UINT16 trainID 列车ID
* @param[out] 无
* @return 0x55:列车包络不可转为UCT包络；0xaa:列车包络可转为UCT包络
* @note 无
*/
UINT8 elm_PrePareTrainCanUct(UINT16 trainID)
{
	UINT8 chRtn = 0x55u;
	chRtn = GetTrainCanUct(trainID);
	return chRtn;
}


/**
* @brief 获取列车激活端
* @param[in] UINT16 trainID 列车ID
* @param[out] 无
* @return UINT8 激活端
* @note 无
*/
UINT8 elm_PrepareTrainACT(UINT16 trainID) 
{
	return GetTrainActive(trainID);
}

/**
* @brief 判断两点是否同向
* @param[in] LOD_STRU strPointA
* @param[in] LOD_STRU strPointB
* @return CI_ERROR:比较失败；FLAG_SET:同向；FLAG_UNSET:不同向
* @note 无
*/
UINT8 elm_PrepareTwoPointsSameDir(const LOD_STRU strPointA, const LOD_STRU strPointB)
{
	return IsPointABSameDir(strPointA, strPointB);
}

/**
* @brief 获取列车最小安全前方向
* @param[in] UINT16 wTrainId 列车编号
* @return 最小安全前方向
* @note 无
*/
UINT8 elm_PrepareTrainMinHeadDir(const UINT16 wTrainId)
{
	return GetTrainDir_MinHead(wTrainId);
}

/**
* @brief 获取列车最大安全后方向
* @param[in] UINT16 wTrainId 列车编号
* @return 最大安全后方向
* @note 无
*/
UINT8 elm_PrepareTrainMaxTailDir(const UINT16 wTrainId)
{
	return GetTrainDir_MaxTail(wTrainId);
}

/**
* @brief 获取两点间方向变化点数量
* @param[in] LOD_STRU* pLODAStru
* @param[in] LOD_STRU* pLODBStru
* @return 方向变化点数量
* @note 无
*/
UINT8 elm_PrepareDirChangNum(const LOD_STRU* pLODAStru, const LOD_STRU* pLODBStru)
{
	return GetDirChangeNumBtwPoints(pLODAStru, pLODBStru);
}

/**
* @brief 根据方向变化点数量转换方向
* @param[in] UINT8 Dir 方向
* @param[in] UINT8 wChangeNum 方向变化点数量
* @return 转换后的方向
* @note 无
*/
UINT8 elm_PrepareDirByChangeNum(UINT8 Dir, UINT8 wChangeNum)
{
	return TransDirByChangeNum(Dir, wChangeNum);
}

/**
* @brief 判断是否满足前筛通过条件(降低复杂度)
* @param[in]UINT16 wTrainId 列车ID
* @param[in]const LOD_STRU trainPos 列车安全端位置
* @param[in]const LOD_STRU ACpos 计轴对应端点位置
* @param[out] UINT32* errorCode 故障记录
* @return CI_SUCCESS 满足筛选条件
*         CI_ERROR不满足
*			ADJUST_UCT  不满足筛选但需要处理UCT包络
* Create: fan 2024 4.1
*/
UINT8 elm_PrepareHeadScreenCheck(UINT16 wTrainId, const LOD_STRU trainPos, const LOD_STRU ACpos,UINT32* errorCode)
{
	UINT8 retValue = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT32 tmpTrainLen = 0u;                 /*前方列车长度*/
	UINT16 wHeadAxis = 0u;                 /*IVOC提供的前方计轴编号*/
	UINT8 wITEResult = 0u;                 /*IVOC提供的前方ITE识别结果*/
	UINT16 tmpAxisId = 0u;                      /*计轴器id缓存*/
	UINT16 tmpACId = 0u;                      /*计轴区段id缓存*/
	UINT32 tmpDis = 0u;                      /*距离计轴端点长度*/
	UINT8 trainDir = 0u;
	UINT32 errorLog = 0u;

	if (NULL != errorCode)
	{
		errorLog = *errorCode;

		/** 获取最小安全前所属计轴区段*/
		tmpACId = elm_PrepareACOfMinSafeHeadLoc(wTrainId);
		ASSER_ERROR(0u == tmpACId, errorLog, 0x08000000u);

		/** 获取线路最小车长 */
		tmpTrainLen = elm_PrepareTrainLength(LINE_MAX_TRAIN);
		ASSER_ERROR((0u == tmpTrainLen) || (0xffffffffu == tmpTrainLen), errorLog, 0x01000000u);

		/** 计算最小安全前距离前方计轴端点的距离*/
		tmpDis = elm_PrepareDistanceBtwPoints(trainPos, ACpos);
		ASSER_ERROR(0xffffffffu == tmpDis, errorLog, 0x00800000u);

		/** 获取列车运行方向 */
		trainDir = elm_PrepareTrainMinHeadDir(wTrainId);
		ASSER_ERROR(0u == trainDir, errorLog, 0x04000000u);

		/** 获取前方计轴器*/
		funRet = elm_PrepareACHeadAxisId(tmpACId, trainDir, &tmpAxisId);
		ASSER_ERROR(CI_ERROR == funRet, errorLog, 0x00004000u);

		/* 获取IVOC提供的前方计轴编号和识别结果 */
		wHeadAxis = GetTrainHeadITEScreen(wTrainId, &wITEResult);
		ASSER_ERROR(0xffffU == wHeadAxis, errorLog, 0x00008000u);

		if ((0u == errorLog) &&
			((tmpDis < tmpTrainLen) ||
				((tmpAxisId == wHeadAxis) && (TRAIN_ITE_RESULT_NO == wITEResult))))
		{
			/*距离小于于最小车长  或满足ITE提供计轴器编号一致且无车*/
			retValue = CI_SUCCESS;
		}
		else if (tmpDis < tmpTrainLen)
		{
			/*需要处理前方UCT包络 */
			retValue = ADJUST_UCT;
		}
		else
		{
			retValue = CI_ERROR;
		}
		*errorCode += errorLog;
	}
	else
	{
		retValue = CI_ERROR;
	}
	return retValue;
}

/**
* @brief 判断是否满足后筛通过条件(降低复杂度)
* @param[in]UINT16 wTrainId 列车ID
* @param[in]const LOD_STRU trainPos 列车安全端位置
* @param[in]const LOD_STRU ACpos 计轴对应端点位置
* @param[out] UINT32* errorCode 故障记录
* @return CI_SUCCESS 满足筛选条件
*         CI_ERROR不满足
*			ADJUST_UCT  不满足筛选但需要处理UCT包络
* Create: fan 2024 4.1
*/
UINT8 elm_PrepareTailScreenCheck(UINT16 wTrainId, const LOD_STRU trainPos, const LOD_STRU ACpos, UINT32* errorCode)
{
	UINT8 retValue = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT32 tmpTrainLen = 0u;                 /*后方列车长度*/
	UINT16 wTailAxis = 0u;                 /*IVOC提供的计轴编号*/
	UINT8 wITEResult = 0u;                 /*IVOC提供的后方ITE识别结果*/
	UINT16 tmpAxisId = 0u;                      /*计轴器id缓存*/
	UINT16 tmpACId = 0u;                      /*计轴区段id缓存*/
	UINT32 tmpDis = 0u;                      /*距离计轴端点长度*/
	UINT8 trainDir = 0u;
	UINT32 errorLog = 0u;

	if (NULL != errorCode)
	{
		errorLog = *errorCode;

		/** 获取最大安全后所属计轴*/
		tmpACId = elm_PrepareACOfMaxSafeTailLoc(wTrainId);
		ASSER_ERROR(0u == tmpACId, errorLog, 0x08000000u);

		/** 获取线路最小车长 */
		tmpTrainLen = elm_PrepareTrainLength(LINE_MAX_TRAIN);
		ASSER_ERROR((0u == tmpTrainLen) || (0xffffffffu == tmpTrainLen), errorLog, 0x01000000u);

		/** 计算最大安全后距离后方计轴端点的距离*/
		tmpDis = elm_PrepareDistanceBtwPoints(trainPos, ACpos);
		ASSER_ERROR(0xffffffffu == tmpDis, errorLog, 0x00800000u);

		/** 获取列车运行方向 */
		trainDir = elm_PrepareTrainMaxTailDir(wTrainId);
		ASSER_ERROR(0u == trainDir, errorLog, 0x04000000u);

		/** 获取后方方计轴器*/
		funRet = elm_PrepareACTailAxisId(tmpACId, trainDir, &tmpAxisId);
		ASSER_ERROR(CI_ERROR == funRet, errorLog, 0x00004000u);

		/* 获取IVOC提供的后方计轴编号和识别结果 */
		wTailAxis = GetTrainTailITEScreen(wTrainId, &wITEResult);
		ASSER_ERROR(0xffffU == wTailAxis, errorLog, 0x00008000u);

		if ((0u == errorLog) &&
			((tmpDis < tmpTrainLen) ||
				((tmpAxisId == wTailAxis) && (TRAIN_ITE_RESULT_NO == wITEResult))))
		{
			/*距离小于于最小车长  或满足ITE提供计轴器编号一致且无车*/
			retValue = CI_SUCCESS;
		}
		else if (tmpDis < tmpTrainLen)
		{
			/*需要处理前方UCT包络 */
			retValue = ADJUST_UCT;
		}
		else
		{
			retValue = CI_ERROR;
		}
		*errorCode += errorLog;
	}
	else
	{
		retValue = CI_ERROR;
	}
	return retValue;
}