 /******************************************************************************
** 文件名:  CTEnvelopeTrack.c
** 描 述:   实现CT包络的追踪处理
*******************************************************************************/ 
#include "EnvelopeLogicProcess.h"
#include "AxisAssertManageAPI.h"
#include "../DataManage/DeviceDataManage.h"
#include "WholeLineScreenAPI.h"

#if LINE_MAX_TRAIN > 255
#error LINE_MAX_TRAIN数值不能超过255，目前设备ID定义（类型（1字节）+ID（1字节））
#endif

/*================================静态函数声明区==============================*/


static UINT8 elm_ProcessHeadLeave(UINT16 trainid, IN const EnvelopeStruct* pEnvelop, IN const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX], \
	UINT8 preACCnt, IN const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX], UINT8 newACCnt);  /* 处理车头离开 */
static UINT8 elm_ProcessTailLeave(UINT16 trainid, IN const EnvelopeStruct* pEnvelop, IN const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX], \
	UINT8 preACCnt, IN const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX], UINT8 newACCnt);  /* 处理车尾离开 */

static UINT8 elm_RefreshACMapInfo(IN const EnvelopeStruct* pEnvelop, IN const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX], \
	UINT8 preACCnt, IN const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX], UINT8 newACCnt);   /* 刷新包络内计轴的映射关系信息 */

static void elm_SearchCTELMSuspHeadandTail(UINT16 trainID, UINT8 cutFlag, IN const ELM_TrainSafeLocStruct *pSafeLoc, \
	OUT UINT16 *preTrainID, OUT UINT16 *pBackTrainID);    /* 根据列车位置，获取列车的前后筛信息 */
static UINT8 elm_AddCTEnvelope(UINT16 trainID, OUT UINT8 *handOverFlag);    /* 增加CT包络 */
static UINT8 elm_ReFreshACInCTEnvelope(IN const EnvelopeStruct* pEnvelop, UINT16 trainid, OUT UINT8 *handOverFlag);  /* 处理CT包络走过的路径 */
static UINT8 elm_MonitorCTEnvelopePreAndBack(IN const EnvelopeStruct* pEnvelop);    /* 监控CT包络前后端 */
static UINT8 elm_ReFreshCTEnvelope(UINT16 envelopeID, UINT16 trainid, OUT UINT8 *handOverFlag);    /* 刷新列车包络*/

/**
* @brief 静态函数：处理车头离开
* @param[in] UINT16 trainid 列车ID
* @param[in] IN const EnvelopeStruct* pEnvelop 包络信息
* @param[in] const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX]   上周期占用的包络计轴序列（序列从包络尾指向包络头）
* @param[in] UINT8 preACCnt  上周期占用的包络计轴数量
* @param[in] const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX]   本周期占用的包络计轴序列（序列从包络尾指向包络头）
* @param[in] UINT8 newACCnt  本周期占用的包络计轴数量
* @param[out] 无
* @return CI_SUCCESS 处理正确，返回成功
*         CI_ERROR   处理错误，返回失败
* @note
*   1、新建，2022年4月21日
*/
static UINT8 elm_ProcessHeadLeave(UINT16 trainid, IN const EnvelopeStruct* pEnvelop, IN const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX], \
	UINT8 preACCnt, IN const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX], UINT8 newACCnt)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT8 cycle = 0u;
	UINT32 errorCode = 0u;
	UINT8 posFlag = (UINT8)UINT8_MAX;

	/*- 入口参数校验 */
	ASSERT_RET_VALUE(NULL == preACID, ret, 0x80000000u);
	ASSERT_RET_VALUE((UINT8)SECTION_IN_ENVELOPE_SUM_MAX < preACCnt, ret, 0x40000000u);
	ASSERT_RET_VALUE(NULL == newACID, ret, 0x20000000u);
	ASSERT_RET_VALUE((UINT8)SECTION_IN_ENVELOPE_SUM_MAX < newACCnt, ret, 0x10000000u);
	ASSERT_RET_VALUE(NULL == pEnvelop, ret, 0x08000000u);

	/*- 如果有包络头存在影藏车，则需要将回缩的计轴添加UKT包络*/
	for (cycle = 0u; cycle < preACCnt; cycle++)
	{
		/** 判断计轴是否在新的包络中*/
		funRet = elm_PrepareInUINT16Array(preACID[preACCnt - cycle - 1u], newACID, newACCnt);

		/** 获取计轴在包络中的位置 */
		posFlag = elm_GetACOfEnvelopePos(preACID[preACCnt - cycle - 1u], preACID, preACCnt);

		/** 判断是否查询正确 */
		ASSERT_BREAK(UINT8_MAX == posFlag, errorCode, 0x04000000u);

		if ((CI_SUCCESS == funRet) && (ELM_HEAD == posFlag))
		{
			/** 计轴仍在新包络且为车头，继续遍历，处理之前四开道岔其他计轴*/
		}
		else if (CI_SUCCESS == funRet)
		{
			/** 找到未驶过的计轴， 跳出*/
			break;
		}
		else if (ELM_HEAD == posFlag)
		{
			if (LINE_MAX_TRAIN == pEnvelop->headTrainID)
			{
				/** 维护日志，调试级别*/
				ELM_LOG(ELM_LOG_FATAL, "info:Refresh CT_ELM%d for Train%d,Front AC%d need to add UKT_ELM.\n", pEnvelop->id, trainid, preACID[preACCnt - cycle - 1u]);

				/** 在计轴上添加故障包络*/
				funRet = elm_AddUKTEnvelopeInAC(preACID[preACCnt - cycle - 1u]);

				/** 判断是否添加成功*/
				if (CI_ERROR == funRet)
				{
					/** 添加失败，不可能分支，如果真的走进入到此分支，设置包络管理模块无法正常工作 */
					elm_SetELMWorkFlag(ELM_WORK_ERROR);
					ASSER_ERROR(CI_SUCCESS == funRet, errorCode, 0x02000000u);
					ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Refresh CT_ELM%d for Train%d,Front AC%d need to add UKT_ELM error.", errorCode, pEnvelop->id, trainid, preACID[preACCnt - cycle - 1u]);
					break;
				}
				else
				{
					/** 继续处理*/
				}
			}
			else
			{
				/** 无需处理 */
			}

			/** 设置车头出清*/
			aam_SetEnvelopeEnterFlag(AAM_ENVELOPE_HEAD_EXIT, pEnvelop->headTrainID, preACID[preACCnt - cycle - 1u], trainid);
		}
		else
		{
			/** 非车尾和车身，交给车尾处理*/
			break;
		}
	}

	/*_ 设置函数返回值 */
	ASSERT_SETRET(0u == errorCode, ret, CI_SUCCESS, CI_ERROR);
	return ret;
}


/**
* @brief 静态函数：处理车尾离开
* @param[in] UINT16 trainid 列车ID
* @param[in] IN const EnvelopeStruct* pEnvelop 包络信息
* @param[in] const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX]   上周期占用的包络计轴序列（序列从包络尾指向包络头）
* @param[in] UINT8 preACCnt  上周期占用的包络计轴数量
* @param[in] const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX]   本周期占用的包络计轴序列（序列从包络尾指向包络头）
* @param[in] UINT8 newACCnt  本周期占用的包络计轴数量
* @param[out] 无
* @return CI_SUCCESS 处理正确，返回成功
*         CI_ERROR   处理错误，返回失败
* @note
*   1、新建，2022年4月21日
*/
static UINT8 elm_ProcessTailLeave(UINT16 trainid, IN const EnvelopeStruct* pEnvelop, IN const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX], \
	UINT8 preACCnt, IN const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX], UINT8 newACCnt)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT8 cycle = 0u;
	UINT32 errorCode = 0u;
	UINT8 posFlag = (UINT8)UINT8_MAX;

	/*- 入口参数校验 */
	ASSERT_RET_VALUE(NULL == preACID, ret, 0x80000000u);
	ASSERT_RET_VALUE((UINT8)SECTION_IN_ENVELOPE_SUM_MAX < preACCnt, ret, 0x40000000u);
	ASSERT_RET_VALUE(NULL == newACID, ret, 0x20000000u);
	ASSERT_RET_VALUE((UINT8)SECTION_IN_ENVELOPE_SUM_MAX < newACCnt, ret, 0x10000000u);
	ASSERT_RET_VALUE(NULL == pEnvelop, ret, 0x08000000u);

	/*- 如果有包络尾存在影藏车，则需要将驶过的计轴添加UKT包络*/
	for (cycle = 0u; cycle < preACCnt; cycle++)
	{
		/** 判断计轴是否在新的包络中*/
		funRet = elm_PrepareInUINT16Array(preACID[cycle], newACID, newACCnt);

		/** 获取计轴在包络中的位置 */
		posFlag = elm_GetACOfEnvelopePos(preACID[cycle], preACID, preACCnt);

		/** 判断是否查询正确 */
		ASSERT_BREAK(UINT8_MAX == posFlag, errorCode, 0x04000000u);

		if ((CI_SUCCESS == funRet) && (ELM_TAIL == posFlag))
		{
			/** 计轴仍在新包络且为车尾，继续遍历，处理之前四开道岔其他计轴*/
		}
		else if (CI_SUCCESS == funRet)
		{
			/** 找到未驶过的计轴， 跳出*/
			break;
		}
		else if (((UINT8)ELM_TAIL == posFlag) || ((UINT8)ELM_BODY == posFlag))
		{
			if ((UINT16)LINE_MAX_TRAIN == pEnvelop->tailTrainID)
			{
				/** 维护日志，维护级别*/
				ELM_LOG(ELM_LOG_FATAL, "info:Refresh CT_ELM%d Train%d,Back AC%d need to add UKT_ELM.\n", pEnvelop->id, trainid, preACID[cycle]);

				/** 在计轴上添加故障包络*/
				funRet = elm_AddUKTEnvelopeInAC(preACID[cycle]);

				/** 判断是否添加成功*/
				if (CI_ERROR == funRet)
				{
					/** 添加失败，不可能分支，如果真的走进入到此分支，设置包络管理模块无法正常工作 */
					elm_SetELMWorkFlag(ELM_WORK_ERROR);
					ASSER_ERROR(CI_SUCCESS == funRet, errorCode, 0x04000000u);
					ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Refresh CT_ELM%d for Train%d,Back AC%d need to add UKT_ELM error.", errorCode, pEnvelop->id, trainid, preACID[cycle]);
					break;
				}
				else
				{
					/** 继续处理*/
				}

			}
			else
			{
				/** 无需处理 */
			}

			/** 设置车尾出清*/
			aam_SetEnvelopeEnterFlag(AAM_ENVELOPE_TAIL_EXIT, pEnvelop->tailTrainID, preACID[cycle], trainid);
		}
		else
		{
			/** 非车尾和车身，交给车头处理*/
			break;
		}
	}

	/*_ 设置函数返回值 */
	ASSERT_SETRET(0u == errorCode, ret, CI_SUCCESS, CI_ERROR);
	return ret;
}


/**
* @brief 静态函数：刷新包络内计轴的映射关系信息
* @param[in] IN const EnvelopeStruct* pEnvelop 包络信息
* @param[in] const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX]   上周期占用的包络计轴序列（序列从包络尾指向包络头）
* @param[in] UINT8 preACCnt  上周期占用的包络计轴数量
* @param[in] const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX]   本周期占用的包络计轴序列（序列从包络尾指向包络头）
* @param[in] UINT8 newACCnt  本周期占用的包络计轴数量
* @param[out] 无
* @return CI_SUCCESS 处理正确，返回成功
*         CI_ERROR   处理错误，返回失败
* @note
*   1、新建，2022年4月21日
*/
static UINT8 elm_RefreshACMapInfo(IN const EnvelopeStruct* pEnvelop, IN const UINT16 preACID[SECTION_IN_ENVELOPE_SUM_MAX], \
	UINT8 preACCnt, IN const UINT16 newACID[SECTION_IN_ENVELOPE_SUM_MAX], UINT8 newACCnt)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT8 cycle = 0u;
	UINT8 cycleY = 0u;
	UINT16 tmpACIndex = 0u;
	UINT32 errorCode = 0u;

	/*- 入口参数校验 */
	ASSERT_RET_VALUE(NULL == preACID, ret, 0x80000000u);
	ASSERT_RET_VALUE((UINT8)SECTION_IN_ENVELOPE_SUM_MAX < preACCnt, ret, 0x40000000u);
	ASSERT_RET_VALUE(NULL == newACID, ret, 0x20000000u);
	ASSERT_RET_VALUE((UINT8)SECTION_IN_ENVELOPE_SUM_MAX < newACCnt, ret, 0x10000000u);
	ASSERT_RET_VALUE(NULL == pEnvelop, ret, 0x08000000u);

	/** 计轴区段连续占用检查 */
	for (cycle = 0u; cycle < preACCnt; cycle++)
	{
		for (cycleY = 0u; cycleY < newACCnt; cycleY++)
		{
			/** 判断是否因为占用连续而跳出循环 */
			ASSERT_BREAK(preACID[cycle] == newACID[cycleY], errorCode, 0x00000000u);
		}

		/** 判断是否因为占用连续而跳出循环 */
		ASSERT_BREAK(cycleY != newACCnt, errorCode, 0x00000000u);
	}

	if (cycle == preACCnt)
	{
		/** 说明列车不连续占用计轴，设置删除此车包络，设置列车占用的区段为UKT */
		ASSER_ERROR(cycle == preACCnt, errorCode, 0x04000000u);
		ELM_LOG_LOC(ELM_LOG_FATAL, "errorCode:0x%08x info:elm ac not continue occ error.", errorCode);
	}
	else
	{
		/** 说明旧包络和新包络有交集，连续占用计轴，包络跟踪正确，删除计轴上的包络映射*/
		for (cycle = 0u; cycle < preACCnt; cycle++)
		{
			tmpACIndex = elm_PrepareACIndex(preACID[cycle]);
			funRet = elm_SetACRelEnvelopeMap(OP_DEL, tmpACIndex, pEnvelop->id);
			ASSERT_BREAK(CI_ERROR == funRet, errorCode, 0x02000000u);    /*设置错误码*/
		}

		/** 更新计轴上的包络映射*/
		for (cycle = 0u; cycle < newACCnt; cycle++)
		{
			tmpACIndex = elm_PrepareACIndex(newACID[cycle]);
			funRet = elm_SetACRelEnvelopeMap(OP_ADD, tmpACIndex, pEnvelop->id);
			ASSERT_BREAK(CI_ERROR == funRet, errorCode, 0x01000000u);    /*设置错误码*/
		}


		/*_ 设置函数返回值 */
		ASSER_DEBUG(0u != errorCode, ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Refresh acMap error.", errorCode));
	}

	ASSERT_SETRET(0u == errorCode, ret, CI_SUCCESS, CI_ERROR);
	return ret;
}

/**
* @brief 静态函数：根据列车位置，获取列车的前后筛信息
* @param[in] UINT16 trainID 列车ID
* @param[in] const ELM_TrainSafeLocStruct *pSafeLoc 安全包络
* @param[out] UINT16 *preTrainID 前车
* @param[out] UINT16 *pBackTrainID 后车
* @return
* @note
*   1、从EnvelopeManageAPI.c拆分到此文件中，代码未修改
*/
static void elm_SearchCTELMSuspHeadandTail(UINT16 trainID, UINT8 cutFlag, IN const ELM_TrainSafeLocStruct *pSafeLoc, OUT UINT16 *preTrainID, OUT UINT16 *pBackTrainID)
{
	/*- 局部变量定义 */
	UINT8 OCid = 0u;
	UINT8 cycle = 0u;
	UINT8 envelopeCnt = 0u;
	UINT8 acCnt = 0u;
	UINT8 funRtn = 0u;
	UINT8 acUTOccFlag = CI_ERROR;
	UINT16 ACID[SECTION_IN_ENVELOPE_SUM_MAX] = { 0u };
	UINT32 errorCode = 0u;
	CfpEnvelopeStruct InfEnvelope[SECTION_REL_ENVELOPE_SUM_MAX * ONE_OTHER_CFP_SUM_MAX] = { 0u };/** 获取OC发送的包络信息个数 */
	ELM_TrainSafeLocStruct tmpSafeLoc = { 0u };    /* 安全位置临时存储 */


												   /** 获取列车的安全位置*/
	funRtn = elm_PrepareTrainSafeLoc(trainID, &tmpSafeLoc);

	/** 入口参数判断*/
	ASSERT_RET_NO_VALUE(NULL == pSafeLoc, 0x80000000u);
	ASSERT_RET_NO_VALUE(NULL == preTrainID, 0x40000000u);
	ASSERT_RET_NO_VALUE(NULL == pBackTrainID, 0x20000000u);
	ASSERT_RET_NO_VALUE(CI_ERROR == funRtn, 0x10000000u);

	/** 判断车尾是否属于本OC*/
	if ((ELM_HEAD_CUT == cutFlag) || (ELM_TAIL_CUT == cutFlag))
	{
		/** 查询包络范围内的计轴，如果存在UKT包络则不信相邻OC的筛选信息 */
		acCnt = elm_PrepareACBtwPoints(pSafeLoc->startPos, pSafeLoc->endPos, ACID);

		/** 判断是否查询成功 */
		if (0u == acCnt)
		{
			/** 查询错误 */
			ASSER_ERROR(CI_ERROR == acUTOccFlag, errorCode, 0x08000000u);
		}
		else
		{
			/** 遍历所有的计轴，如果计轴上存在UKT则退出 */
			for (cycle = 0u; cycle < acCnt; cycle++)
			{
				/** 通过计轴ID获取计轴是否UT占用 */
				acUTOccFlag = elm_CheckACIsUTOcc(ACID[cycle]);

				/** 判断计轴是否为UT占用*/
				ASSERT_BREAK(CI_ERROR == acUTOccFlag, errorCode, 0x00000000u);
			}

			if (cycle == acCnt)
			{

				/** 获取相邻OC ID*/
				if (ELM_HEAD_CUT == cutFlag)
				{
					/** 获取车头所属OC */
					funRtn = elm_PreparePointIsSelf(&(tmpSafeLoc.endPos), &OCid);
				}
				else
				{
					/** 获取车尾所属OC */
					funRtn = elm_PreparePointIsSelf(&(tmpSafeLoc.startPos), &OCid);

				}

				/** 计轴上无UT占用，则采信相邻OC的筛选信息 */
				if (0u == funRtn)
				{
					ELM_LOG(ELM_LOG_FATAL, "info:Get next OC id error.\n");
				}
				else
				{
					/** 获取OC发送的包络信息 */
					envelopeCnt = elm_PrepareNextOcInfEnvelope(OCid, InfEnvelope);

					/** 遍历所有的包络 */
					for (cycle = 0u; cycle < envelopeCnt; cycle++)
					{
						if ((TYPE_CT_ENVELOPE == InfEnvelope[cycle].envelopeType) && (trainID == InfEnvelope[cycle].trainID[0]))
						{
							(*preTrainID) = InfEnvelope[cycle].headTrainID;
							(*pBackTrainID) = InfEnvelope[cycle].tailTrainID;
							ELM_LOG(ELM_LOG_FATAL, "info:Believe SuspicHeadandTail for Train%d from next OC%d cycle%d.\n", trainID, OCid, cycle);
							break;
						}
						else
						{
							/** 继续遍历*/
						}
					}
				}
			}
			else
			{
				/** 不采信相邻OC筛选信息*/
			}
		}
	}
	else
	{
		/** 属于本OC，添加前后可疑*/
	}

	/** 错误打印*/
	ASSER_DEBUG(0u != errorCode, ELM_LOG_LOC(ELM_LOG_ERROR, "errno:0x%08x info:train supec get error.", errorCode));
}


/**
* @brief 静态函数：增加CT包络
* @param[in] UINT16 trainID 列车ID
* @param[out] UINT8* handOverFlag 切换车标识
* @return CI_SUCCESS 添加CT包络正确，返回成功
*         CI_ERROR   添加CT包络错误，返回失败
* @note
*   1、从EnvelopeManageAPI.c拆分到此文件中，代码未修改
*/
static UINT8 elm_AddCTEnvelope(UINT16 trainID, OUT UINT8* handOverFlag)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;    /* 函数返回值 */
	UINT8 cycle = 0u;   /*循环变量*/
	UINT8 funRet = CI_ERROR;
	UINT32 errorCode = 0u;                         /*错误码*/
	UINT16 buffIndex = ENVELOPE_UNVAILD_INDEX;    /** 包络缓存地址 */
	UINT16 tmpACIndex = 0u;   /*计轴数组索引*/
	EnvelopeStruct tmpEnvelope = { 0u };    /*包络临时变量*/
	ELM_TrainSafeLocStruct tmpSafeLoc = { 0u };    /* 安全位置临时存储 */
	UINT8 tempEnvelopeCnt = 0u;   /*包络数量*/
	UINT16 tempEnvelopeID[SECTION_REL_ENVELOPE_SUM_MAX] = { 0u }; /*包络ID*/
	const EnvelopeStruct* pEnvelopeTemp = NULL;   /*包络指针*/
	UINT16 preTrainID = LINE_MAX_TRAIN;
	UINT16 BackTrainID = LINE_MAX_TRAIN;
	UINT8 cutFlag = ELM_NO_CUT;

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

	/** 第一步：获取列车的安全位置*/
	funRet = elm_PrepareTrainSafeLoc(trainID, &tmpSafeLoc);
	ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x80000000u)

		/** 维护日志，调试级别*/
		ELM_LOG(ELM_LOG_FATAL, "info:ADD CT_ELM Train%d,safeT:%d-%d-%02x,safeH:%d-%d-%02x.\n", trainID, tmpSafeLoc.startPos.Lnk, tmpSafeLoc.startPos.Off, tmpSafeLoc.startPos.Dir, \
			tmpSafeLoc.endPos.Lnk, tmpSafeLoc.endPos.Off, tmpSafeLoc.endPos.Dir)

		/** 对包络进行截取 */
		funRet = elm_PrepareCutZoneInSelf(&(tmpSafeLoc.startPos), &(tmpSafeLoc.endPos), &cutFlag);

	/** 补丁：判断是否是切换车，首次创建时如果列车是VBTC列车采信相邻OC发送的前后筛信息，*/
	elm_SearchCTELMSuspHeadandTail(trainID, cutFlag, &tmpSafeLoc, &preTrainID, &BackTrainID);

	/** 维护日志，调试级别*/
	ELM_LOG(ELM_LOG_FATAL, "info:CUT CT_ELM Train%d,safeT:%d-%d-%02x,safeH:%d-%d-%02x.\n", trainID, tmpSafeLoc.startPos.Lnk, tmpSafeLoc.startPos.Off, tmpSafeLoc.startPos.Dir, \
		tmpSafeLoc.endPos.Lnk, tmpSafeLoc.endPos.Off, tmpSafeLoc.endPos.Dir)

		if (ELM_BELONG_OWNER == funRet)
		{
			/** 第二步：创建包络 */
			funRet = elm_CreateEnveLope(TYPE_CT_ENVELOPE, trainID, tmpSafeLoc.startPos, tmpSafeLoc.endPos, preTrainID, BackTrainID, &tmpEnvelope);
			ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x40000000u)

				/** 判断包络是否创建成功 */
				if (0u == errorCode)
				{
					/** 从车尾开始遍历*/
					for (cycle = 0u; cycle < tmpEnvelope.ACCnt; cycle++)
					{
						/** 通过计轴ID获取计轴数组索引 */
						tmpACIndex = elm_PrepareACIndex(tmpEnvelope.ACID[cycle]);

						/** 通过计轴数组索引获取计轴关联的包络个数和包络ID */
						tempEnvelopeCnt = elm_GetACRelEnvelopeCnt(tmpACIndex, tempEnvelopeID);

						/** 如果查询的包络数非法，退出循环 */
						ASSERT_BREAK(SECTION_REL_ENVELOPE_SUM_MAX == tempEnvelopeCnt, errorCode, 0x20000000u);

						/** 判断是否存在包络*/
						if ((0u == tempEnvelopeCnt) || (1u != tempEnvelopeCnt))
						{
							/** 不存在或者存在其他包络，直接添加包络*/
						}
						else
						{
							/** 通过包络ID获取*/
							pEnvelopeTemp = elm_GetEnvelopeInfoPtr(tempEnvelopeID[0]);

							/** 判断包络的类型是否UKT包络 */
							if (TYPE_UKT_ENVELOPE == pEnvelopeTemp->envelopeType)
							{
								/** 为UKT包络，删除UKT包络*/
								funRet = elm_DeleteUKTEnvelope(pEnvelopeTemp);
							}
							else
							{
								/** 非UKT包络，无需处理 */
							}
						}
						ASSERT_BREAK(CI_ERROR == funRet, errorCode, 0x10000000u);
					}

					/** 判断处理车身范围内的包络信息 */
					if (0u == errorCode)
					{
						/** 第二步：获取可用的包络存储位置 */
						buffIndex = elm_GetEnvelopeValidIndex();
						ASSER_ERROR(ENVELOPE_UNVAILD_INDEX == buffIndex, errorCode, 0x08000000u);

						/** 判断包络索引位置是否正确*/
						if (ENVELOPE_UNVAILD_INDEX != buffIndex)
						{
							/** 设置包络唯一标识*/
							tmpEnvelope.id = buffIndex;

							/** 添加到存储区*/
							funRet = elm_SetEnvelopeByIndex(&tmpEnvelope, buffIndex);
							ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x04000000u);

							/** 从车尾开始遍历*/
							for (cycle = 0u; cycle < tmpEnvelope.ACCnt; cycle++)
							{
								/** 通过计轴ID获取计轴数组索引 */
								tmpACIndex = elm_PrepareACIndex(tmpEnvelope.ACID[cycle]);

								/** 创建计轴到包络的映射关系 */
								funRet = elm_SetACRelEnvelopeMap(OP_ADD, tmpACIndex, buffIndex);
								ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x02000000u);
							}

							/** 创建列车到包络的索引 */
							funRet = elm_SetTrainRelEnvelopeMap(OP_ADD, trainID, buffIndex);
							ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x01000000u);

							/** 判断添加CT包络是否正确 */
							if (0u != errorCode)
							{
								/** 添加包络错误，不可能分支，设置包络处理模块异常  */
								elm_SetELMWorkFlag(ELM_WORK_ERROR);
								ELM_LOG_LOC(ELM_LOG_ERROR, "errno:0x%08x info:Create CT_ELM for Train%d error because add error.", errorCode, trainID);
							}
							else
							{
								/** 处理正确*/
							}
						}
						else
						{
							/** 无可用的包络存储空间，不可能分支，设置包络处理模块异常  */
							elm_SetELMWorkFlag(ELM_WORK_ERROR);
							ELM_LOG_LOC(ELM_LOG_ERROR, "errno:0x%08x info:Create CT_ELM for Train%d error because no valid buff.", errorCode, trainID);
						}
					}
					else
					{
						/** 处理错误，不可达分支，设置包络处理模块异常 */
						elm_SetELMWorkFlag(ELM_WORK_ERROR);
						ELM_LOG_LOC(ELM_LOG_ERROR, "errno:0x%08x info:Create CT_ELM for Train%d error,errorInfo:%d-%d-%d-%d-%d.", \
							errorCode, trainID, tmpEnvelope.ACID[cycle], tmpACIndex, tempEnvelopeCnt, tempEnvelopeID[0], funRet);
					}
				}
				else
				{
					/** CT车包络创建失败 */
					ELM_LOG_LOC(ELM_LOG_ERROR, "errno:0x%08x info:Create CT_ELM for Train%d error.", errorCode, trainID);
				}
		}
		else
		{
			/** 设置完成标识 */
			*(handOverFlag) = (ELM_BELONG_OTHER == funRet) ? CI_SUCCESS : CI_ERROR;

			ASSER_ERROR(0u == funRet, errorCode, 0x00800000u);
			ASSER_DEBUG(ELM_BELONG_OTHER == funRet, ELM_LOG(ELM_LOG_FATAL, "info:CUT CT_ELM for Train%d not need to control,flag：%d.\n", trainID, funRet));
			ASSER_DEBUG(0u == funRet, ELM_LOG_LOC(ELM_LOG_ERROR, "errno:0x%08x info:CUT CT_ELM for Train%d error.", trainID, funRet));
		}

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

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


/**
* @brief 静态函数：处理CT包络走过的路径
* @param[in] const EnvelopeStruct* pEnvelop 需要处理的包络
* @param[in] UINT16 trainid 包络对应的CT车ID
* @param[out] UINT8* handOverFlag 切换完成标识
* @return CI_SUCCESS 处理正确
*         CI_ERROR   处理错误
* @note
*   1、从EnvelopeManageAPI.c拆分到此文件中，代码未修改
*/
static UINT8 elm_ReFreshACInCTEnvelope(IN const EnvelopeStruct* pEnvelop, UINT16 trainid, OUT UINT8 *handOverFlag)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT32 errorCode = 0u;                         /*错误码*/
	UINT8 tmpACCnt = 0u;          /*缓存计轴数量*/
	UINT16 tmpACID[SECTION_IN_ENVELOPE_SUM_MAX] = { 0u };      /*缓存计轴ID*/
	ELM_TrainSafeLocStruct safeLoc = { 0u };    /*列车安全位置*/
	UINT8 tmpSearchACCnt;          /*缓存计轴数量*/
	UINT16 tmpSearchACID[SECTION_IN_ENVELOPE_SUM_MAX] = { 0u };      /*缓存计轴ID*/
	UINT16 temTrainID = 0u;
	UINT8 cutFlag = ELM_NO_CUT;
	UINT8 headNeedScreen = NEED_SCREEN;
	UINT8 tailNeedScreen = NEED_SCREEN;
	UINT8 trainPort = 0u;

	/** 入口参数校验 */
	if ((NULL == pEnvelop) || (0u == trainid) || (LINE_MAX_TRAIN == trainid) || (NULL == handOverFlag))
	{
		/** 入口参数错误*/
		ASSER_ERROR(CI_ERROR == ret, errorCode, 0x80000000u)
			ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:input error!", errorCode)
	}
	else
	{
		/*- 缓存之前的计轴信息 */
		tmpACCnt = pEnvelop->ACCnt;
		if (SECTION_IN_ENVELOPE_SUM_MAX > tmpACCnt)
		{
			(void)CommonMemCpy(tmpACID, (UINT32)(sizeof(UINT16)*SECTION_IN_ENVELOPE_SUM_MAX), pEnvelop->ACID, (UINT32)(sizeof(UINT16)*pEnvelop->ACCnt));
		}
		else
		{
			;		/*要拷贝的数据大于拷贝空间，不拷贝*/
		}
		/*- 获取列车安全位置*/
		funRet = elm_PrepareTrainSafeLoc(trainid, &safeLoc);
		ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x40000000u);    /*设置错误码*/

		/** 维护日志，调试级别*/
		ELM_LOG(ELM_LOG_FATAL, "info:Refresh CT_ELM Train%d,safeT:%d-%d-%02x,safeH:%d-%d-%02x.\n", trainid, safeLoc.startPos.Lnk, safeLoc.startPos.Off, safeLoc.startPos.Dir, \
			safeLoc.endPos.Lnk, safeLoc.endPos.Off, safeLoc.endPos.Dir);

		/** 对包络进行截取 */
		funRet = elm_PrepareCutZoneInSelf(&(safeLoc.startPos), &(safeLoc.endPos), &cutFlag);

		/** 维护日志，调试级别*/
		ELM_LOG(ELM_LOG_FATAL, "info:CUT CT_ELM Train%d,safeT:%d-%d-%02x,safeH:%d-%d-%02x.\n", trainid, safeLoc.startPos.Lnk, safeLoc.startPos.Off, safeLoc.startPos.Dir, \
			safeLoc.endPos.Lnk, safeLoc.endPos.Off, safeLoc.endPos.Dir)

		if (ELM_BELONG_OWNER == funRet)
		{
				/*- 获取安全包络范围的计轴区段*/
				tmpSearchACCnt = elm_PrepareACBtwPoints(safeLoc.startPos, safeLoc.endPos, tmpSearchACID);
				ASSER_ERROR((0u == tmpSearchACCnt) || (SECTION_IN_ENVELOPE_SUM_MAX == tmpSearchACCnt), errorCode, 0x20000000u);   /*设置错误码*/

																																  /*- 更新计轴上的包络映射*/
				funRet = elm_RefreshACMapInfo(pEnvelop, tmpACID, tmpACCnt, tmpSearchACID, tmpSearchACCnt);
				ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x10000000u);    /*设置错误码*/

				if (0u == errorCode)
				{
					funRet = elm_SetEnvelopeACInfo(pEnvelop->id, tmpSearchACCnt, tmpSearchACID);
					ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x08000000u);    /*设置错误码*/

																				/*- 更新包络位置 */
					funRet = elm_SetEnvelopeLoc(pEnvelop->id, safeLoc.startPos, safeLoc.endPos);  /*设置位置*/
					ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x04000000u);    /*设置错误码*/

																				/** 更新列车激活端 */
					trainPort = elm_PrepareTrainACT(trainid);
					elm_SetTrainACTPortInELM(pEnvelop->id, trainid, trainPort);

					/*- 更新计轴上列车序列 */
					funRet = elm_RefreshACseqInfoForCT(pEnvelop, tmpSearchACID, tmpSearchACCnt, cutFlag);
					ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x02000000u);    /*设置错误码*/

					if (0u == errorCode)
					{
						/** 处理包络尾驶过的计轴 */
						funRet = elm_ProcessTailLeave(trainid, pEnvelop, tmpACID, tmpACCnt, tmpSearchACID, tmpSearchACCnt);
						ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x01000000u);    /*设置错误码*/

																					/** 处理包络头驶过的计轴*/
						funRet = elm_ProcessHeadLeave(trainid, pEnvelop, tmpACID, tmpACCnt, tmpSearchACID, tmpSearchACCnt);
						ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x00800000u);    /*设置错误码*/
					}
					else
					{
						/** 处理错误*/
					}
				}
				else
				{
					/** 已经设置成错误，无需处理*/
				}
			}
			else if (ELM_BELONG_OTHER == funRet)
			{
				/** 车不属于本OC了，直接删除包络 */
				ELM_LOG(ELM_LOG_FATAL, "errno:0x%08x info:CUT CT_ELM for Train%d not need to control,flag：%d.", errorCode, trainid, funRet);

				funRet = elm_ClearHanderOverEnvelope(pEnvelop, trainid);


				/** 下线车处理 */
				headNeedScreen = (LINE_MAX_TRAIN == pEnvelop->headTrainID) ? NEED_SCREEN : UNNEED_SCREEN;
				tailNeedScreen = (LINE_MAX_TRAIN == pEnvelop->tailTrainID) ? NEED_SCREEN : UNNEED_SCREEN;
				elm_JudgeTrainOffline(trainid, headNeedScreen, tailNeedScreen);

				(*handOverFlag) = CI_SUCCESS;    /* 切换完成列车 */
				ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x00400000u);    /*设置错误码*/
			}
			else
			{
				ASSER_ERROR(0u == funRet, errorCode, 0x00200000u)
					ELM_LOG_LOC(ELM_LOG_ERROR, "errno:0x%08x info:CUT CT_ELM for Train%d error.", errorCode, trainid)
			}
	}

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

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


/**
* @brief 静态函数：监控CT包络前后端
* @param[in]
* @param[out]
* @return
*   1、从EnvelopeManageAPI.c拆分到此文件中，代码未修改
*/
static UINT8 elm_MonitorCTEnvelopePreAndBack(IN const EnvelopeStruct* pEnvelop)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT32 errorCode = 0u;                         /*错误码*/
	const EnvelopeStruct* pTemp = NULL;
	UINT16 preEnvelopeid = 0u;
	UINT16 backEnvelopeid = 0u;
	UINT8 dirCheck = 0u;
	UINT8 chRet = CI_ERROR; /*设置前后端可疑函数返回值*/

	/** 入口参数校验 */
	if (NULL == pEnvelop)
	{
		/** 入口参数错误*/
		ASSER_ERROR(CI_ERROR == ret, errorCode, 0x80000000u)
			ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:input error!", errorCode)
	}
	else
	{
		/** 查询包络的前方和后方包络，周期查询的目的是为了吃掉前方UKT*/
		funRet = elm_GetNearestEnvelope(pEnvelop->id, &preEnvelopeid, &backEnvelopeid);

		if (CI_ERROR == funRet)
		{
			/** 设置列车前后都有影藏车*/
			(void)elm_SetEnvelopeHeadTrainID(pEnvelop->id, LINE_MAX_TRAIN);
			(void)elm_SetEnvelopeTailTrainID(pEnvelop->id, LINE_MAX_TRAIN);

			/** 维护日志--维护级别*/
			ELM_LOG_LOC(ELM_LOG_FATAL, "info:Monitor CT_ELM%d , Pre/Back ELM search error need to Add Head and Tail suspicious.", pEnvelop->id)
		}
		else
		{
			/*- 监控包络前方*/
			pTemp = elm_GetEnvelopeInfoPtr(preEnvelopeid);
			if (NULL != pTemp)
			{
				/** 比较两包络方向是否相同 */
				dirCheck = elm_DirIsSameELMWithELM(pEnvelop, pTemp);

				if (TYPE_UKT_ENVELOPE == pTemp->envelopeType)
				{
					/** 添加前方可疑*/
					chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, LINE_MAX_TRAIN);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Monitor CT_ELM%d,Add Head suspicious becasue UKT_ELM id:%d.", pEnvelop->id, pTemp->id)

						/** 判断UKT包络是否在安全位置内部*/
					funRet = elm_PrepareInUINT16Array(pTemp->ACID[0], pEnvelop->ACID, pEnvelop->ACCnt);
					

					if (CI_SUCCESS == funRet)
					{
						/** UKT包络被CT包络吃掉 */
						chRet &= elm_DeleteUKTEnvelope(pTemp);
					}
					else
					{
						/** 无需处理，只需要加前端可疑*/
					}
				}
				else if (LINE_MAX_TRAIN == pEnvelop->headTrainID)
				{
					/** 如果前方存在隐藏车，则无需设置。放在此处的目的，是为了CT车前后监控时能吃掉UKT包络 */
					chRet = CI_SUCCESS;
				}
				else if ((ELM_DIR_SAME == dirCheck) && (0u == pEnvelop->headTrainID) && (0u != pTemp->tailTrainID))
				{
					/** 添加前方可疑*/
					chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, pTemp->tailTrainID);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Head suspicious becasue ELM id:%d-T%d.", pEnvelop->id, pTemp->id, pTemp->tailTrainID);
				}
				else if ((ELM_DIR_SAME == dirCheck) && (0u != pEnvelop->headTrainID) && (0u != pTemp->tailTrainID) && (pEnvelop->headTrainID != pTemp->tailTrainID))
				{
					/** 添加前方可疑*/
					chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, LINE_MAX_TRAIN);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Head suspicious becasue ELM id:%d-T%d.", pEnvelop->id, pTemp->id, pTemp->tailTrainID);
				}
				else if ((ELM_DIR_CONVERT == dirCheck) && (0u == pEnvelop->headTrainID) && (0u != pTemp->headTrainID))
				{
					/** 添加前方可疑*/
					chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, pTemp->headTrainID);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Head suspicious becasue ELM id:%d-H%d.", pEnvelop->id, pTemp->id, pTemp->headTrainID);
				}
				else if ((ELM_DIR_CONVERT == dirCheck) && (0u != pEnvelop->headTrainID) && (0u != pTemp->headTrainID) && (pEnvelop->headTrainID != pTemp->headTrainID))
				{
					/** 添加前方可疑*/
					chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, LINE_MAX_TRAIN);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Head suspicious becasue ELM id:%d-H%d.", pEnvelop->id, pTemp->id, pTemp->headTrainID);
				}
				else if (TYPE_UCT_ENVELOPE == pTemp->envelopeType)
				{
					if (ELM_DIR_SAME == dirCheck)
					{
						if ((0u != pEnvelop->headTrainID) && (pEnvelop->headTrainID != pTemp->trainID[0u]))
						{
							/** 前方列车ID与UCT的尾车不相同*/
							chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, LINE_MAX_TRAIN);
						}
						else if (pEnvelop->trainID[0u] == pTemp->trainID[0u])
						{
							/** 目前没有聚变，所以直接染UCT的后方列车ID */
							chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, pTemp->tailTrainID);
						}
						else
						{
							/** 添加前方列车为UCT包络列车序列的尾车*/
							chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, pTemp->trainID[0u]);
						}

						/** 维护日志--维护级别*/
						ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Head suspicious becasue UCT_ELM id:%d-%d.", pEnvelop->id, pTemp->id, pTemp->trainID[0u]);
					}
					else
					{

						if ((0u != pEnvelop->headTrainID) && (pEnvelop->headTrainID != pTemp->trainID[pTemp->trianCnt - 1u]))
						{
							/** 前方列车ID与UCT的头车不相同*/
							chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, LINE_MAX_TRAIN);
						}
						else if (pEnvelop->trainID[0u] == pTemp->trainID[0u])
						{
							/** 目前没有聚变，所以直接染UCT的前方列车车 */
							chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, pTemp->headTrainID);
						}
						else
						{
							/** 添加前方列车为UCT包络列车序列的尾车*/
							chRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, pTemp->trainID[pTemp->trianCnt - 1u]);
						}

						/** 维护日志--维护级别*/
						ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Head suspicious becasue UCT_ELM id:%d-%d.", pEnvelop->id, pTemp->id, pTemp->trainID[pTemp->trianCnt - 1u]);
					}
				}
				else
				{
					/** 无需处理*/
					chRet = CI_SUCCESS;
				}
				if (CI_ERROR == chRet)
				{
					; /*设置可疑失败，暂不处理*/
				}
			}
			else
			{
				/** 无需处理*/
			}


			/*- 监控包络后方*/
			pTemp = elm_GetEnvelopeInfoPtr(backEnvelopeid);
			if (NULL != pTemp)
			{
				chRet = CI_SUCCESS;
				/** 比较两包络方向是否相同 */
				dirCheck = elm_DirIsSameELMWithELM(pEnvelop, pTemp);

				if (TYPE_UKT_ENVELOPE == pTemp->envelopeType)
				{
					/** 添加后方可疑*/
					chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, LINE_MAX_TRAIN);

					/** 维护日志，调试级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Monitor CT_ELM%d,Add Tail suspicious becasue UKT_ELM id:%d.", pEnvelop->id, pTemp->id)

						/** 判断UKT包络是否在安全位置内部*/
						funRet = elm_PrepareInUINT16Array(pTemp->ACID[0], pEnvelop->ACID, pEnvelop->ACCnt);

					if (CI_SUCCESS == funRet)
					{
						/** UKT包络被CT包络吃掉 */
						chRet &= elm_DeleteUKTEnvelope(pTemp);
					}
					else
					{
						/** 无需处理，只需要加前端可疑*/
					}
				}
				else if (LINE_MAX_TRAIN == pEnvelop->tailTrainID)
				{
					/** 如果后方存在隐藏车，则无需设置。放在此处的目的，是为了CT车前后监控时能吃掉UKT包络 */
				}
				else if ((ELM_DIR_SAME == dirCheck) && (0u == pEnvelop->tailTrainID) && (0u != pTemp->headTrainID))
				{
					/** 添加后方可疑*/
					chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, pTemp->headTrainID);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Tail suspicious becasue ELM id:%d-H%d.", pEnvelop->id, pTemp->id, pTemp->headTrainID);
				}
				else if ((ELM_DIR_SAME == dirCheck) && (0u != pEnvelop->tailTrainID) && (0u != pTemp->headTrainID) && (pEnvelop->tailTrainID != pTemp->headTrainID))
				{
					/** 添加后方可疑*/
					chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, LINE_MAX_TRAIN);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Tail suspicious becasue ELM id:%d-H%d.", pEnvelop->id, pTemp->id, pTemp->headTrainID);
				}
				else if ((ELM_DIR_CONVERT == dirCheck) && (0u == pEnvelop->tailTrainID) && (0u != pTemp->tailTrainID))
				{
					/** 添加后方可疑*/
					chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, pTemp->tailTrainID);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Tail suspicious becasue ELM id:%d-T%d.", pEnvelop->id, pTemp->id, pTemp->tailTrainID);
				}
				else if ((ELM_DIR_CONVERT == dirCheck) && (0u != pEnvelop->tailTrainID) && (0u != pTemp->tailTrainID) && (pEnvelop->tailTrainID != pTemp->tailTrainID))
				{
					/** 添加后方可疑*/
					chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, LINE_MAX_TRAIN);

					/** 维护日志--维护级别*/
					ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Tail suspicious becasue ELM id:%d-T%d.", pEnvelop->id, pTemp->id, pTemp->tailTrainID);
				}
				else if (TYPE_UCT_ENVELOPE == pTemp->envelopeType)
				{
					if (ELM_DIR_SAME == dirCheck)
					{
						if ((0u != pEnvelop->tailTrainID) && (pEnvelop->tailTrainID != pTemp->trainID[pTemp->trianCnt - 1u]))
						{
							/** 添加后方列车为255*/
							chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, LINE_MAX_TRAIN);
						}
						else if (pEnvelop->trainID[0u] == pTemp->trainID[0u])
						{
							/** 目前没有聚变，所以直接染UCT的后方列车车 */
							chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, pTemp->headTrainID);
						}
						else
						{
							/** 添加后方列车为UCT包络列车序列的头车*/
							chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, pTemp->trainID[pTemp->trianCnt - 1u]);
						}

						/** 维护日志--维护级别*/
						ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Tail suspicious becasue UCT_ELM id:%d-%d.", pEnvelop->id, pTemp->id, pTemp->trainID[pTemp->trianCnt - 1u]);
					}
					else
					{
						if ((0u != pEnvelop->tailTrainID) && (pEnvelop->tailTrainID != pTemp->trainID[0u]))
						{
							/** 添加后方列车为255*/
							chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, LINE_MAX_TRAIN);
						}
						else if (pEnvelop->trainID[0u] == pTemp->trainID[0u])
						{
							/** 目前没有聚变，所以直接染UCT的后方列车车 */
							chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, pTemp->tailTrainID);
						}
						else
						{
							/** 添加前方列车为UCT包络列车序列的尾车*/
							chRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, pTemp->trainID[0u]);
						}

						/** 维护日志--维护级别*/
						ELM_LOG_LOC(ELM_LOG_FATAL, "info:Refresh CT_ELM%d,Add Tail suspicious becasue UCT_ELM id:%d-%d.", pEnvelop->id, pTemp->id, pTemp->trainID[0u]);
					}
				}
				else
				{
					/** 无需处理*/
				}
				if (CI_ERROR == chRet)
				{
					; /*设置可疑失败，暂不处理*/
				}
			}
			else
			{
				/** 无需处理*/
			}
		}
	}

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

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

/**
* @brief 静态函数：刷新列车包络
* @param[in] UINT16 envelopeID 列车包络
* @param[out] UINT8 *handOverFlag 完成切换标识
* @return CI_SUCCESS 添加CT包络正确，返回成功
*         CI_ERROR   添加CT包络错误，返回失败
* @note
*   1、从EnvelopeManageAPI.c拆分到此文件中，代码未修改
*/
static UINT8 elm_ReFreshCTEnvelope(UINT16 envelopeID, UINT16 trainid, OUT UINT8 *handOverFlag)
{
	/*- 局部变量定义 */
	UINT8 ret = CI_ERROR;
	UINT8 funRet = CI_ERROR;
	UINT32 errorCode = 0u;                         /*错误码*/
	const EnvelopeStruct* pEnvelop = NULL;

	/** 获取列车包络 */
	pEnvelop = elm_GetEnvelopeInfoPtr(envelopeID);

	/** 入口参数校验 */
	if ((NULL == pEnvelop) || (NULL == handOverFlag))
	{
		/** 包络ID错误 */
		ASSER_ERROR(CI_ERROR == ret, errorCode, 0x80000000u)
			ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:input error!", errorCode)
	}
	else
	{
		/** 初始化位未完成切换 */
		(*handOverFlag) = CI_ERROR;

		/** 刷新包络信息 */
		funRet = elm_ReFreshACInCTEnvelope(pEnvelop, trainid, handOverFlag);
		ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x40000000u);

		if ((CI_SUCCESS == funRet) && (CI_ERROR == (*handOverFlag)))
		{
			/** 非切换完成列车，需要监控前后端 */
			funRet = elm_MonitorCTEnvelopePreAndBack(pEnvelop);
			ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x20000000u);
		}
		else if ((CI_SUCCESS == funRet) && (CI_SUCCESS == (*handOverFlag)))
		{
			/** 切换完成列车，不需要监控前后端 */
		}
		else
		{
			/** 刷新包络信息错误，返回失败 */
		}
	}

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

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


/**
* @brief CT车包络跟踪处理
* @note 安全前提：一个CT包络不可能跳过另一个CT包络；一个CT包络不可能越过一个UCT包络；存在UKT包络的计轴不可能存在CT包络或者UCT包络
*   1、从EnvelopeManageAPI.c拆分到此文件中，代码未修改
*/
void elm_CTEnvelopeTrack(void)
{
	/*- 局部变量定义 */
	UINT8 funRet = CI_ERROR;                                 /* 函数返回值 */
	UINT8 cycle = 0u;                                        /*循环变量*/
	UINT8 trainCnt = 0u;		                             /*通信车数量*/
	UINT8 handOverFlag = CI_ERROR;
	UINT16 trainID[TRAIN_SUM_MAX_IN_OC] = { 0u };              /*通信车ID*/
	UINT16 needCheckFlag[TRAIN_SUM_MAX_IN_OC] = { 0u };        /*通信车需要检查丢车标志*/
	UINT16 relEnvelopeID[TRAIN_REL_ENVELOPE_SUM_MAX] = { 0u };  /*列车关联的包络索引*/
	UINT16 relEnvelopeCnt = TRAIN_REL_ENVELOPE_SUM_MAX;    /*列车关联的包络数量*/
	UINT32 errorCode = 0u;                                   /*错误码*/

	/** 获取通信车数量，elm_PrepareCommTrainID需要实现对列车ID的合法性校验*/
	trainCnt = elm_PrepareCommTrainID(trainID);

	/** 遍历所有的通信车 */
	for (cycle = 0u; cycle < trainCnt; cycle++)
	{
		/** 获取通信车的关联包络ID */
		relEnvelopeCnt = elm_GetRelELIdByTrainIDAndType(TYPE_CT_ENVELOPE, trainID[cycle], relEnvelopeID);

		/** 获取安全位置的道岔位置是否不符合拓扑关系且占用标志 */
		funRet = elm_PrepareTrainSafeHeadFlag(trainID[cycle]);

		/** 判断列车是否为初始列车 */
		if ((CI_SUCCESS == funRet) && (0u == relEnvelopeCnt))
		{
			/** 维护日志--维护级别*/
			ELM_LOG(ELM_LOG_FATAL, "info: Create new CT_ELM for train%d.\n", trainID[cycle])

				/** 列车为初始汇报，需要增加一个通信车包络*/
				funRet = elm_AddCTEnvelope(trainID[cycle], &handOverFlag);

			/** 判断处理是否成功*/
			if (CI_ERROR == funRet)
			{
				/** 设置列车无需检查丢车 */
				needCheckFlag[cycle] = UINT8_MAX;

				/** 创建通信车包络失败，无需处理，继续维持UKT包络 */
				ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x80000000u)
					ASSER_DEBUG(CI_ERROR == funRet, ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Create new CT_ELM for train%d error!", errorCode, trainID[cycle]))
			}
			else
			{
				if (CI_SUCCESS == handOverFlag)
				{
					/** 列车完成切换删车了，无需检查丢车*/
					needCheckFlag[cycle] = UINT8_MAX;
				}
				else
				{
					/** 处理正确，需要检查是否丢车 */
				}
			}
		}
		else if ((CI_SUCCESS == funRet) && (1u == relEnvelopeCnt))
		{
			/* 只有CT包络才涉及B轨UT可追踪功能*/
			elm_DealNoCGFollowUt(relEnvelopeID[0u], trainID[cycle]);

			/** 维护日志--调试级别*/
			ELM_LOG(ELM_LOG_FATAL, "info: Refresh CT_ELM id%d for train%d .\n", relEnvelopeID[0u], trainID[cycle])

			/** 存在列车包络，只需要进行更新列车的包络，并进行前后列车的监控*/
			funRet = elm_ReFreshCTEnvelope(relEnvelopeID[0u], trainID[cycle], &handOverFlag);

			ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x40000000u);
			ASSER_DEBUG(CI_ERROR == funRet, ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Refresh CT_ELM id%d for train%d error,convert to UKT!", errorCode, relEnvelopeID[0u], trainID[cycle]));

			/** 判断处理是否成功*/
			if (CI_ERROR == funRet)
			{
				/** 设置列车无需检查丢车 */
				needCheckFlag[cycle] = UINT8_MAX;

				/** 删除CT包络，生成UKT包络 */
				funRet = elm_DeleteCTOrUCTEnvelope(relEnvelopeID[0u]);

				/** 判断是否处理成功 */
				if (CI_ERROR == funRet)
				{
					/** 设置包络管理模块处理错误 */
					elm_SetELMWorkFlag(ELM_WORK_ERROR);
					ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x20000000u)
						ASSER_DEBUG(CI_ERROR == funRet, ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Refresh CT_ELM id%d for train%d convert to UKT error!", errorCode, relEnvelopeID, trainID[cycle]))
				}
				else
				{
					/** 继续处理 */
				}
			}
			else
			{
				if (CI_SUCCESS == handOverFlag)
				{
					/** 列车完成切换删车了，无需检查丢车*/
					needCheckFlag[cycle] = UINT8_MAX;
				}
				else
				{
					/** 处理正确，需要检查是否丢车 */
				}
			}
		}
		else if ((CI_ERROR == funRet) && (0u == relEnvelopeCnt))
		{
			/** 设置列车无需检查丢车 */
			needCheckFlag[cycle] = UINT8_MAX;

			/** 列车在四开道岔上，继续维持UKT */
			ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x10000000u);
			ASSER_DEBUG(CI_ERROR == funRet, ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Don't Create new CT_ELM for train%d because switch error!", errorCode, trainID[cycle]));

		}
		else if ((CI_ERROR == funRet) && (1u == relEnvelopeCnt))
		{
			/** 设置列车无需检查丢车 */
			needCheckFlag[cycle] = UINT8_MAX;

			/** CT包络列车车头占压在四开道岔上，删除为UKT */
			(void) elm_DeleteCTOrUCTEnvelope(relEnvelopeID[0u]);
			ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x08000000u);
			ASSER_DEBUG(CI_ERROR == funRet, ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Delete CT_ELM for train%d because switch error!", errorCode, trainID[cycle]));
		}
		else
		{
			/** 设置列车无需检查丢车 */
			needCheckFlag[cycle] = UINT8_MAX;
			/* 一个CT车关联多个包络，则需要判断是否为UCT的恢复。*/
			elm_UCTEnvelopeRecover(trainID[cycle]);
		}


		/** 判断是否需要丢车防护*/
		if (UINT8_MAX == needCheckFlag[cycle])
		{
			/** 说明已经导向安全处理了，无需进行丢车检查 */
		}
		else
		{
			/** 获取通信车的关联包络ID */
			relEnvelopeCnt = elm_GetRelELIdByTrainIDAndType(TYPE_CT_ENVELOPE, trainID[cycle], relEnvelopeID);
			ASSER_ERROR((0u == relEnvelopeCnt) || (TRAIN_REL_ENVELOPE_SUM_MAX == relEnvelopeCnt), errorCode, 0x08000000u);

			if ((0u == relEnvelopeCnt) || (TRAIN_REL_ENVELOPE_SUM_MAX == relEnvelopeCnt))
			{
				/** 存在丢车风险或者包络处理错误,设置包络管理模块处理错误*/
				elm_SetELMWorkFlag(ELM_WORK_ERROR);
				ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Train%d losed error!", errorCode, trainID[cycle]);
				break;
			}
			else
			{
				/** 不存在丢车风险*/
			}
		}
	}
}

/**
* @brief 处理无C轨可追踪B轨UT
* @param[in] UINT16 envelopeID 列车包络
* @param[in] UINT16 wTrainId 列车ID
* @return 无
* @note by cgh 20240815
*/
void elm_DealNoCGFollowUt(UINT16 wEnvelopeID,UINT16 wTrainId)
{
	UINT8 funRet = CI_ERROR;
	UINT32 errorCode = 0U;/*错误码*/
	const EnvelopeStruct* pEnvelop = NULL;
	UINT8 chNoCGFollowUtSwitch = 0U;
	ELM_TrainSafeLocStruct safeLoc = { 0U };    /*列车安全位置*/
	UINT16 wTempTrainID = 0U;/*临时记录列车ID*/
	UINT8 chTempVirHeadScreenFlag = 0U;/*临时虚拟前筛标志*/
	UINT8 chTempVirTailScreenFlag = 0U;/*临时虚拟后筛标志*/

	/** 获取列车包络 */
	pEnvelop = elm_GetEnvelopeInfoPtr(wEnvelopeID);

	/** 入口参数校验 */
	if ((NULL != pEnvelop) && (0U < wTrainId) && (LINE_MAX_TRAIN > wTrainId))
	{
		funRet = elm_PrepareTrainSafeLoc(wTrainId, &safeLoc);
		ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x40000000U);
		funRet = elm_PrepareTwoPointsSameDir(safeLoc.startPos, pEnvelop->startPos);
		ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x20000000u);    /*设置错误码*/
		if (FLAG_UNSET == funRet)
		{
			/*将折返场景下包络可疑换向放到这里的目的是保证当周期安全位置和包络对应的头尾是一致的*/
			wTempTrainID = pEnvelop->headTrainID;
			funRet = elm_SetEnvelopeHeadTrainID(pEnvelop->id, pEnvelop->tailTrainID);
			ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x10000000u);    /*设置错误码*/
			funRet = elm_SetEnvelopeTailTrainID(pEnvelop->id, wTempTrainID);
			ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x08000000u);    /*设置错误码*/

			/*虚拟筛选标志也要换向*/
			chTempVirHeadScreenFlag = GetTrainVirHeadScreenPassFlag(wTrainId);
			chTempVirTailScreenFlag = GetTrainVirTailScreenPassFlag(wTrainId);
			SetTrainVirHeadScreenPassFlag(wTrainId, chTempVirTailScreenFlag);
			SetTrainVirTailScreenPassFlag(wTrainId, chTempVirHeadScreenFlag);
		}
		else
		{
			/** 未进行折返 */
		}

		chNoCGFollowUtSwitch = GetNoCGFollowUtSwitch();
		if (FUNC_SWITCH_ON == chNoCGFollowUtSwitch)
		{
			if (0U == errorCode)
			{
				/*处理AG虚拟筛选标志*/
				elm_DealAgVirScreenFlag(wEnvelopeID, wTrainId);
				/*处理BG虚拟筛选标志*/
				elm_DealBgVirScreenFlag(wEnvelopeID, wTrainId);
			}
			else
			{
				SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainFullEnterLjkCycNum(wTrainId, 0U);
				SetTrainEnterLjkLinkId(wTrainId, 0U);
			}
		}
		else
		{
			; /*功能开关未打开不处理*/
		}
	}
	else
	{
		ASSER_ERROR(CI_ERROR == funRet, errorCode, 0x80000000U);
	}

	ASSER_DEBUG(0U != errorCode, ELM_LOG_LOC(ELM_LOG_ERROR, "errorCode:0x%08x info:Train%d elm_DealNoCGFollowUt!", errorCode, wTrainId));
}

/**
* @brief 清除虚拟筛选通过标志
* @param[in] UINT16 wTrainId 列车ID
* @return 无
* @note by cgh 20240815
*/
void elm_ClearVirScreenPassFlag(UINT16 wTrainId)
{
	ELM_TrainSafeLocStruct safeLoc = { 0U };    /*列车安全位置*/
	UINT8 chCheckFlag = CI_ERROR;
	UINT16 wTrainEnterLjkLinkId = 0U;/*列车驶入列检库LINK ID*/
	UINT16 wOrgnJointMainLkId = 0U;/*起点相邻LINK编号*/
	UINT16 wTmnlJointMainLkId = 0U;/*终点相邻LINK编号*/
	UINT16 wNeedCheckLinkId = 0U;/*需要检查的LINK编号*/
	UINT16 wLinkRelatedPhySec = 0U;/*LINK关联物理区段*/
	UINT8 chCheckOccFlag = 0U;/*检查占用标志*/
	UINT8 chAxisOccState = 0U;/*计轴区段占用状态*/
	UINT32 dwOccupyToIdleCount = 0U;/*占用到空闲持续时间*/
	UINT8 chPhyLjkFlag = 0U;/*列检库属性*/
	UINT16 wLinkBelongAcId = 0U;/*LINK关联计轴区段ID*/
	UINT32 dwTrainFullEnterLjkCycNum = 0U;/*列车完全驶入LJK周期号*/
	UINT8 chLinkRelPhySecAGorBGAttr = 0U;/*LINK关联物理区段ABD属性*/
	UINT8 chTransmitState = 0U;/*列车通信状态*/
	UINT16 wTrainIndex = 0U;/*列车索引*/

	wTrainIndex = GetTrainBufIndex(wTrainId);
	if ((0U < wTrainIndex) && (LINE_MAX_TRAIN > wTrainIndex))
	{
		dwTrainFullEnterLjkCycNum = GetTrainFullEnterLjkCycNum(wTrainId);
		wTrainEnterLjkLinkId = GetTrainEnterLjkLinkId(wTrainId);
		chLinkRelPhySecAGorBGAttr = GetLinkRelPhySecAGorBGAttr(wTrainEnterLjkLinkId);

		if ((0U != dwTrainFullEnterLjkCycNum) && (LINK_REL_PHYSEC_AG == chLinkRelPhySecAGorBGAttr))
		{
			/*当前列车完全驶入LJK且是AG才继续监督DG*/
			/*列车包络完全进入A轨后，容忍占用到空闲时间，D轨出现计轴区段（道岔位置连通在D轨）采集占用，设置前筛通过标识、后筛通过标识无效*/
			wOrgnJointMainLkId = GetLinkOrgnJointMainLkIdById(wTrainEnterLjkLinkId);
			wTmnlJointMainLkId = GetLinkTmnlJointMainLkById(wTrainEnterLjkLinkId);
			wLinkRelatedPhySec = GetLinkRelatedPhySec(wOrgnJointMainLkId);
			chPhyLjkFlag = GetPhySecLjkFlag(wLinkRelatedPhySec);

			/*AG两边必有一个LINK关联物理区段不是列检库属性*/
			if (PHYSICAL_SECTION_LJK_NO == chPhyLjkFlag)
			{
				wNeedCheckLinkId = wOrgnJointMainLkId;
			}
			else
			{
				wNeedCheckLinkId = wTmnlJointMainLkId;
			}

			wLinkBelongAcId = GetLinkBelongAcId(wNeedCheckLinkId);

			if ((0U < wLinkBelongAcId) && (wLinkBelongAcId < AXIS_SECTION_SUM_MAX))
			{
				chAxisOccState = GetAxisOccupyState(wLinkBelongAcId);
				if (AXIS_SECTION_OCCUPY_NO != chAxisOccState)
				{
					dwOccupyToIdleCount = GetSystemParaOccuToIdleCyc();
					chCheckOccFlag = SystemOverTimeCheck(dwTrainFullEnterLjkCycNum, dwOccupyToIdleCount);
				}
				else
				{
					; /*未占用保持*/
				}
			}
			else
			{
				/*获取到的计轴区段错误，认为异常*/
				chCheckOccFlag = CI_TIME_OUT;
			}

			if (CI_TIME_OUT == chCheckOccFlag)
			{
				/*超时设置前后筛通过标志无效*/
				SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainFullEnterLjkCycNum(wTrainId, 0U);
				SetTrainEnterLjkLinkId(wTrainId, 0U);
			}
			else
			{
				;
			}
		}
		else
		{
			; /*不监督DG*/
		}
		

		/*列车正常通信需要根据列车位置清除标志*/
		chTransmitState = GetTrainTransitmitStat(wTrainId);
		if (TRAIN_COMM_STATE_GOOD == chTransmitState)
		{
			chCheckFlag = elm_PrepareTrainSafeLoc(wTrainId, &safeLoc);
			if (CI_SUCCESS == chCheckFlag)
			{
				/*车头驶出所在休眠唤醒轨，设置前筛通过标识无效；车尾驶出所在休眠唤醒轨，设置后筛通过标识无效*/
				if (safeLoc.endPos.Lnk != wTrainEnterLjkLinkId)
				{
					SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				}
				else
				{
					; /*不处理*/
				}

				if (safeLoc.startPos.Lnk != wTrainEnterLjkLinkId)
				{
					SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				}
				else
				{
					; /*不处理*/
				}

				if ((safeLoc.startPos.Lnk != wTrainEnterLjkLinkId) && (safeLoc.endPos.Lnk != wTrainEnterLjkLinkId))
				{
					/*列车完全不在对应轨道，清列车驶入列检库LINK和周期*/
					SetTrainEnterLjkLinkId(wTrainId, 0U);
					SetTrainFullEnterLjkCycNum(wTrainId, 0U);
				}
				else
				{
					;
				}
			}
			else
			{
				SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainFullEnterLjkCycNum(wTrainId, 0U);
				SetTrainEnterLjkLinkId(wTrainId, 0U);
			}
		}
		else
		{
			; /*不清除也不往外发*/
		}
	}
	else
	{
		; /*不处理*/
	}
}

/**
* @brief 虚拟筛选通过标志监督
* @param[in] UINT16 wTrainId 列车ID
* @return 无
* @note by cgh 20240822
*/
void elm_VirScreenPassMonitor(void)
{
	UINT16 trainCycle = 0U;
	UINT16 wTrainId = 0U;
	UINT16 wTrainEnterLjkLinkId = 0U;/*列车驶入列检库LINK ID*/

	/*遍历所有列车*/
	for (trainCycle = 0U; trainCycle < TRAIN_SUM_MAX; trainCycle++)
	{
		wTrainId = GetTrainId(trainCycle);
		wTrainEnterLjkLinkId = GetTrainEnterLjkLinkId(wTrainId);
		if (0U != wTrainEnterLjkLinkId)
		{
			/*说明需要去执行监督及清除*/
			elm_ClearVirScreenPassFlag(wTrainId);
		}
		else
		{
			; /*不需要监督和清除*/
		}
	}
}

/**
* @brief 处理AG虚拟筛选标志
* @param[in] UINT16 envelopeID 列车包络
* @param[in] UINT16 wTrainId 列车ID
* @return 无
* @note by cgh 20250805
*/
void elm_DealAgVirScreenFlag(UINT16 wEnvelopeID, UINT16 wTrainId)
{
	UINT8 funRet = CI_ERROR;
	const EnvelopeStruct* pEnvelop = NULL;
	ELM_TrainSafeLocStruct safeLoc = { 0U };    /*列车安全位置*/
	UINT8 chLinkRelPhySecAGorBGAttr = 0U;/*LINK关联物理区段ABG属性*/
	UINT8 chEnvelopLinkABGAttr = 0U;/*包络相关LINK关联物理区段ABG属性*/
	UINT16 wLinkRelatedPhySec = 0U;/*LINK关联物理区段*/
	UINT8 chPhyLjkFlag = 0U;/*列检库属性*/
	UINT16 wTrainEnterLjkLinkId = 0U;/*列车进入列检库LINK ID*/
	UINT32 dwCycNum = 0U;/*当前周期号*/
	UINT8 chAgLinkExistRelCgFlag = 0U;/*AG是否存在CG标志*/

	/** 获取列车包络 */
	pEnvelop = elm_GetEnvelopeInfoPtr(wEnvelopeID);

	/** 入口参数校验 */
	if ((NULL != pEnvelop) && (0U < wTrainId) && (LINE_MAX_TRAIN > wTrainId))
	{
		funRet = elm_PrepareTrainSafeLoc(wTrainId, &safeLoc);

		if (CI_SUCCESS == funRet)
		{
			chLinkRelPhySecAGorBGAttr = GetLinkRelPhySecAGorBGAttr(safeLoc.endPos.Lnk);
			chEnvelopLinkABGAttr = GetLinkRelPhySecAGorBGAttr(pEnvelop->endPos.Lnk);
			wLinkRelatedPhySec = GetLinkRelatedPhySec(pEnvelop->endPos.Lnk);
			chPhyLjkFlag = GetPhySecLjkFlag(wLinkRelatedPhySec);
			chAgLinkExistRelCgFlag = GetAgLinkExistRelCgFlag(safeLoc.endPos.Lnk);

			/*包络刷新在后，所以此时虽然安全位置进入AG，但包络可能还没进入*/
			if ((LINK_REL_PHYSEC_AG == chLinkRelPhySecAGorBGAttr) && (0U == pEnvelop->headTrainID)
				&& (LINK_REL_PHYSEC_DEFAULT == chEnvelopLinkABGAttr) && (PHYSICAL_SECTION_LJK_NO == chPhyLjkFlag)
				&& (AGLINK_EXIST_REL_CG_NO == chAgLinkExistRelCgFlag))
			{
				/*列车安全车头驶入AG且当前驶入前没有前端可疑且不是从BG过来的车且不存在CG便设置前筛通过标志有效*/
				SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_VALID);
				SetTrainEnterLjkLinkId(wTrainId, safeLoc.endPos.Lnk);
			}
			else
			{
				; /*不设置对应标志，安全位置和包络均进入AG维持原来的标志*/
			}

			chLinkRelPhySecAGorBGAttr = GetLinkRelPhySecAGorBGAttr(safeLoc.startPos.Lnk);
			chEnvelopLinkABGAttr = GetLinkRelPhySecAGorBGAttr(pEnvelop->startPos.Lnk);
			wLinkRelatedPhySec = GetLinkRelatedPhySec(pEnvelop->startPos.Lnk);
			chPhyLjkFlag = GetPhySecLjkFlag(wLinkRelatedPhySec);
			chAgLinkExistRelCgFlag = GetAgLinkExistRelCgFlag(safeLoc.startPos.Lnk);

			/*包络刷新在后，所以此时虽然安全位置进入AG，但包络可能还没进入*/
			if ((LINK_REL_PHYSEC_AG == chLinkRelPhySecAGorBGAttr) && (0U == pEnvelop->tailTrainID)
				&& (LINK_REL_PHYSEC_DEFAULT == chEnvelopLinkABGAttr) && (PHYSICAL_SECTION_LJK_NO == chPhyLjkFlag)
				&& (AGLINK_EXIST_REL_CG_NO == chAgLinkExistRelCgFlag))
			{
				/*列车安全车尾驶入AG且当前驶入前没有后端可疑且不是从BG过来的车且不存在CG便设置后筛通过标志有效*/
				SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_VALID);
				SetTrainEnterLjkLinkId(wTrainId, safeLoc.startPos.Lnk);
			}
			else
			{
				; /*不设置对应标志，安全位置和包络均进入AG维持原来的标志*/
			}

			wTrainEnterLjkLinkId = GetTrainEnterLjkLinkId(wTrainId);
			/*列车包络完全进入A轨后，容忍占用到空闲时间，D轨出现计轴区段（道岔位置连通在D轨）采集占用，设置前筛通过标识、后筛通过标识无效*/
			if ((LINK_REL_PHYSEC_AG == chLinkRelPhySecAGorBGAttr) && (safeLoc.startPos.Lnk == safeLoc.endPos.Lnk)
				&& (safeLoc.startPos.Lnk == wTrainEnterLjkLinkId) && (AGLINK_EXIST_REL_CG_NO == chAgLinkExistRelCgFlag))
			{
				dwCycNum = Get2oo2CurCycleNum();
				SetTrainFullEnterLjkCycNum(wTrainId, dwCycNum);
			}
			else
			{
				;
			}
		}
		else
		{
			SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
			SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
			SetTrainFullEnterLjkCycNum(wTrainId, 0U);
			SetTrainEnterLjkLinkId(wTrainId, 0U);
		}
	}
	else
	{
		;
	}
}

/**
* @brief 处理BG虚拟筛选标志
* @param[in] UINT16 envelopeID 列车包络
* @param[in] UINT16 wTrainId 列车ID
* @return 无
* @note by cgh 20250805
*/
void elm_DealBgVirScreenFlag(UINT16 wEnvelopeID, UINT16 wTrainId)
{
	UINT8 funRet = CI_ERROR;
	const EnvelopeStruct* pEnvelop = NULL;
	ELM_TrainSafeLocStruct safeLoc = { 0U };    /*列车安全位置*/
	UINT8 chLinkRelPhySecAGorBGAttr = 0U;/*LINK关联物理区段ABG属性*/
	UINT8 chEnvelopLinkABGAttr = 0U;/*包络相关LINK关联物理区段ABG属性*/
	UINT8 chAgLinkExistRelCgFlag = 0U;/*AG是否存在CG标志*/

	/** 获取列车包络 */
	pEnvelop = elm_GetEnvelopeInfoPtr(wEnvelopeID);

	/** 入口参数校验 */
	if ((NULL != pEnvelop) && (0U < wTrainId) && (LINE_MAX_TRAIN > wTrainId))
	{
		funRet = elm_PrepareTrainSafeLoc(wTrainId, &safeLoc);

		if (CI_SUCCESS == funRet)
		{
			chLinkRelPhySecAGorBGAttr = GetLinkRelPhySecAGorBGAttr(safeLoc.endPos.Lnk);
			chEnvelopLinkABGAttr = GetLinkRelPhySecAGorBGAttr(pEnvelop->endPos.Lnk);
			chAgLinkExistRelCgFlag = GetAgLinkExistRelCgFlag(pEnvelop->endPos.Lnk);

			/*包络刷新在后，所以此时虽然安全位置进入BG，但包络可能还没进入*/
			if ((LINK_REL_PHYSEC_BG == chLinkRelPhySecAGorBGAttr) && (0U == pEnvelop->headTrainID)
				&& (LINK_REL_PHYSEC_AG == chEnvelopLinkABGAttr) && (AGLINK_EXIST_REL_CG_NO == chAgLinkExistRelCgFlag))
			{
				/*列车安全车头驶入BG且当前驶入前没有前端可疑且是从AG过来的车且不存在CG便设置前筛通过标志有效*/
				SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
				SetTrainFullEnterLjkCycNum(wTrainId, 0U);
				SetTrainEnterLjkLinkId(wTrainId, 0U);
				/*先清除再设置，仅为了逻辑清晰一些*/
				SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_VALID);
				SetTrainEnterLjkLinkId(wTrainId, safeLoc.endPos.Lnk);
			}
			else
			{
				; /*不设置对应标志，安全位置和包络均进入BG维持原来的标志*/
			}

			chLinkRelPhySecAGorBGAttr = GetLinkRelPhySecAGorBGAttr(safeLoc.startPos.Lnk);
			chEnvelopLinkABGAttr = GetLinkRelPhySecAGorBGAttr(pEnvelop->startPos.Lnk);
			chAgLinkExistRelCgFlag = GetAgLinkExistRelCgFlag(pEnvelop->startPos.Lnk);

			/*包络刷新在后，所以此时虽然安全位置进入BG，但包络可能还没进入*/
			if ((LINK_REL_PHYSEC_BG == chLinkRelPhySecAGorBGAttr) && (0U == pEnvelop->tailTrainID)
				&& (LINK_REL_PHYSEC_AG == chEnvelopLinkABGAttr) && (AGLINK_EXIST_REL_CG_NO == chAgLinkExistRelCgFlag))
			{
				/*列车安全车尾驶入BG且当前驶入前没有后端可疑且是从AG过来的车且不存在CG便设置后筛通过标志有效*/
				SetTrainFullEnterLjkCycNum(wTrainId, 0U);
				SetTrainEnterLjkLinkId(wTrainId, 0U);
				/*先清除再设置，仅为了逻辑清晰一些*/
				SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_VALID);
				SetTrainEnterLjkLinkId(wTrainId, safeLoc.startPos.Lnk);
			}
			else
			{
				; /*不设置对应标志，安全位置和包络均进入AG维持原来的标志*/
			}		
		}
		else
		{
			SetTrainVirHeadScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
			SetTrainVirTailScreenPassFlag(wTrainId, TRAIN_VIR_SCREEN_PASS_FLAG_INVALID);
			SetTrainFullEnterLjkCycNum(wTrainId, 0U);
			SetTrainEnterLjkLinkId(wTrainId, 0U);
		}
	}
	else
	{
		;
	}
}