/******************************************************************************
** 文件名:  as.c  ( 排序处理 )
** 描 述:   计轴排序处理模块
*******************************************************************************/

#include "AxisSort.h"
#include "AxisSort_api.h"
#include "../EnvelopeManage/EnvelopeManageAPI.h"
#include "../EnvelopeManage/ELMDataPrepare.h"
#include "TrainOnAcManage.h"
#include "SystemConfigDefine.h"
#include "Convert.h"
#include "AxisSectionConfigDataManage.h"

/* LINK序列 */
static UINT16 g_pSortLinkNum;                         /* 本控区的Link数量 */
static UINT16 g_pSortLinkIndex[AS_LINK_MAX + 1U];     /* 本控区的Link索引 */

AS_SORT_INFO_s g_pSortLinkInfo[AS_LINK_MAX + 1U]; /*link排序*/

/* 通信车序列，在SortCT阶段完成CT车排序 */
static UINT16 s_pCTSortIndex[SIZE_MAX_LINE_TRAIN_NUM];            /*本信息不周期清空*/
static CT_SORT_INFO_s s_pCTSortInfo[SIZE_MAX_COM_VOBC_NUM + 1U];     /*本信息不周期清空*/
															 
static UINT16 g_pSortACNum; /* 本ZC控区ZC管辖的计轴数量 */
static UINT16 g_pSortACIndex[AS_AC_MAX + 1U];   /* 本ZC控区管辖的计轴索引 */
static AS_SORT_INFO_s g_pSortACInfo[AS_AC_MAX + 1U]; /* AC排序 */

static s_TRAIN_ENVELOPE_ID s_TrainELSeq;  /*列车包络*/

/*通信车序列初始化*/
static void CTSortInit(void);
/*清空Link序列*/
static void LinksClear(void);
/*清空AC序列*/
static void ACClear(void);
/*Link序列初始化*/
static void LinkSortInit(void);
/*AC序列初始化*/
static void ACSortInit(void);
/*获取空闲的通信车序列节点*/
static UINT16 GetFreeCTNode(void);
/*通信车序列删车*/
static void CTDelTrain(UINT16 u16TrainID);
/*通信车序列加车*/
static void CTAddTrain(UINT16 u16TrainID);
/*增加丢通信车序列*/
static void UCTAddTrain(UINT16 u16TrainID, IN UINT8 u8Dir, IN LOD_STRU sHead, IN LOD_STRU sTail);
/*Link添加有位置列车*/
static void LinkAddTrain(UINT16 u16LinkID, UINT16 u16TrainID, UINT8 u8Type);
/*Link序列添加列车*/
static void LinksAddTrain(UINT16 u16TrainID, UINT8 u8TrainType);
/*列车可疑左端添加故障车*/
static void TrainAddSuspectLeft(UINT16 u16TrainID, UINT16 u16LinkID);
/*列车可疑右端添加故障车*/
static void TrainAddSuspectRight(UINT16 u16TrainID, UINT16 u16LinkID);
/*插入序列*/
static void SeqInsert(IN UINT16 u16TrainID, IN UINT8 u8TrainType, IN UINT16 u16ELID, INOUT UINT8 *pu8TrainNum, INOUT TRAIN_SEQUANCE_s TrainList[SIZE_MAX_TRAINOFAC], IN UINT8 u8InsertIndex);

/*计算两列车的相对位置，并落到link上*/
static UINT8 CalcTrainOrder(IN UINT16 u16Train1, IN UINT16 u16Train2,UINT16 u16LinkID);

/*计算两个包络的相对位置,并落到计轴上*/
static UINT8 CalcEnveLopeOrderInAC(IN const EnvelopeStruct* p1, IN const EnvelopeStruct* p2, UINT16 u16ACID);
/*从列车包络模块获取根据所有的包络，对elm发来的包络进行排序，且落到AC上*/
static void SortAllEnveLopeInAC(void);
/*计轴区段根据包络添加车序*/
static void ACAddEnvelope(IN UINT16 u16ACID, IN const EnvelopeStruct *pEnvelope, IN UINT16 u16ELID);
/*添加隐藏车排序*/
static void SortSuspectCT(void);
/*丢失通信车排序*/
static void SortUCT(void);
/*纯UT车排序*/
static void SortUKT(void);

/******以下是从其他接口模块获取准备的数据*******************************/
/*查询两点间Link序列*/
static UINT8 LinkManage_GetLinkInfoExp(LOD_STRU pStart, LOD_STRU pEnd, UINT8 u8Direction, UINT16 pu16LinkID[]);
/*判断两点的前后顺序*/
static UINT8 LinkManage_CheckSortTrainExp(UINT16 u16Link1, UINT32 u32Offset1, UINT16 u16Link2, UINT32 u32Offset2, UINT8 u8Direction);
/*从筛选模块获取所有车的包络信息*/
static void elm_GetAllTrainELSeq(void);
/*是否是CT车且车头有隐藏车UKT*/
static UINT8 elm_IsCTHeadUKT(UINT16 u16TrainID);
/*是否是CT车且车尾有隐藏车UKT*/
static UINT8 elm_IsCTTailUKT(UINT16 u16TrainID);

/*计算两列车相对位置*/
static UINT8 CalcAreaOrder(IN const TrainLocStruct* p1, IN const TrainLocStruct* p2);

/**
* @brief 打印link排序信息
* @param 无
* @return 无
* @note 无
*/
static void as_DebugPrint(void);
/*****************************************************************************
* @name        as_Init
* @brief       AS模块初始化
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
void as_Init(void)
{
	/*- 通信车序列初始化 */
	CTSortInit();

	/*- Link序列初始化 */
	LinkSortInit();

	/*- AC序列初始化 */
	ACSortInit();

	
}

/*****************************************************************************
* @name        as_MainProcess
* @brief       AS模块主函数
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
void as_MainProcess(void)
{
	as_CycleInit();

	/*通信车排序*/
	as_SortCT();  

	/*准备列车包络信息（from列车包络管理模块）*/
	elm_GetAllTrainELSeq();

	/*UT车排序*/
	as_SortUT();

	/*列车包络排序*/
	as_SortBaseEnveLope();

	/*link排序信息打印*/
	as_DebugPrint();

}
/*************************************************************
* @name  as_CycleInit
* @brief 周期初始化
* @param[in] void
* @return void
* @note
*************************************************************/
void as_CycleInit(void)
{
	/*- 清空link序列 */
	LinksClear();
	/*- 清空AC序列 */
	ACClear();
}

/*****************************************************************************
* @name        CTSortInit
* @brief       通信车序列初始化
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void CTSortInit(void)
{
	/*- 初始化通信车序列*/
	(void)CommonMemSet(s_pCTSortIndex, (UINT32)sizeof(s_pCTSortIndex), 0u, (UINT32)sizeof(s_pCTSortIndex));
	(void)CommonMemSet(s_pCTSortInfo, (UINT32)sizeof(s_pCTSortInfo), 0u, (UINT32)sizeof(s_pCTSortInfo));
}


/*****************************************************************************
* @name        LinksClear
* @brief       清空Link序列
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void LinksClear(void)
{
	UINT16 u16LinkID = DEFAULT_ZERO;
	UINT16 u16Index = DEFAULT_ZERO;
	/*- 计轴索引置1 ; 是否尾部? ; 索引递增*/
	for (u16Index = 1U; u16Index <= g_pSortLinkNum; u16Index++)
	{
		/*- 清空link序列 */
		u16LinkID = g_pSortLinkInfo[u16Index].u16ID;
		(void)memset(&g_pSortLinkInfo[u16Index], 0, sizeof(AS_SORT_INFO_s));
		g_pSortLinkInfo[u16Index].u16ID = u16LinkID;
		g_pSortLinkInfo[u16Index].u8SortFail = FLAG_UNSET;

	}
}

/*****************************************************************************
* @name        ACClear
* @brief       清空AC序列
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void ACClear(void)
{
	UINT16 u16ACID = DEFAULT_ZERO;
	UINT16 u16Index = DEFAULT_ZERO;
	/*- 计轴索引置1 ; 是否尾部? ; 索引递增*/
	for (u16Index = 1U; u16Index <= g_pSortACNum; u16Index++)
	{
		/*- 清空AC序列 */
		u16ACID = g_pSortACInfo[u16Index].u16ID;
		(void)memset(&g_pSortACInfo[u16Index], 0, sizeof(AS_SORT_INFO_s));
		g_pSortACInfo[u16Index].u16ID = u16ACID;
		g_pSortACInfo[u16Index].u8SortFail = FLAG_UNSET;

	}
}


/*****************************************************************************
* @name        LinkSortInit
* @brief       Link序列初始化
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void LinkSortInit(void)
{
	UINT16 u16LinkID = DEFAULT_ZERO;    /* LinkID */

	/*- 初始化Link序列 */
	(void)CommonMemSet(g_pSortLinkIndex, (UINT32)sizeof(g_pSortLinkIndex), 0u, (UINT32)sizeof(g_pSortLinkIndex));
	(void)CommonMemSet(g_pSortLinkInfo, (UINT32)sizeof(g_pSortLinkInfo), 0u, (UINT32)sizeof(g_pSortLinkInfo));

	g_pSortLinkNum = DEFAULT_ZERO;
	for (u16LinkID = 1U; u16LinkID <= AS_LINK_MAX; u16LinkID++)
	{
		if (g_pSortLinkNum < AS_LINK_MAX)
		{
			g_pSortLinkNum++;
			g_pSortLinkIndex[u16LinkID] = g_pSortLinkNum;
			g_pSortLinkInfo[g_pSortLinkNum].u16ID = u16LinkID;
			g_pSortLinkInfo[g_pSortLinkNum].u8SortFail = FLAG_UNSET;
		}
		else
		{
			debug_infor_printf((const)"FATAL:[AS]本控区内Link数量过多\n");
		}
	}
}


/*****************************************************************************
* @name        ACSortInit
* @brief       计轴序列初始化
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void ACSortInit(void)
{
	UINT16 u16ACID = DEFAULT_ZERO;          /* 计轴ID */

	/*- 初始化计轴序列 */
	(void)CommonMemSet(g_pSortACIndex, (UINT32)sizeof(g_pSortACIndex), 0u, (UINT32)sizeof(g_pSortACIndex));
	(void)CommonMemSet(g_pSortACInfo, (UINT32)sizeof(g_pSortACInfo), 0u, (UINT32)sizeof(g_pSortACInfo));
	g_pSortACNum = DEFAULT_ZERO;

	/*- @alias 计轴序列初始化为本ZC所属的计轴们 */
	for (u16ACID = 1U; u16ACID <= AS_AC_MAX; u16ACID++)
	{
		if (g_pSortACNum < AS_AC_MAX)
		{
			g_pSortACNum++;
			g_pSortACIndex[u16ACID] = g_pSortACNum;
			g_pSortACInfo[g_pSortACNum].u16ID = u16ACID;
			g_pSortACInfo[g_pSortACNum].u8SortFail = FLAG_UNSET;
		}
		else
		{
			debug_infor_printf((const)"FATAL:[AS]本控区内计轴数量过多\n");
		}		
	}
}

/*****************************************************************************
* @name        as_SortCT
* @brief       通信车排序
* @param[in]   无
* @return      无
* @note        正常通信列车: 根据列车包络刷新通信车序列;
*        本周期丢失位置的通信列车: 在序列中转为故障车，从通信车序列中移除；
*        本周期新出现的位置报告列车: 添加到通信车序列和link序列中。
*****************************************************************************/
void as_SortCT(void)
{
	UINT8 u8LocValid = DEFAULT_ZERO;    /* 位置有效性 */
	UINT16 u16TrainID = DEFAULT_ZERO;   /* 列车ID */
	/* 由于需要把通信中断的列车转为故障车序列，所以这里不能只遍历当前通信列车 */
	
	/*- 列车索引置1 ; 是否尾部? ; 索引递增*/
	for (u16TrainID = 1U; u16TrainID < SIZE_MAX_LINETRAIN; u16TrainID++)
	{
		/*从列车管理模块中获取列车位置是否有效，即是否是CT车*/
		u8LocValid = TrainManage_GetTrainLocValid(u16TrainID);

		/*- 通信车序列是否已经存在 */
		if (DEFAULT_ZERO != s_pCTSortIndex[u16TrainID])
		{
			/*- 列车位置是否有效 */
			if (FLAG_SET == u8LocValid)
			{
				/*- 通信车序列更新列车 */
				CTAddTrain(u16TrainID);
				/*- Link序列添加CT车 */
				LinksAddTrain(u16TrainID, TYPE_CT);
			}
			else
			{
				debug_infor_printf((const)"AS0001:[%d Train] Location is Invalid, UTC Train\n", (const)u16TrainID);
#if 0
				/*- Link序列添加UT车 */
				LinksAddTrain(u16TrainID, TYPE_UCT);
				/****注意，丢失通信车在SortUCT()函数中实现，因为涉及到包络的更新*****/
#endif
			}
		}
		else
		{
			/*- 列车位置是否有效 */
			if (FLAG_SET == u8LocValid)
			{
				debug_infor_printf((const)"AS0002:Added Location Reporting Train:[%d]\n", (const)u16TrainID);
				/*- 通信车序列添加列车 */
				CTAddTrain(u16TrainID);
				/*- Link序列添加CT车 */
				LinksAddTrain(u16TrainID, TYPE_CT);
			}
			else
			{
				/*列车无定位则无需添加到通信车序列*/
			}
		}
	}

	/*- 列车索引置1 ; 是否尾部? ; 索引递增*/
	for (u16TrainID = 1U; u16TrainID < SIZE_MAX_LINETRAIN; u16TrainID++)
	{
		u8LocValid = TrainManage_GetTrainLocValid(u16TrainID);
		/*- 是否是有通信车序列的位置无效列车 */
		if ((DEFAULT_ZERO != s_pCTSortIndex[u16TrainID]) && (FLAG_SET != u8LocValid))
		{
			debug_infor_printf((const)"AS0003:[%d Train] location is invalid, delete the train\n", (const)u16TrainID);
			/*- 通信车序列删除列车 */
			CTDelTrain(u16TrainID);
		}
		else
		{
			/*无需处理*/
		}
	}
}

/*****************************************************************************
* @name        as_SortUT
* @brief       非正常通信车排序
* @param[in]   无
* @return      无
* @note        1、根据列车包络管理模块给的车包络信息，添加通信故障车需求到排序。
*                 （针对有ID车，但是类型是UCT的通信故障车）
*              2、根据列车包络管理模块模块给的车包络信息，添加可疑车到序列
                  （有车ID，且可疑标志有效）
*              3、根据列车包络管理模块给的车包络信息，添加纯UT车到序列
                  （ID为255的隐藏车）

*****************************************************************************/
void as_SortUT(void)
{
	/*添加CT隐藏车UKT到序列*/
	SortSuspectCT();
	/*添加隐藏车UKT到序列*/
	SortUKT();
	/*添加通信故障车到序列*/
	SortUCT();
}
/*****************************************************************************
* @name        SortSuspectCT
* @brief       添加隐藏车排序
* @param[in]   无
* @return      无
* @note        可疑车排序，根据列车包络管理给的车包络可疑标志，在可移方向添加故障车
*              只处理CT车255隐藏车部分，UCT部分无需处理，已经在SortUCT阶段处理。
*
*****************************************************************************/
static void SortSuspectCT(void)
{
	UINT8 u8Flag = DEFAULT_ZERO;       /* 可疑标志 */
	UINT16 u16TrainID = DEFAULT_ZERO;  /* 列车ID */
	UINT8 u8Dir_head = DEFAULT_ZERO;        /*列车安全车头运行方向*/
	UINT8 u8Dir_tail = DEFAULT_ZERO;        /*列车安全车尾运行方向*/
	/*- 列车索引置1 ; 是否尾部? ; 索引递增*/
	for (u16TrainID = 1U; u16TrainID < SIZE_MAX_LINETRAIN; u16TrainID++)
	{
		/*- 通信车序列是否存在 */
		if (DEFAULT_ZERO != s_pCTSortIndex[u16TrainID])
		{
			u8Dir_head = GetTrainSafeHeadDir(u16TrainID);
			u8Dir_tail = GetTrainSafeTailDir(u16TrainID);
			u8Flag = elm_IsCTHeadUKT(u16TrainID);
			/*- 是否CT前端有可疑UT*/
			if (FLAG_SET == u8Flag)
			{
				/*- 运行方向与电子地图方向同向 */
				if (EMAP_SAME_DIR == u8Dir_head)
				{
					/*- 后端可疑的列车，后方添加UT车 */
					TrainAddSuspectRight(u16TrainID, s_pCTSortInfo[s_pCTSortIndex[u16TrainID]].SafeHead.Lnk);
				}
				else
				{
					/*- 前端可疑的列车，前方添加UT车 */
					TrainAddSuspectLeft(u16TrainID, s_pCTSortInfo[s_pCTSortIndex[u16TrainID]].SafeHead.Lnk);
				}
			}
			else
			{
				;
			}
			u8Flag = elm_IsCTTailUKT(u16TrainID);
			/*- 是否CT后端有可疑UT */
			if (FLAG_SET == u8Flag)
			{
				/*- 运行方向与电子地图方向同向 */
				if (EMAP_SAME_DIR == u8Dir_tail)
				{
					/*- 前端可疑的列车，前方添加UT车 */
					TrainAddSuspectLeft(u16TrainID, s_pCTSortInfo[s_pCTSortIndex[u16TrainID]].SafeTail.Lnk);
				}
				else
				{
					/*- 后端可疑的列车，后方添加UT车 */
					TrainAddSuspectRight(u16TrainID, s_pCTSortInfo[s_pCTSortIndex[u16TrainID]].SafeTail.Lnk);
				}
			}
			else
			{
				;
			}
		}
		else
		{
			;
		}
	}
}
/*****************************************************************************
* @name        SortUCT
* @brief       丢失通信车排序
* @param[in]   无
* @return      无
* @note        根据列车管理模块给的车包络信息，添加通信故障车需求到排序。
*              针对有ID车，但是类型是UCT的通信故障车
*
*
*****************************************************************************/
static void SortUCT(void)
{
	UINT16 cycIndex = DEFAULT_ZERO;   /*包络索引 */
	UINT16 TrainID = DEFAULT_ZERO;
	UINT8 u8LinkNum = DEFAULT_ZERO;     /*某个包络的link数*/
	UINT8 u8Index = DEFAULT_ZERO;       /*列车包络link 索引*/
	UINT16 u16LinkIndex = DEFAULT_ZERO; /* Link索引 */
	UINT32 u32LinkLenth = DEFAULT_ZERO; /* Link lenth */
	UINT16 LinkList[MAX_LINK_LIST_NUM] = { 0U };    /* Link列表 */
	const EnvelopeStruct* pEnvelope = NULL;

	UINT8 TempNum = DEFAULT_ZERO;
	UINT16 LinkListTemp[MAX_LINK_LIST_NUM] = { DEFAULT_ZERO };
	UINT16 AcID = DEFAULT_ZERO;
	UINT8 u8OccState = DEFAULT_ZERO;

	for (cycIndex = 0U; cycIndex < s_TrainELSeq.ELNum; cycIndex++)
	{
		/*在所有包络里面找到丢失通信车包络*/
		pEnvelope = elm_GetEnvelopeInfoByID(s_TrainELSeq.TrainEnveLopeID[cycIndex]);

		if (NULL != pEnvelope)
		{
			if (TYPE_UCT == pEnvelope->envelopeType)
			{
				/**查询该列车包络内的link序列*/
				u8LinkNum = LinkManage_GetLinkInfoExp(pEnvelope->startPos, pEnvelope->endPos, pEnvelope->startPos.Dir, LinkList);
				TempNum = DEFAULT_ZERO;

				/*UCT只要考虑完全的始端到终端的link，非完整始端到终端的link，ct车已经考虑可疑。*/
				/*LinkList转化*/
				for (u8Index = 0U; u8Index < u8LinkNum; u8Index++)
				{
					u32LinkLenth = GetLinkLengthById(LinkList[u8Index]);
					if (1u == u8LinkNum)
					{
						if (((0u < pEnvelope->startPos.Off) && (u32LinkLenth > pEnvelope->startPos.Off))
							|| ((0u < pEnvelope->endPos.Off) && (u32LinkLenth > pEnvelope->endPos.Off)))
						{
							; /*始端或终端不是端点，则无需处理*/
						}
						else
						{
							/*两端都是端点*/
							LinkListTemp[0] = LinkList[0];
							TempNum = 1u;
						}
					}
					else if (MAX_LINK_LIST_NUM > u8LinkNum)
					{
						if ((0u == u8Index)
							&& (0u != pEnvelope->startPos.Off) && (u32LinkLenth != pEnvelope->startPos.Off))
						{
							; /* 起点不是端点，说明同link有CT车，剔除 */
						}
						else if (((u8LinkNum - 1u) == u8Index)
							&& (0u != pEnvelope->endPos.Off) && (u32LinkLenth != pEnvelope->endPos.Off))
						{
							; /* 终点不是端点，说明同link有CT车，剔除 */
						}
						else
						{
							LinkListTemp[TempNum] = LinkList[u8Index];
							TempNum++;
						}
					}
					else
					{
						; /**/
					}
				}
			    /************/

				/*列车包络内的Link序列初始值置0; 是否尾部? ; 索引递增*/
				for (u8Index = 0U; u8Index < TempNum; u8Index++)
				{
					/*根据linkID找到排序序列索引*/
					u16LinkIndex = g_pSortLinkIndex[LinkListTemp[u8Index]];

					AcID = GetLinkBelongAcId(LinkListTemp[u8Index]);
					u8OccState = elm_PrepareACStatus(AcID);  /*目前uct包括可能包住空闲直轨，后续裂变功能不包住的话需要处理*/

					/*- Link是否存在 */
					if ((DEFAULT_ZERO != u16LinkIndex) && (ELM_AC_OCC == u8OccState))
					{
						/*- 添加UT车 */
						debug_infor_printf((const)"AS0067:[%d Train] In Link[%d] Insert UCT Train\n", NAME_FAILUREAREA, (const)LinkListTemp[u8Index]);
						SeqInsert(NAME_FAILUREAREA, TYPE_FAILURE, cycIndex, &g_pSortLinkInfo[u16LinkIndex].u8TrainNum, g_pSortLinkInfo[u16LinkIndex].TrainList, 0U);
					}
					else
					{
						; /**/
					}	
					
				}
		
			}
			else
			{
				/*非UCT车包络无需处理*/
			}
		}
		else
		{
			;
		}
	}	
}


/*****************************************************************************
* @name        SortUKT
* @brief       纯UT车排序
* @param[in]   无
* @return      无
* @note        纯UT车排序，根据筛选模块给的车包络信息，添加纯UT车。
*
*****************************************************************************/
static void SortUKT(void)
{
	UINT16 u16LinkIndex = DEFAULT_ZERO;/* Link索引 */
	UINT16 cycIndex = DEFAULT_ZERO;   /*包络索引 */

	UINT8 u8LinkNum = DEFAULT_ZERO;     /*某个包络的link数*/
	UINT8 u8Index = DEFAULT_ZERO;       /*link 索引*/
	UINT16 LinkList[MAX_LINK_LIST_NUM] = { 0U };    /* Link列表 */
	const EnvelopeStruct* pEnvelope = NULL;

	for (cycIndex = 0U; cycIndex < s_TrainELSeq.ELNum; cycIndex++)
	{
		/*在所有包络里面找到UKT车，ID255且类型为UKT*/
		pEnvelope = elm_GetEnvelopeInfoByID(s_TrainELSeq.TrainEnveLopeID[cycIndex]);
		if (NULL != pEnvelope)
		{
			if ((NAME_FAILUREAREA == pEnvelope->trainID[0]) && (TYPE_FAILURE == pEnvelope->envelopeType))
			{
				/**查询该列车包络内的link序列*/
				u8LinkNum = LinkManage_GetLinkInfoExp(pEnvelope->startPos, pEnvelope->endPos, pEnvelope->startPos.Dir, LinkList);
				/*列车包络内的Link序列初始值置0; 是否尾部? ; 索引递增*/
				for (u8Index = 0U; u8Index < u8LinkNum; u8Index++)
				{
					if (MAX_LINK_LIST_NUM > u8Index)
					{
						/*根据linkID找到排序序列索引*/
						u16LinkIndex = g_pSortLinkIndex[LinkList[u8Index]];
						/*- Link是否存在 */
						if (DEFAULT_ZERO != u16LinkIndex)
						{
							/*- 添加UT车 */
							debug_infor_printf((const)"AS0066:[Train %d ]in Link[%d] Set UT Train\n", NAME_FAILUREAREA, (const) LinkList[u8Index]);
							SeqInsert(NAME_FAILUREAREA, TYPE_FAILURE, cycIndex, &g_pSortLinkInfo[u16LinkIndex].u8TrainNum, g_pSortLinkInfo[u16LinkIndex].TrainList, 0U);
						}
						else
						{
							;
						}
					}
					else
					{
						;
					}
				}
			}
			else
			{
				/*非UKT包络无需处理*/
			}
		}
		else
		{
			;/*无处理*/
		}

	}

}

/*****************************************************************************
* @name        CTAddTrain
* @brief       通信车序列加车
* @param[in]   u16TrainID 列车ID
* @return      无
* @note        无
*****************************************************************************/
static void CTAddTrain(UINT16 u16TrainID)
{
	UINT16 u16Index = DEFAULT_ZERO; /* 通信车序列索引 */

	/*- CT序列是不否存在 */
	if (DEFAULT_ZERO == s_pCTSortIndex[u16TrainID])
	{
		/*- 创建新的CT序列 */
		debug_infor_printf((const) "AS0005:CT Train Sequences Add Train[%d]\n", (const)u16TrainID);
		s_pCTSortIndex[u16TrainID] = GetFreeCTNode();
	}
	else
	{
		;
	}

	u16Index = s_pCTSortIndex[u16TrainID];

	/*- CT序列是否有效,更新通信车序列信息*/
	if (DEFAULT_ZERO != u16Index)
	{
		s_pCTSortInfo[u16Index].u16SortTrainID = u16TrainID;
		s_pCTSortInfo[u16Index].u8NodeValidTag = FLAG_SET;

		/*****根据ID获取列车运行方向,安全包络等********/
		s_pCTSortInfo[u16Index].u8SortTrainDir = GetTrainSafeTailDir(u16TrainID);/*包络 安全车尾点的方向*/
		(void)TrainManage_GetTrainSafeLoc(FINDHEADSAFEFLAG, u16TrainID, &s_pCTSortInfo[u16Index].SafeHead.Lnk, &s_pCTSortInfo[u16Index].SafeHead.Off, &s_pCTSortInfo[u16Index].SafeHead.Dir);
		(void)TrainManage_GetTrainSafeLoc(FINDTAILSAFEFLAG, u16TrainID, &s_pCTSortInfo[u16Index].SafeTail.Lnk, &s_pCTSortInfo[u16Index].SafeTail.Off, &s_pCTSortInfo[u16Index].SafeTail.Dir);
	}
	else
	{
		debug_infor_printf((const)"FATAL:[AS]通信车序列溢出\n");
	}
}

/*****************************************************************************
* @name        UCTAddTrain
* @brief       增加丢通信车序列
* @param[in]   u16TrainID 列车ID
* @return      无
* @note        无
*****************************************************************************/
static void UCTAddTrain(UINT16 u16TrainID, IN UINT8 u8Dir,IN LOD_STRU sHead, IN LOD_STRU sTail)
{
	UINT16 u16Index = DEFAULT_ZERO; /* 通信车序列索引 */

	/*- CT序列是不否存在 */
	if (DEFAULT_ZERO == s_pCTSortIndex[u16TrainID])
	{
		/*- 创建新的CT序列 */
		debug_infor_printf((const)"AS0055:UCT Train Sequences Add Train[%d]\n", (const)u16TrainID);
		s_pCTSortIndex[u16TrainID] = GetFreeCTNode();
	}
	else
	{
		;
	}

	u16Index = s_pCTSortIndex[u16TrainID];

	/*- CT序列是否有效,更新通信车序列信息*/
	if (DEFAULT_ZERO != u16Index)
	{
		s_pCTSortInfo[u16Index].u16SortTrainID = u16TrainID;
		s_pCTSortInfo[u16Index].u8NodeValidTag = FLAG_SET;

		s_pCTSortInfo[u16Index].u8SortTrainDir = u8Dir;
		s_pCTSortInfo[u16Index].SafeHead = sHead;
		s_pCTSortInfo[u16Index].SafeHead = sTail;
	}
	else
	{
		debug_infor_printf((const)"FATAL:[AS]通信车or丢失通信车序列溢出\n");
	}
}

/*****************************************************************************
* @name        CTDelTrain
* @brief       通信车序列删车
* @param[in]   u16TrainID 列车ID
* @return      无
* @note        无
*****************************************************************************/
static void CTDelTrain(UINT16 u16TrainID)
{
	UINT16 u16Index = DEFAULT_ZERO;

	u16Index = s_pCTSortIndex[u16TrainID];
	/*- 通信车序列是否存在 */
	if (DEFAULT_ZERO != u16Index)
	{
		/*- 从序列中删除该车 */
		debug_infor_printf((const)"AS0006:CT Train Sequences Delete Train[%d], Envelope[%d,%d]~[%d,%d], Direction[%x]\n", u16TrainID,
			s_pCTSortInfo[u16Index].SafeHead.Lnk, s_pCTSortInfo[u16Index].SafeHead.Off,
			s_pCTSortInfo[u16Index].SafeTail.Lnk, s_pCTSortInfo[u16Index].SafeTail.Off,
			s_pCTSortInfo[u16Index].u8SortTrainDir);
		(void)memset(&s_pCTSortInfo[u16Index], 0, sizeof(CT_SORT_INFO_s));
		s_pCTSortIndex[u16TrainID] = DEFAULT_ZERO;
	}
	else
	{
		/*- 不可达分支 */
		debug_infor_printf((const) "AS0007:Try to Delete Train in CT Train Sequences, But The Train Did Not Exist\n");
	}
}

/*****************************************************************************
* @name        GetFreeCTNode
* @brief       获取空闲的通信车序列节点
* @param[in]   无
* @return      通信车序列索引
* @note        无
*****************************************************************************/
static UINT16 GetFreeCTNode(void)
{
	UINT16 u16Index = DEFAULT_ZERO;
	UINT16 u16Ret = DEFAULT_ZERO;

	/*- 通信列车索引置1 ; 是否尾部? ; 索引递增*/
	for (u16Index = 1U; u16Index <= SIZE_MAX_COM_VOBC_NUM; u16Index++)
	{
		/*- 是否是空闲节点 */
		if (FLAG_SET != s_pCTSortInfo[u16Index].u8NodeValidTag)
		{
			/*- 记录节点索引，退出循环 */
			u16Ret = u16Index;
			break;
		}
		else
		{
			;
		}
	}
	return u16Ret;
}


/*****************************************************************************
* @name        LinksAddTrain
* @brief       Link序列添加列车
* @param[in]   u16TrainID  列车ID
* @param[in]   u8TrainType 列车类型
* @return      无
* @note        无
*****************************************************************************/
static void LinksAddTrain(UINT16 u16TrainID, UINT8 u8TrainType)
{
	UINT8 u8LinkNum = DEFAULT_ZERO;       /* 计轴数量 */
	UINT8 u8Index = DEFAULT_ZERO;         /* 循环变量 */
	UINT16 u16TrainIndex = DEFAULT_ZERO;  /* 通信车序列索引 */
	UINT16 u16LinkList[MAX_LINK_LIST_NUM] = {0u};     /* Link列表 */

	u16TrainIndex = s_pCTSortIndex[u16TrainID];

	/**查询该列车包络内的link序列*/
	u8LinkNum = LinkManage_GetLinkInfoExp(s_pCTSortInfo[u16TrainIndex].SafeTail,s_pCTSortInfo[u16TrainIndex].SafeHead, s_pCTSortInfo[u16TrainIndex].u8SortTrainDir, u16LinkList);

	/*列车包络内的Link序列初始值置0; 是否尾部? ; 索引递增*/
	for (u8Index = 0U; u8Index < u8LinkNum; u8Index++)
	{
		if (MAX_LINK_LIST_NUM > u8Index)
		{
			/*- Link添加列车 */
			LinkAddTrain(u16LinkList[u8Index], u16TrainID, u8TrainType);
		}
		else
		{
			;
		}
	}
}


/*****************************************************************************
* @name        LinkAddTrain
* @brief       Link添加有位置列车
* @param[in]   u16LinkID Link ID
* @param[in]   u16TrainID 列车ID
* @param[in]   u8Type 列车类型
* @return      无
* @note        
*****************************************************************************/
static void LinkAddTrain(UINT16 u16LinkID, UINT16 u16TrainID, UINT8 u8Type)
{
	UINT8 u8Order = DEFAULT_ZERO;       /* 相对位置 */
	UINT8 u8Index = DEFAULT_ZERO;       /* 循环变量 */
	UINT16 u16LinkIndex = DEFAULT_ZERO;   /* 计轴序列索引 */

	u16LinkIndex = g_pSortLinkIndex[u16LinkID];

	/*- 是否是本控区的Link */
	if (DEFAULT_ZERO != u16LinkIndex)
	{
		/*- Link排序是否有异常 */
		if (FLAG_SET == g_pSortLinkInfo[u16LinkIndex].u8SortFail)
		{
			debug_infor_printf((const)"AS0011: Try To Add Train[%d] in Abnormal Link[%d]\n", u16TrainID, u16LinkID );
		}
		/*- Link列车序列是否为空 */
		else if (DEFAULT_ZERO == g_pSortLinkInfo[u16LinkIndex].u8TrainNum)
		{
			debug_infor_printf((const)"AS0028:Link[%d] add the first train[%d]\n", u16LinkID, u16TrainID);
			g_pSortLinkInfo[u16LinkIndex].TrainList[0].u16TrainID = u16TrainID;
			g_pSortLinkInfo[u16LinkIndex].TrainList[0].u8TrainType = u8Type;
			g_pSortLinkInfo[u16LinkIndex].u8TrainNum = 1U;
		}
		/*- Link序列是否已满 */
		else if (SIZE_MAX_TRAINOFAC <= g_pSortLinkInfo[u16LinkIndex].u8TrainNum)
		{
			/* link排序列车过多，参数为LINK ID和列车数量 */
			g_pSortLinkInfo[u16LinkIndex].u8SortFail = FLAG_SET;
			debug_infor_printf((const)"AS0029:Link[%d] have too many trains, Train:[%d]\n", u16LinkID, g_pSortLinkInfo[u16LinkIndex].u8TrainNum);
			/*- @alias Link序列上列车数量过多，置排序异常 */
			for (u8Index = 0U; u8Index < g_pSortLinkInfo[u16LinkIndex].u8TrainNum; u8Index++)
			{
				debug_infor_printf((const)"[%d,%d]",
					g_pSortLinkInfo[u16LinkIndex].TrainList[u8Index].u16TrainID,
					g_pSortLinkInfo[u16LinkIndex].TrainList[u8Index].u8TrainType);
			}
			debug_infor_printf((const)"\n");
		}
		else
		{
			/*- Link序列初始值置0; 是否尾部? ; 索引递增*/
			for (u8Index = 0U; u8Index < g_pSortLinkInfo[u16LinkIndex].u8TrainNum; u8Index++)
			{
				u8Order = CalcTrainOrder(u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8Index].u16TrainID,u16LinkID);
				/*- 新车是否在该车下游 */
				if (AS_ORDER_DOWNSTREAM == u8Order)
				{
					/*- 新车在该车下游，继续遍历 */
				}
				else
				{
					/*- 新车是否在该车上游 */
					if (AS_ORDER_UPSTREAM == u8Order)
					{
						/*- 新车在该车上游，找到插入位置，循环正常退出 */
					}
					else
					{
						/*- 置排序异常，循环异常退出 */
						g_pSortLinkInfo[u16LinkIndex].u8SortFail = FLAG_SET;
						debug_infor_printf((const)"AS0030:Link[%d] sort faild : Failed to calculate relative position[%d Train][%d Train]\n",
							u16LinkID, u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8Index].u16TrainID);

					}
					/* 只要新车不在该车下游，就都结束循环，下面再根据是否发生排序异常决定是否加入序列 */
					/*- 循环退出 */
					break;
				}
			}

			/*
			* 找到了插入位置时在插入位置插入，
			* 没找到插入位置时说明新车在最后，在序列末尾插入
			*/
			/*- 排序是否正常 */
			if (FLAG_UNSET == g_pSortLinkInfo[u16LinkIndex].u8SortFail)
			{
				/*- Link序列插入列车 */
				debug_infor_printf((const) "AS0031:Link[%d] in [%d/%d] insert train[%d,%d]\n",
					u16LinkID, u8Index, g_pSortLinkInfo[u16LinkIndex].u8TrainNum, u16TrainID, u8Type);
				SeqInsert(u16TrainID, u8Type, 0 ,&g_pSortLinkInfo[u16LinkIndex].u8TrainNum, g_pSortLinkInfo[u16LinkIndex].TrainList, u8Index);
			}
			else
			{
				;
			}
		}
	}
	else
	{
		;
	}
}


/*****************************************************************************
* @name        SeqInsert
* @brief       插入序列
* @param[in]   u16TrainID    列车ID
* @param[in]   u8TrainType   列车类型
* @param[in]   u16ELID     列车包络ID
* @param[in]   pu8TrainNum   插入前的列车序列数量
* @param[out]  pu8TrainNum   插入后的列车序列数量
* @param[in]   TrainList     插入前的列车序列列表
* @param[out]  TrainList     插入后的列车序列列表
* @param[out]  u8InsertIndex 插入位置
* @return      无
* @note        无
*****************************************************************************/
static void SeqInsert(IN UINT16 u16TrainID, IN UINT8 u8TrainType, IN UINT16 u16ELID, INOUT UINT8 *pu8TrainNum, INOUT TRAIN_SEQUANCE_s TrainList[SIZE_MAX_TRAINOFAC], IN UINT8 u8InsertIndex)
{
	UINT8 u8Cycle = DEFAULT_ZERO; /* 循环变量 */
	/*- 输入是否越界 */
	if ((*pu8TrainNum < SIZE_MAX_TRAINOFAC) && (u8InsertIndex <= *pu8TrainNum))
	{
		/*- @alias 将插入位置及之后的列车后移 */
		for (u8Cycle = *pu8TrainNum; u8Cycle > u8InsertIndex; u8Cycle--)
		{
			TrainList[u8Cycle] = TrainList[u8Cycle - 1U];
		}
		/*- 插入列车 */
		TrainList[u8InsertIndex].u16TrainID = u16TrainID;
		TrainList[u8InsertIndex].u8TrainType = u8TrainType;
		TrainList[u8InsertIndex].u16ELID = u16ELID;
		(*pu8TrainNum)++;
	}
	else
	{
		debug_infor_printf((const)"AS0027:When Index [%d/%d] insert Train[%d,%d], The number of trains overflowed \n", u8InsertIndex, *pu8TrainNum, u16TrainID, u8TrainType);
		/*- 不可达分支 */
		for (u8Cycle = DEFAULT_ZERO; u8Cycle < *pu8TrainNum; u8Cycle++)
		{
			debug_infor_printf((const) "[%d,%d]", TrainList[u8Cycle].u16TrainID, TrainList[u8Cycle].u8TrainType);
		}
		debug_infor_printf((const) "\n");
	}
}

/*****************************************************************************
* @name        CalcTrainOrder
* @brief       计算两列车的相对位置
* @param[in]   u16Train1 列车1ID
* @param[in]   u16Train2 列车2ID
* @param[in]   u16LinkID 需要映射的link
* @return
*     AS_ORDER_DOWNSTREAM (0x55) [T1][T2]=0x55代表T1<-T2
*     AS_ORDER_UPSTREAM   (0xAA) [T1][T2]=0xAA代表T1->T2
*     AS_ORDER_FAIL       (0xFF) 计算失败
* @note        无
*****************************************************************************/
static UINT8 CalcTrainOrder(IN UINT16 u16Train1, IN UINT16 u16Train2, UINT16 u16LinkID)
{
	UINT8 u8Ret = AS_ORDER_FAIL;      /* 函数返回值 */
	UINT8 u8HeadSort = DEFAULT_ZERO;  /* 车头次序 */
	UINT8 u8TailSort = DEFAULT_ZERO;  /* 车尾次序 */
	UINT16 u16T1Index = DEFAULT_ZERO; /* 列车1在通信车序列中的索引 */
	UINT16 u16T2Index = DEFAULT_ZERO; /* 列车2在通信车序列中的索引 */
	LOD_STRU T1StartPos = {0u};       /* 列车1起点 */
	LOD_STRU T1EndPos = { 0u };       /* 列车1终点 */
	LOD_STRU T2StartPos = { 0u } ;    /* 列车2起点 */
	LOD_STRU T2EndPos = { 0u };       /* 列车2终点 */

	LOD_STRU tempPos = { 0u };    /* 临时变量 */

	u16T1Index = s_pCTSortIndex[u16Train1];
	u16T2Index = s_pCTSortIndex[u16Train2];

	/*- 两列车的通信车序列是否存在 */
	if ((DEFAULT_ZERO != u16T1Index) && (DEFAULT_ZERO != u16T2Index) && (DEFAULT_ZERO != u16LinkID))
	{
		T1StartPos = s_pCTSortInfo[u16T1Index].SafeTail;
		T1EndPos = s_pCTSortInfo[u16T1Index].SafeHead;
		/*根据本车的运行方向来选择始端和终端，判断两个列车运行方向是否同向*/
		u8Ret = IsPointABSameDir(s_pCTSortInfo[u16T1Index].SafeHead, s_pCTSortInfo[u16T2Index].SafeTail);
		if (FLAG_SET == u8Ret)
		{
			/*同向*/
			T2StartPos = s_pCTSortInfo[u16T2Index].SafeTail;
			T2EndPos = s_pCTSortInfo[u16T2Index].SafeHead;
		}
		else if (FLAG_UNSET == u8Ret)
		{
			/*反向*/
			T2StartPos = s_pCTSortInfo[u16T2Index].SafeHead;
			T2EndPos = s_pCTSortInfo[u16T2Index].SafeTail;
		}
		else
		{
			u8Ret = AS_ORDER_FAIL;
		}

		if (AS_ORDER_FAIL != u8Ret)
		{
			/**获取两个点的前后位置关系****************/
			/*0x00U：查询失败；0x01U：沿着1方向，1点在后方；0x02U：沿着1的方向，1点在前方；0x03U：重合*/
			u8HeadSort = LinkManage_CheckSortTrainExp(T1StartPos.Lnk, T1StartPos.Off, T2StartPos.Lnk, T2StartPos.Off, T1StartPos.Dir);
			u8TailSort = LinkManage_CheckSortTrainExp(T1EndPos.Lnk, T1EndPos.Off,T2EndPos.Lnk, T2EndPos.Off, T1EndPos.Dir);

			tempPos.Lnk = u16LinkID;
			tempPos.Off = 1;  /*赋值为1cm*/
			tempPos.Dir = EMAP_SAME_DIR;

			/*查询两点之间是否同向，看基于1车的方向和待映射的link是否同向*/
			u8Ret = IsPointABSameDir(T1EndPos, tempPos);

			/*- 1车是否在2车下游 */
			if ((0x01U == u8HeadSort) && (0x01U == u8TailSort) && (CI_ERROR != u8Ret))
			{
				/*- 输出1车在上游 (0-max,在0处)*/
				if (FLAG_SET == u8Ret)
				{
					u8Ret = AS_ORDER_UPSTREAM;
				}
				else
				{
					u8Ret = AS_ORDER_DOWNSTREAM;
				}
				
			}
			/*- 1车是否在2车上游(0-max,在max处) */
			else if ((0x02U == u8HeadSort) && (0x02U == u8TailSort) && (CI_ERROR != u8Ret))
			{
				/*- 输出1车在下游 */
				
				if (FLAG_SET == u8Ret)
				{
					u8Ret = AS_ORDER_DOWNSTREAM;
				}
				else
				{
					u8Ret = AS_ORDER_UPSTREAM;
				}
			}
			else
			{
				/*- 查询失败(两列车互相不可达?) */
				debug_infor_printf((const)"AS0024: Get relative position error, Result:[%d,%d],[%d Train][%d,%d]~[%d,%d],[%d Train][%d,%d]~[%d,%d]\n", u8HeadSort, u8TailSort,
					u16Train1, s_pCTSortInfo[u16T1Index].SafeHead.Lnk, s_pCTSortInfo[u16T1Index].SafeHead.Off,
					s_pCTSortInfo[u16T1Index].SafeTail.Lnk, s_pCTSortInfo[u16T1Index].SafeTail.Off,
					u16Train2, s_pCTSortInfo[u16T2Index].SafeHead.Lnk, s_pCTSortInfo[u16T2Index].SafeHead.Off,
					s_pCTSortInfo[u16T2Index].SafeTail.Lnk, s_pCTSortInfo[u16T2Index].SafeTail.Off);
				u8Ret = AS_ORDER_FAIL;
			}

		}

	}
	else
	{
		/*- 不可达分支 */
		debug_infor_printf((const) "AS0025: Get relative position error, Train don't exist[%d,%d],[%d,%d]\n", u16Train1, u16T1Index, u16Train2, u16T2Index);
		u8Ret = AS_ORDER_FAIL;
	}

	return u8Ret;
}

/*****************************************************************************
* @name        TrainAddSuspectLeft
* @brief       列车可疑左端添加故障车
* @param[in]   u16TrainID 列车ID
* @param[in]   u16LinkID 待插入LINK ID
* @return      无
* @note        无
*****************************************************************************/
static void TrainAddSuspectLeft(UINT16 u16TrainID, UINT16 u16LinkID)
{
	UINT8 u8SeqIndex = DEFAULT_ZERO;     /* 排序数组索引 */
	UINT16 u16LinkIndex = DEFAULT_ZERO;  /* Link序列索引 */

	/*- 初始化 */
	u16LinkIndex = g_pSortLinkIndex[u16LinkID];

	/*- Link是否在本ZC控区 */
	if (DEFAULT_ZERO != u16LinkIndex)
	{
		/*- 查找本列车在Link序列中的位置 */
		u8SeqIndex = as_SeqSearch(u16TrainID, g_pSortLinkInfo[u16LinkIndex].u8TrainNum, g_pSortLinkInfo[u16LinkIndex].TrainList);
		/*- Link是否排序异常 */
		if (FLAG_SET == g_pSortLinkInfo[u16LinkIndex].u8SortFail)
		{
			debug_infor_printf((const) "AS0014:At abnormal Link[%d], train[%d] Try to add Leftsuspicious Train\n", u16LinkID, u16TrainID);
		}
		/*- 是否查找失败*/
		else if (INVALID_8 == u8SeqIndex)
		{
			/* 增加列车失败，参数为LINK ID和列车ID */
			debug_infor_printf((const)"AS0015:[%d Train] At Link[%d]Add Leftsuspicious Train failed,(Axle sequence Error[%d])\n",
				u16TrainID, u16LinkID, g_pSortLinkInfo[u16LinkIndex].u8TrainNum);
			/*- @alias 不可达分支 */
			for (u8SeqIndex = DEFAULT_ZERO; u8SeqIndex < g_pSortLinkInfo[u16LinkIndex].u8TrainNum; u8SeqIndex++)
			{
				debug_infor_printf((const) "[%d,%d]",
					g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u8TrainType);
			}
			debug_infor_printf((const) "\n");
		}
		/*- 车头方向是否已经有故障车 */
		else if ((DEFAULT_ZERO < u8SeqIndex) && (TYPE_FAILURE == g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex - 1U].u8TrainType))
		{
			/*- 不再重复添加 */
			debug_infor_printf((const)"AS0016:[%d Train] At Link[%d] left have UT Train[%d,%d], No more additions\n",
				u16TrainID, u16LinkID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex - 1U].u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex - 1U].u8TrainType);
		}
		/*- 计轴序列是否已满 */
		else if (SIZE_MAX_TRAINOFAC <= g_pSortLinkInfo[u16LinkIndex].u8TrainNum)
		{
			/* 增加列车失败，参数为LINK ID和列车ID */
			g_pSortLinkInfo[u16LinkIndex].u8SortFail = FLAG_SET;
			debug_infor_printf((const) "AS0017:[%d Train] At Link[%d] Add Leftsuspicious Train Failed, too many trains [%d] in Link\n", u16TrainID, u16LinkID, g_pSortLinkInfo[u16LinkIndex].u8TrainNum);
			/*- @alias 置计轴排序异常 */
			for (u8SeqIndex = DEFAULT_ZERO; u8SeqIndex < g_pSortLinkInfo[u16LinkIndex].u8TrainNum; u8SeqIndex++)
			{
				debug_infor_printf((const)"[%d,%d]",
					g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u8TrainType);
			}
		}
		else
		{
			/*- 添加故障车 */
			debug_infor_printf((const) "AS0018:[%d Train] At Link[%d][%d/%d] Add Leftsuspicious Train\n", u16TrainID, u16LinkID, u8SeqIndex, g_pSortLinkInfo[u16LinkIndex].u8TrainNum);
			SeqInsert(NAME_FAILUREAREA, TYPE_FAILURE,0, &g_pSortLinkInfo[u16LinkIndex].u8TrainNum, g_pSortLinkInfo[u16LinkIndex].TrainList, u8SeqIndex);
		}
	}
	else
	{
		;
	}

}

/*****************************************************************************
* @name        TrainAddSuspectRight
* @brief       列车可疑右端添加故障车
* @param[in]   u16TrainID 列车ID
* @param[in]   u16LinkID 待插入LINK ID
* @return      无
* @note        无
*****************************************************************************/
static void TrainAddSuspectRight(UINT16 u16TrainID, UINT16 u16LinkID)
{
	UINT8 u8SeqIndex = DEFAULT_ZERO;     /* 排序数组索引 */
	UINT16 u16LinkIndex = DEFAULT_ZERO;  /* 计轴序列索引 */

	/*- 初始化 */
	u16LinkIndex = g_pSortLinkIndex[u16LinkID];

	/*- Link是否在本ZC控区 */
	if (DEFAULT_ZERO != u16LinkIndex)
	{
		/*- 查找本列车在Link序列中的位置 */
		u8SeqIndex = as_SeqSearch(u16TrainID, g_pSortLinkInfo[u16LinkIndex].u8TrainNum, g_pSortLinkInfo[u16LinkIndex].TrainList);
		/*- Link是否排序异常 */
		if (FLAG_SET == g_pSortLinkInfo[u16LinkIndex].u8SortFail)
		{
			debug_infor_printf((const) "AS0019:At Abnormal Link[%d],  Train[%d] Try to Add Rightsuspicious Train\n", u16LinkID, u16TrainID);
		}
		/*- 是否查找失败*/
		else if (INVALID_8 == u8SeqIndex)
		{
			debug_infor_printf((const) "AS0020:[%d Train] At Link[%d] Add Leftsuspicious Train Failed (Axle sequence Error[%d])\n",
				u16TrainID, u16LinkID, g_pSortLinkInfo[u16LinkIndex].u8TrainNum);
			/*- 不可达分支 */
			for (u8SeqIndex = DEFAULT_ZERO; u8SeqIndex < g_pSortLinkInfo[u16LinkIndex].u8TrainNum; u8SeqIndex++)
			{
				debug_infor_printf((const)"[%d,%d]",
					g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u8TrainType);
			}
		}
		/*- 车尾方向是否已经有故障车 */
		else if (((u8SeqIndex + 1U) < g_pSortLinkInfo[u16LinkIndex].u8TrainNum) && (TYPE_FAILURE == g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex + 1U].u8TrainType))
		{
			/*- 不再重复添加 */
			debug_infor_printf((const) "AS0021:[%d Train]At Link[%d] Right have UT Train[%d,%d], No more additions\n",
				u16TrainID, u16LinkID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex + 1U].u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex + 1U].u8TrainType);
		}
		/*- Link序列是否已满 */
		else if (SIZE_MAX_TRAINOFAC <= g_pSortLinkInfo[u16LinkIndex].u8TrainNum)
		{
			g_pSortLinkInfo[u16LinkIndex].u8SortFail = FLAG_SET;
			debug_infor_printf((const)"AS0022:[%d Train] At Link[%d] Add Rightsuspicious Train Failed, too much trains[%d] in Link\n", u16TrainID, u16LinkID, g_pSortLinkInfo[u16LinkIndex].u8TrainNum);
			/*- @alias 置Link排序异常 */
			for (u8SeqIndex = DEFAULT_ZERO; u8SeqIndex < g_pSortLinkInfo[u16LinkIndex].u8TrainNum; u8SeqIndex++)
			{
				debug_infor_printf((const) "[%d,%d]",
					g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u16TrainID, g_pSortLinkInfo[u16LinkIndex].TrainList[u8SeqIndex].u8TrainType);
			}
		}
		else
		{
			/*- 添加故障车 */
			debug_infor_printf((const)"AS0023:[%d Train] At Link[%d][%d/%d] Add Rightsuspicious Train\n", u16TrainID, u16LinkID, u8SeqIndex + 1U, g_pSortLinkInfo[u16LinkIndex].u8TrainNum);
			SeqInsert(NAME_FAILUREAREA, TYPE_FAILURE, 0,&g_pSortLinkInfo[u16LinkIndex].u8TrainNum, g_pSortLinkInfo[u16LinkIndex].TrainList, u8SeqIndex + 1U);
		}
	}
	else
	{
		/*none*/
	}
}


/*****************************************************************************
* @name        CalcEnveLopeOrderInAC
* @brief       计算两个包络的相对位置,同时落到计轴上
* @param[in]   p1 包络1
* @param[in]   p2 包络2
* @param[in]   u16ACID
* @return
*     AS_ORDER_DOWNSTREAM (0x55) 0x55代表p1->p2
*     AS_ORDER_UPSTREAM   (0xAA) 0xAA代表p1<-p2
*     AS_ORDER_FAIL       (0xFF) 计算失败
* @note        无
*****************************************************************************/
static UINT8 CalcEnveLopeOrderInAC(IN const EnvelopeStruct* p1, IN const EnvelopeStruct* p2, UINT16 u16ACID)
{
	UINT8 u8Ret = AS_ORDER_FAIL;      /* 函数返回值 */
	UINT8 u8HeadSort = DEFAULT_ZERO;  /* 车头次序 */
	UINT8 u8TailSort = DEFAULT_ZERO;  /* 车尾次序 */
	UINT16 * pAcLinkId = NULL;		  /* 计轴区段包含的link序列 */
	LOD_STRU E1StartPos = { 0u };     /* 包络1起点 */
	LOD_STRU E1EndPos = { 0u };       /* 包络1终点 */
	LOD_STRU E2StartPos = { 0u };     /* 包络2起点 */
	LOD_STRU E2EndPos = { 0u };       /* 包络2终点 */
	LOD_STRU tempPos = { 0u };

	pAcLinkId = GetAxisLinkIdBuf(u16ACID);

	if ((NULL == p1) || (NULL == p2) || (NULL == pAcLinkId))
	{
		;/*参数错误*/
	}
	else
	{
		tempPos.Lnk = pAcLinkId[0];
		tempPos.Off = 1u;  /*赋值为1cm*/
		tempPos.Dir = EMAP_SAME_DIR;

		E1StartPos = p1->endPos;
		E1EndPos = p1->startPos;

		/*判断两个包络是否同向，另外需要确认下故障车包络也需要方向正确，不一定准但是给的方向基于点要对*/
		u8Ret = IsPointABSameDir(p1->startPos, p2->endPos);
		if (CI_ERROR != u8Ret)
		{
			if (FLAG_SET == u8Ret)
			{
				/*同向*/
				E2StartPos = p2->endPos;
				E2EndPos = p2->startPos;
			}
			else
			{
				/*反向*/
				E2StartPos = p2->startPos;
				E2EndPos = p2->endPos;
			}

			/**获取两个点的前后位置关系****************/
			/*0x00U：查询失败；0x01U：第一点位置在后方；0x02U：第二点位置在后方；0x03U：两个参数所标识的点位置重合*/
			u8HeadSort = LinkManage_CheckSortTrainExp(E1StartPos.Lnk, E1StartPos.Off, E2StartPos.Lnk, E2StartPos.Off, E1StartPos.Dir);
			u8TailSort = LinkManage_CheckSortTrainExp(E1EndPos.Lnk, E1EndPos.Off, E2EndPos.Lnk, E2EndPos.Off, E1EndPos.Dir);

			/*查询两点之间是否同向，看基于1车的方向和待映射的计轴是否同向*/
			u8Ret = IsPointABSameDir(E1StartPos, tempPos);

			/*- 1车是否在2车下游 */
			if ((0x01U == u8HeadSort) && (0x01U == u8TailSort) && (CI_ERROR != u8Ret))
			{
				/*- 输出1车在上游 (0-max,在0处)*/
				if (FLAG_SET == u8Ret)
				{
					u8Ret = AS_ORDER_UPSTREAM;
				}
				else
				{
					u8Ret = AS_ORDER_DOWNSTREAM;
				}
			}
			/*- 1车是否在2车上游 */
			else if ((0x02U == u8HeadSort) && (0x02U == u8TailSort) && (CI_ERROR != u8Ret))
			{
				/*- 输出1车在下游 */

				if (FLAG_SET == u8Ret)
				{
					u8Ret = AS_ORDER_DOWNSTREAM;
				}
				else
				{
					u8Ret = AS_ORDER_UPSTREAM;
				}
			}
			else
			{
				
				u8Ret = AS_ORDER_FAIL;
				
				/*- 查询失败(两列车互相不可达?) */
				debug_infor_printf((const)"AS0040: Get relative position error, Result[%d,%d],[%d Train, ELid:%d][%d,%d]~[%d,%d],[%d Train,ELid:%d][%d,%d]~[%d,%d]\n", u8HeadSort, u8TailSort,
					p1->trainID[0], p1->id, E1StartPos.Lnk, E1StartPos.Off, E1EndPos.Lnk, E1EndPos.Off,
					p2->trainID[0], p2->id, E2StartPos.Lnk, E2StartPos.Off, E2EndPos.Lnk, E2EndPos.Off);
			}
		}
		else
		{
			u8Ret = AS_ORDER_FAIL;
		}
	}
	return u8Ret;
}

/*****************************************************************************
* @name        CalcEnveLopeOrder
* @brief       计算两个包络的相对位置
* @param[in]   p1 包络1
* @param[in]   p2 包络2
* @return
*     AS_ORDER_DOWNSTREAM (0x55) 0x55代表p1->p2
*     AS_ORDER_UPSTREAM   (0xAA) 0xAA代表p1<-p2
*     AS_ORDER_1INCLUDE2   p1包含p2，包括(()  ),(   ())，(  ()  )
*     AS_ORDER_2INCLUDE1   p2包含p1，包括(()  ),(   ())，(  ()  )
*     AS_ORDER_FAIL       (0xFF) 计算失败
* @note        无
*****************************************************************************/
static UINT8 CalcEnveLopeOrder(IN const EnvelopeStruct* p1, IN const EnvelopeStruct* p2)
{
	UINT8 u8Ret = AS_ORDER_FAIL;      /* 函数返回值 */
	UINT8 u8HeadSort = DEFAULT_ZERO;  /* 车头次序 */
	UINT8 u8TailSort = DEFAULT_ZERO;  /* 车尾次序 */
	UINT16 * pAcLinkId = NULL;		  /* 计轴区段包含的link序列 */
	LOD_STRU E1StartPos = { 0u };     /* 包络1起点 */
	LOD_STRU E1EndPos = { 0u };       /* 包络1终点 */
	LOD_STRU E2StartPos = { 0u };     /* 包络2起点 */
	LOD_STRU E2EndPos = { 0u };       /* 包络2终点 */
	LOD_STRU tempPos = { 0u };

	if ((NULL == p1) || (NULL == p2))
	{
		;/*参数错误*/
	}
	else
	{
		E1StartPos = p1->endPos;
		E1EndPos = p1->startPos;

		/*判断两个包络是否同向，另外需要确认下故障车包络也需要方向正确，不一定准但是给的方向基于点要对*/
		u8Ret = IsPointABSameDir(p1->startPos, p2->endPos);
		if (CI_ERROR != u8Ret)
		{
			if (FLAG_SET == u8Ret)
			{
				/*同向*/
				E2StartPos = p2->endPos;
				E2EndPos = p2->startPos;
			}
			else
			{
				/*反向*/
				E2StartPos = p2->startPos;
				E2EndPos = p2->endPos;
			}

			/**获取两个点的前后位置关系****************/
			/*0x00U：查询失败；0x01U：第一点位置在后方；0x02U：第二点位置在后方；0x03U：两个参数所标识的点位置重合*/
			u8HeadSort = LinkManage_CheckSortTrainExp(E1StartPos.Lnk, E1StartPos.Off, E2StartPos.Lnk, E2StartPos.Off, E1StartPos.Dir);
			u8TailSort = LinkManage_CheckSortTrainExp(E1EndPos.Lnk, E1EndPos.Off, E2EndPos.Lnk, E2EndPos.Off, E1EndPos.Dir);

			if ((0x01U == u8HeadSort) && (0x01U == u8TailSort))
			{
				u8Ret = AS_ORDER_DOWNSTREAM;  /*p1->p2*/
			}
			else if ((0x02U == u8HeadSort) && (0x02U == u8TailSort) )
			{
				u8Ret = AS_ORDER_UPSTREAM;  /*p1<-p2*/
			}
			else
			{
				if (((0x01U == u8HeadSort) && (0x03U == u8TailSort))
					|| (((0x03U == u8HeadSort) && (0x01U == u8TailSort)))
					|| (((0x01U == u8HeadSort) && (0x02U == u8TailSort))))
				{
					u8Ret = AS_ORDER_1INCLUDE2; /*1在外*/
				}
				else if (((0x02U == u8HeadSort) && (0x03U == u8TailSort))
					|| (((0x03U == u8HeadSort) && (0x02U == u8TailSort)))
					|| (((0x02U == u8HeadSort) && (0x01U == u8TailSort))))
				{
					u8Ret = AS_ORDER_2INCLUDE1; /*p1在内*/
				}
				else
				{
					u8Ret = AS_ORDER_FAIL;
				}
				/*- 查询失败(两列车互相不可达?) */
				debug_infor_printf((const)"AS0040: Get relative position error, Result[%d,%d],[%d Train,ELid:%d][%d,%d]~[%d,%d],[%d Train,ELid:%d][%d,%d]~[%d,%d]\n", u8HeadSort, u8TailSort,
					p1->trainID[0], p1->id, E1StartPos.Lnk, E1StartPos.Off, E1EndPos.Lnk, E1EndPos.Off,
					p2->trainID[0], p2->id, E2StartPos.Lnk, E2StartPos.Off, E2EndPos.Lnk, E2EndPos.Off);
			}
		}
		else
		{
			u8Ret = AS_ORDER_FAIL;
		}
	}
	return u8Ret;
}


void as_SortBaseEnveLope(void)
{
	/*对所有的CT列车包络信息进行排序，并落到计轴上*/
	SortAllEnveLopeInAC();
}

/*****************************************************************************
* @name        SortAllEnveLopeInAC
* @brief       从列车包络模块获取根据所有的包络，对elm发来的CT包络进行排序，且落到AC上
* @param[in]   无
* @return      无
* @note        根据包络管理模块提供的所有CT包络，给每个计轴上的包络排序
*               注意只对CT包络进行了排序，对前后端筛选无效的未做处理。
*               主要提供给区段状态设置模块用
*
*****************************************************************************/
static void SortAllEnveLopeInAC(void)
{
	UINT16 ELIndex = DEFAULT_ZERO;   /*包络索引 */
	UINT8  ACNum = DEFAULT_ZERO;     /*某个包络的AC数*/
	UINT8 u8Index = DEFAULT_ZERO;       /*AC 索引*/

	UINT16 ACList[AS_AC_MAX] = { 0U };    /* Link列表 */
	const EnvelopeStruct* pEnvelope = NULL;

	/*获取所有的列车包络*/
	for (ELIndex = 0U; ELIndex < s_TrainELSeq.ELNum; ELIndex++)
	{
		/*获取包络*/
		pEnvelope = elm_GetEnvelopeInfoByID(s_TrainELSeq.TrainEnveLopeID[ELIndex]);
		if (NULL != pEnvelope)
		{
			if (TYPE_CT == pEnvelope->envelopeType)
			{
				/*列车包络内的Link序列初始值置0; 是否尾部? ; 索引递增*/
				for (u8Index = 0U; u8Index < pEnvelope->ACCnt; u8Index++)
				{
					/*- AC添加列车 */
					ACAddEnvelope(pEnvelope->ACID[u8Index], pEnvelope, s_TrainELSeq.TrainEnveLopeID[ELIndex]);
				}
			}
			else
			{
				; /*计轴只处理CT车的排序*/
			}
			
		}
	}
}

/*****************************************************************************
* @name        ACAddEnvelope
* @brief       计轴区段根据包络添加车序
* @param[in]   u16ACID： AC ID
* @param[in]   pEnvelope   列车包络
* @param[in]   u16ELID     包络ID
* @return      无
* @note       
*****************************************************************************/
static void ACAddEnvelope(IN UINT16 u16ACID, IN const EnvelopeStruct *pEnvelope,IN UINT16 u16ELID)
{
	UINT8 u8Order = DEFAULT_ZERO;       /* 相对位置 */
	UINT8 u8Index = DEFAULT_ZERO;       /* 循环变量 */
	UINT8 u8Ret = DEFAULT_ZERO;         /* 返回值 */
	UINT16 ACIndex = DEFAULT_ZERO;   /* link序列索引 */
	const EnvelopeStruct* pEL = NULL;
	
	/*- 初始化 */
	ACIndex = g_pSortACIndex[u16ACID];
	/*- 是否是本控区的AC */
	if (DEFAULT_ZERO != ACIndex)
	{
		/*- AC排序是否有异常 */
		if (FLAG_SET == g_pSortACInfo[ACIndex].u8SortFail)
		{
			debug_infor_printf((const) "AS0041:try to at abnormal AC[%d] add Train[%d]\n", u16ACID, pEnvelope->trainID[0]);
		}
		/*- AC列车序列是否为空 */
		else if (DEFAULT_ZERO == g_pSortACInfo[ACIndex].u8TrainNum)
		{
			debug_infor_printf((const)"AS0042:AC[%d] add first Train[%d]\n", u16ACID, pEnvelope->trainID[0], pEnvelope->envelopeType);
			g_pSortACInfo[ACIndex].TrainList[0].u16TrainID = pEnvelope->trainID[0];
			g_pSortACInfo[ACIndex].TrainList[0].u8TrainType = pEnvelope->envelopeType;
			g_pSortACInfo[ACIndex].TrainList[0].u16ELID = u16ELID; /*u16ELID ==pEnvelope->id*/
			g_pSortACInfo[ACIndex].u8TrainNum = 1U;
		}
		/*- AC序列是否已满 */
		else if (SIZE_MAX_TRAINOFAC <= g_pSortACInfo[ACIndex].u8TrainNum)
		{
			g_pSortACInfo[ACIndex].u8SortFail = FLAG_SET;
			debug_infor_printf((const) "AS0043:AC[%d]have too many trains [%d]\n", u16ACID, g_pSortACInfo[ACIndex].u8TrainNum);
			/*- @alias AC序列上列车数量过多，置排序异常 */
			for (u8Index = 0U; u8Index < g_pSortACInfo[ACIndex].u8TrainNum; u8Index++)
			{
				debug_infor_printf((const)"[%d,%d]",
					g_pSortACInfo[ACIndex].TrainList[u8Index].u16TrainID,
					g_pSortACInfo[ACIndex].TrainList[u8Index].u8TrainType);
			}
			debug_infor_printf((const) "\n");
		}
		else
		{
			for (u8Index = 0U; u8Index < g_pSortACInfo[ACIndex].u8TrainNum; u8Index++)
			{
				pEL = elm_GetEnvelopeInfoByID(g_pSortACInfo[ACIndex].TrainList[u8Index].u16ELID);	
				if (NULL != pEL)
				{
					u8Order = CalcEnveLopeOrderInAC(pEnvelope, pEL, u16ACID);

					/*- 新车是否在该车下游 */
					if (AS_ORDER_DOWNSTREAM == u8Order)
					{
						/*- 新车在该车下游，继续遍历 */
					}
					else
					{
						/*- 新车是否在该车上游 */
						if (AS_ORDER_UPSTREAM == u8Order)
						{
							/*- 新车在该车上游，找到插入位置，循环正常退出 */
						}
						else
						{
							/*- 置排序异常，循环异常退出 */
							g_pSortACInfo[ACIndex].u8SortFail = FLAG_SET;
							debug_infor_printf((const) "AS1044:AC[%d]排序异常:计算相对位置失败[%d车][%d车]\n",
								u16ACID, pEnvelope->trainID[0], g_pSortACInfo[ACIndex].TrainList[u8Index].u16TrainID);

						}
						/* 只要新车不在该车下游，就都结束循环，下面再根据是否发生排序异常决定是否加入序列 */
						/*- 循环退出 */
						break;
					}
				}
				else
				{
					;
				}
			}
			/*
			* 找到了插入位置时在插入位置插入，
			* 没找到插入位置时说明新车在最后，在序列末尾插入
			*/
			/*- 排序是否正常 */
			if (FLAG_UNSET == g_pSortACInfo[ACIndex].u8SortFail)
			{
				/*- AC序列插入列车 */
				debug_infor_printf((const) "AS1045:AC[%d]在[%d/%d]插入列车[%d,%d]\n",
					u16ACID, u8Index, g_pSortACInfo[ACIndex].u8TrainNum, pEnvelope->trainID[0], pEnvelope->envelopeType);
				SeqInsert(pEnvelope->trainID[0], pEnvelope->envelopeType, pEnvelope->id, &g_pSortACInfo[ACIndex].u8TrainNum, g_pSortACInfo[ACIndex].TrainList, u8Index);
			}
			else
			{
				;
			}
		}
	}
	else
	{
		;
	}
}

/*****************************************************************************
* @name        as_GetLinkFirstTrain
* @brief       获取Link上第一列车的信息
* @param[in]   u16LinkID LinkID
* @return      第一列车的列车序列信息
* @note        第一列车指电子地图方向起点端列车
*              Link不在本ZC控区/Link排序异常/Link无车时，调用本函数将返回一个故障车
*              和as_GetLinkTrainNum()结合使用
*****************************************************************************/
TRAIN_SEQUANCE_s as_GetLinkFirstTrain(IN UINT16 u16LinkID)
{
	TRAIN_SEQUANCE_s TrainSeq = { NAME_FAILUREAREA, TYPE_FAILURE, DEFAULT_ZERO }; /* 列车序列 */

	/*- 是否是本ZC控区的排序正常的有车的Link */
	if ((DEFAULT_ZERO < g_pSortLinkIndex[u16LinkID])
		&& (FLAG_UNSET == g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8SortFail)
		&& (DEFAULT_ZERO < g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8TrainNum))
	{
		/*- 输出Link序列首列车*/
		TrainSeq = g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].TrainList[0];
	}
	else
	{
		/*- 输出一个故障车 */
		TrainSeq.u16TrainID = NAME_FAILUREAREA;
		TrainSeq.u8TrainType = TYPE_FAILURE;
		TrainSeq.u16ELID = DEFAULT_ZERO;
	}
	return TrainSeq;
}

/*****************************************************************************
* @name        as_GetLinkLastTrain
* @brief       获取Link上最后一列车的信息
* @param[in]   u16LinkID LinkID
* @return      最后一列车的列车序列信息
* @note        最后一列车指电子地图方向的终点端的列车
*              Link不在本ZC控区/Link排序异常/Link无车时，调用本函数将返回一个故障车
*              和as_GetLinkTrainNum()结合使用
*****************************************************************************/
TRAIN_SEQUANCE_s as_GetLinkLastTrain(IN UINT16 u16LinkID)
{
	TRAIN_SEQUANCE_s TrainSeq = { NAME_FAILUREAREA, TYPE_FAILURE ,DEFAULT_ZERO }; /* 列车序列 */

	/*- 是否是本ZC控区的排序正常的有车的计轴 */
	if ((DEFAULT_ZERO < g_pSortLinkIndex[u16LinkID])
		&& (FLAG_UNSET == g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8SortFail)
		&& (DEFAULT_ZERO < g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8TrainNum))
	{
		/*- 输出计轴序列末列车*/
		TrainSeq = g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].TrainList[g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8TrainNum - 1U];
	}
	else
	{
		/*- 输出一个故障车 */
		TrainSeq.u16TrainID = NAME_FAILUREAREA;
		TrainSeq.u8TrainType = TYPE_FAILURE;
		TrainSeq.u16ELID = DEFAULT_ZERO;
	}
	return TrainSeq;
}

/*****************************************************************************
* @name        as_GetLinkTrainNum
* @brief       获取Link上的列车数量
* @param[in]   u16LinkID LinkID
* @return      列车数量
* @note        Link不在本ZC控区/Link排序异常时，函数将返回1(一个故障车)
*****************************************************************************/
UINT8 as_GetLinkTrainNum(IN UINT16 u16LinkID)
{
	UINT8 u8TrainNum = DEFAULT_ZERO; /* 列车数量 */

	/*- 是否是本ZC控区的排序正常的计轴 */
	if ((DEFAULT_ZERO < g_pSortLinkIndex[u16LinkID])
		&& (FLAG_UNSET == g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8SortFail))
	{
		/*- 输出列车序列数量 */
		u8TrainNum = g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8TrainNum;
	}
	else
	{
		/*- 输出一个(故障)车*/
		u8TrainNum = 1U;
	}
	return u8TrainNum;
}

/*****************************************************************************
* @name        as_GetLinkTrainList
* @brief       获取Link上的列车序列
* @param[in]   u16LinkID LinkID
* @param[out]  TrainList 列车序列
* @param[in]   u32MaxTrainNum 列车序列的数量上限
* @return      列车数量
* @note TrainList[]沿电子地图方向从起点向终点排列，即TrainList[0]是电子地图起点端列车
*       Link不在本ZC控区/Link排序异常/传入的列车序列空间过小时，函数将返回一个故障车
*****************************************************************************/
UINT8 as_GetLinkTrainList(IN UINT16 u16LinkID, OUT TRAIN_SEQUANCE_s TrainList[SIZE_MAX_TRAINOFAC], IN UINT32 u32MaxTrainNum)
{
	UINT8 u8TrainNum = DEFAULT_ZERO; /* 列车数量 */

	/*- 是否是本ZC控区的排序正常的Link且输入序列空间够大 */
	if ((DEFAULT_ZERO < g_pSortLinkIndex[u16LinkID])
		&& (FLAG_UNSET == g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8SortFail)
		&& (u32MaxTrainNum >= g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8TrainNum))
	{
		/*- 输出列车序列 */
		u8TrainNum = g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].u8TrainNum;
		(void)memmove(TrainList, g_pSortLinkInfo[g_pSortLinkIndex[u16LinkID]].TrainList, u8TrainNum * sizeof(TRAIN_SEQUANCE_s));
	}
	else
	{
		/*- 输出一个故障车 */
		u8TrainNum = 1U;
		TrainList[0].u16TrainID = NAME_FAILUREAREA;
		TrainList[0].u8TrainType = TYPE_FAILURE;
		TrainList[0].u16ELID = DEFAULT_ZERO;
	}
	return u8TrainNum;
}

/*****************************************************************************
* @name        as_SeqSearch
* @brief       列车序列搜索
* @param[in]   u16TrainID  列车ID
* @param[in]   u8TrainNum  列车序列数量
* @param[in]   TrainList   列车序列列表
* @return      正常：在列车序列中的角标，异常：INVALID_8
* @note        无
*****************************************************************************/
UINT8 as_SeqSearch(IN UINT16 u16TrainID, IN UINT8 u8TrainNum, IN const TRAIN_SEQUANCE_s TrainList[SIZE_MAX_TRAINOFAC])
{
	UINT8 u8Index = DEFAULT_ZERO; /* 循环变量 */
									 /*- @alias  遍历列车序列，找到目标列车时停止遍历*/
	for (u8Index = DEFAULT_ZERO; u8Index < u8TrainNum; u8Index++)
	{
		if (TrainList[u8Index].u16TrainID == u16TrainID)
		{
			break;
		}
		else
		{
			;
		}
	}

	/*- @alias 未能找到目标列车时返回INVALID_8 */
	if (u8Index >= u8TrainNum)
	{
		u8Index = INVALID_8;
	}
	else
	{
		;
	}
	return u8Index;
}


/*****************************************************************************
* @name        as_GetACTrainEnevelopList
* @brief       获取计轴上的包络序列
* @param[in]   u16ACID 计轴ID
* @param[out]  TrainList 列车序列
* @param[in]   u32MaxTrainNum 列车序列的数量上限
* @return      列车数量
* @note        TrainList[]沿电子地图方向从起点向终点排列，即TrainList[0]是电子地图起点端列车
*              计轴不在本ZC控区/计轴排序异常(有对向列车)/传入的列车序列空间过小时，函数将返回1个故障车
*              注意：AC上的序列只针对包络排序，不包括ct车头尾筛选无效的隐藏车
*****************************************************************************************/
UINT8 as_GetACTrainEnevelopList(UINT16 u16ACID, TRAIN_SEQUANCE_s TrainList[], UINT32 u32MaxTrainNum)
{
	UINT8 u8TrainNum = DEFAULT_ZERO; /* 列车数量 */

	/*是否是本ZC控区的排序正常的计轴且输入序列空间够大 */
	if ((DEFAULT_ZERO < g_pSortACIndex[u16ACID])
		&& (FLAG_UNSET == g_pSortACInfo[g_pSortACIndex[u16ACID]].u8SortFail)
		&& (u32MaxTrainNum >= g_pSortACInfo[g_pSortACIndex[u16ACID]].u8TrainNum))
	{
		/*- 输出列车序列 */
		u8TrainNum = g_pSortACInfo[g_pSortACIndex[u16ACID]].u8TrainNum;
		(void)memmove(TrainList, g_pSortACInfo[g_pSortACIndex[u16ACID]].TrainList, u8TrainNum * sizeof(TRAIN_SEQUANCE_s));
	}
	else
	{
		/*- 输出1个故障列车*/
		u8TrainNum = 1U;
		TrainList[0].u16TrainID = NAME_FAILUREAREA;
		TrainList[0].u8TrainType = TYPE_FAILURE;
		TrainList[0].u16ELID = DEFAULT_ZERO;
	}
	return u8TrainNum;
}


/**********************以下是从外部接口获取的数据******************************************/

/*****************************************************************************
* @name        TrainManage_GetTrainLocValid
* @brief       获取列车位置是否有效
* @param[in]   UINT16 TrainID
* @return      列车位置是否有效,通信车则返回FLAG_SET
* @note        从列车管理模块获取
*****************************************************************************/
UINT8 TrainManage_GetTrainLocValid(IN UINT16 TrainID)
{
	UINT8  u8Ret = FLAG_UNSET;
	UINT8 u8LocValid = DEFAULT_ZERO; 
	UINT8 u8TrainSlpStt = 0U;
	UINT16 u16IDIndex = DEFAULT_ZERO;

	/*从列车管理模块获取列车位置是否有效*/
	if (TrainID > DEFAULT_ZERO)
	{
		u16IDIndex = GetTrainId(TrainID - 1U);
		u8LocValid = GetTrainTransitmitStat(u16IDIndex);
		u8TrainSlpStt = GetTrainSleepState(u16IDIndex);
		if (TRAIN_COMM_STATE_GOOD == u8LocValid)
		{
			u8Ret = FLAG_SET;
		}
		else if((TRAIN_COMM_STATE_BAD == u8LocValid)
			&&(TRAIN_SLEEP_YES==u8TrainSlpStt))           
		{
			u8Ret = FLAG_SET;
		}
		else 
		{
			u8Ret = FLAG_UNSET;
		}
		
	}
	else
	{
		;/*无处理*/
	}
	return u8Ret;
}

/*****************************************************************************
* @name        TrainManage_GetTrainDir
* @brief       获取列车运行方向（最小安全后端指向车头）
* @param[in]   UINT16 TrainID
* @return     0: 获取数据失败
*			  0x55:与逻辑方向同向
*			  0xAA: 与逻辑方向反向
*			  0xFF: 无效
* @note        从列车管理模块获取
*****************************************************************************/
UINT8 TrainManage_GetTrainDir(IN UINT16 TrainID)
{
	UINT8 dir = DEFAULT_ZERO;
	UINT16 u16IDIndex = DEFAULT_ZERO;
	if (TrainID > DEFAULT_ZERO)
	{
		u16IDIndex = GetTrainId(TrainID - 1U);
		dir = GetTrainDir(u16IDIndex);
	}
	else
	{
		;
	}
	return dir;
}

/******************************************
* @name        TrainManage_GetTrainSafeLoc
* @brief       获取列车安全位置（即安全包络的前后端）
* @param[in]   要获取的安全位置类型 FINDHEADSAFEFLAG 安全车头 ；FINDTAILSAFEFLAG 安全车尾
* @param[in]   列车ID
* @param[out]  安全车头/车尾所处link
* @param[out]  安全车头/车尾所处偏移
* @return      查询成功；0 查询失败
* @note         从列车管理模块获取
******************************************/
UINT8 TrainManage_GetTrainSafeLoc(IN UINT8 u8SafelocType, IN UINT16 u16TrainID,OUT UINT16 *pu16Link, OUT UINT32 *pu32Offset, OUT UINT8 *pu8Dir)
{
	/*- 定义变量 */
	UINT8 u8RetVal = DEFAULT_ZERO;
	UINT16 u16IDIndex = DEFAULT_ZERO;

	if (u16TrainID > DEFAULT_ZERO)
	{
		u16IDIndex = GetTrainId(u16TrainID - 1U);
		/*- 判断要获取的安全位置类型*/
		switch (u8SafelocType)
		{
		case FINDHEADSAFEFLAG:
			/*- 赋值安全车头*/
			*pu16Link = GetTrainSafeHeadLink(u16IDIndex);
			*pu32Offset = GetTrainSafeHeadOffset(u16IDIndex);
			*pu8Dir = GetTrainSafeHeadDir(u16IDIndex);
			u8RetVal = DEFAULT_ONE;
			break;
		case FINDTAILSAFEFLAG:
			/*- 赋值安全车尾*/
			*pu16Link = GetTrainSafeTailLink(u16IDIndex);
			*pu32Offset = GetTrainSafeTailOffset(u16IDIndex);
			*pu8Dir = GetTrainSafeTailDir(u16IDIndex);
			u8RetVal = DEFAULT_ONE;
			break;
		default:
			/*- 查询失败*/
			u8RetVal = DEFAULT_ZERO;
			break;
		}
	}
	else
	{
		;
	}
	return u8RetVal;
}



/***********************************************
* @name         LinkManage_GetLinkInfoExp
* @brief        查询两点间Link序列
* @param[in]    pStart                         起点位置
* @param[in]    pEnd                           终点位置
* @param[in]    u8Direction                    查询方向
* @param[out]   pu16LinkID[MAX_LINK_LIST_NUM]       两点间Link序列，最大MAX_LINK_LIST_NUM
* @return       0：查询失败；返回查找到的link数目：查询成功
* @note         从link管理模块中获取
************************************************/
static UINT8 LinkManage_GetLinkInfoExp(LOD_STRU pStart, LOD_STRU pEnd, UINT8 u8Direction, UINT16 pu16LinkID[])
{
	UINT8 u8Ret = 0U;
	struct_PathPoint p1 = { 0U };
	struct_PathPoint p2 = { 0U };
	UINT8 Val = 0U;
	UINT8 dir = 0U;
	UINT16 linkNum = 0U;

	p1.dwOffset = pStart.Off;
	p1.wLinkId = pStart.Lnk;

	p2.dwOffset = pEnd.Off;
	p2.wLinkId = pEnd.Lnk;
	Val = DsuLinkSeqBtwPoints(&p1,&p2, &dir,&linkNum, pu16LinkID);
	if (CI_SUCCESS == Val)
	{
		u8Ret = (UINT8)linkNum;
	}
	else
	{
		;
	}
	return u8Ret;
}


/***********************************************
* @name         LinkManage_CheckSortTrainExp
* @brief        判断两点的前后顺序
* @param[in]    u16Link1                       第一个点所处link编号
* @param[in]    u32Offset1                     第一个点所处link偏移量
* @param[in]    u16Link2                       第二个点所处link编号
* @param[in]    u32Offset2                     第二个点尾所处link偏移量
* @param[in]    u8Direction                    列车运行方向
* @return       0x00U：查询失败；0x01U：沿着1方向，1->2,1点后方；0x02U：沿着1的方向，2->1, 1点前方；0x03U：两个参数所标识的点位置重合
* @note         从link管理模块获取
************************************************/
static UINT8 LinkManage_CheckSortTrainExp(UINT16 u16Link1, UINT32 u32Offset1, UINT16 u16Link2, UINT32 u32Offset2, UINT8 u8Direction)
{
	UINT8 Order = 0U;
	UINT8 RetVal = 0U;
	struct_PathPoint p1 = { 0U };
	struct_PathPoint p2 = { 0U };

	p1.dwOffset = u32Offset1;
	p1.wLinkId = u16Link1;

	p2.dwOffset = u32Offset2;
	p2.wLinkId = u16Link2;

	Order = dsuJudgePointAandPointBPosition(&p1, &p2, u8Direction);
	switch (Order)
	{
	case FLAG_SET:    /*沿着A的方向，A在后方*/
		RetVal = 0x01U;
		break;
	case FLAG_UNSET:  /*沿着A的方向，A在前方*/
		RetVal = 0x02U;
		break;
	case CI_SUCCESS:
		RetVal = 0x03U;/*重合*/  
		break;
	default:
		RetVal = 0x00U;
		break;
	}
	return RetVal;
}


/**
* @brief 比较两个包络的前后关系
* @param[in] const EnvelopeStruct* pEnvelopeA 包络A
* @param[in] const EnvelopeStruct* pEnvelopeB 包络B
* @return 0x01 包络A在B后
		  0x02 包络A在B前
		  0x03 A包含B
		  0x04 B包含A
		  0x00 无法比较位置关系
* @note 无
*/
UINT8 as_CalcEnvelopeOrder(IN const EnvelopeStruct* pEnvelopeA, IN const EnvelopeStruct* pEnvelopeB)
{
	UINT8 RetVal = DEFAULT_ZERO;

	if ((NULL != pEnvelopeA) &&  (NULL != pEnvelopeB))
	{

		RetVal = CalcEnveLopeOrder(pEnvelopeA, pEnvelopeB);
		switch (RetVal)
		{
		case AS_ORDER_UPSTREAM:    /*B->A*/ 
			RetVal = 0x02U;
			break;
		case AS_ORDER_DOWNSTREAM:
			RetVal = 0x01U;       /*A->B*/
			break;
		case AS_ORDER_1INCLUDE2:
			RetVal = 0x03U;       /*A包含B*/
			break;
		case AS_ORDER_2INCLUDE1:
			RetVal = 0x04U;       /*B包含A*/
			break;
		default:
			RetVal = DEFAULT_ZERO;
			break;
		}
	}
	else
	{
		;
	}
	return RetVal;
}

/*****************************************************************************
* @name        elm_GetAllTrainELSeq
* @brief       从筛选模块获取所有车的包络信息，放入s_TrainELSeq，本模块可以直接查询使用
* @param[in]   none
* @return      none
* @note        从列车筛选模块中获取
*****************************************************************************/
static void elm_GetAllTrainELSeq(void)
{
	UINT16 u16ELNum = DEFAULT_ZERO;

	/*每周期清*/
	(void)memset(&s_TrainELSeq, 0, sizeof(s_TrainELSeq));

	/*获取所有的列车包络*/
	u16ELNum = elm_GetAllEnvelope(s_TrainELSeq.TrainEnveLopeID);
	if (ENVELOPE_SUM_MAX >= u16ELNum)
	{
		s_TrainELSeq.ELNum = u16ELNum;
	}
	else
	{
		(void)memset(&s_TrainELSeq, 0, sizeof(s_TrainELSeq));
	}

}


/*****************************************************************************
* @name        elm_IsCTHeadUKT
* @brief       是否是CT车且车头有隐藏车UT
* @param[in]   u16TrainID 列车ID
* @return      CT车头是否有可疑UKT FLAG_SET:有,FLAG_UNSET:无
* @note        从列车筛选模块中获取
*****************************************************************************/
static UINT8 elm_IsCTHeadUKT(UINT16 u16TrainID)
{
	UINT8 u8Ret = FLAG_UNSET;
	UINT16 cycIndex = 0U;
	UINT16 Val = 0U;
	UINT8 u8HeadVirScreen = TRAIN_VIR_SCREEN_PASS_FLAG_INVALID;
	const EnvelopeStruct* pEnvelope = NULL;

	for (cycIndex = 0U; cycIndex < s_TrainELSeq.ELNum; cycIndex++)
	{
		/*获取包络*/
		pEnvelope = elm_GetEnvelopeInfoByID(s_TrainELSeq.TrainEnveLopeID[cycIndex]);
		if (NULL != pEnvelope)
		{
			/**在所有包络中根据ID查找CT车包络**/
			if ((TYPE_CT == pEnvelope->envelopeType) && (u16TrainID == pEnvelope->trainID[0]))
			{
				Val = pEnvelope->headTrainID;
				u8HeadVirScreen = GetTrainVirHeadScreenPassFlag(u16TrainID);
				break;
			}
			else
			{
				;
			}
		}
	}
	if ((DEFAULT_ZERO != Val) && (TRAIN_VIR_SCREEN_PASS_FLAG_VALID != u8HeadVirScreen))
	{
		u8Ret = FLAG_SET;
	}
	else
	{
		u8Ret = FLAG_UNSET;
	}

	/*- 返回头筛状态*/
	return u8Ret;
}


/*****************************************************************************
* @name        elm_IsCTTailUKT
* @brief       是否是CT车且车尾有隐藏车UT
* @param[in]   u16TrainID 列车ID
* @return      CT车尾是否有可疑UKT,FLAG_SET:有,FLAG_UNSET:无
* @note        无
*****************************************************************************/
static UINT8 elm_IsCTTailUKT(UINT16 u16TrainID)
{
	UINT8 u8Ret = FLAG_UNSET;
	UINT16 cycIndex = 0U;
	UINT16 Val = 0U;
	UINT8 u8TailVirScreen = TRAIN_VIR_SCREEN_PASS_FLAG_INVALID;
	const EnvelopeStruct* pEnvelope = NULL;

	for (cycIndex = 0U; cycIndex < s_TrainELSeq.ELNum; cycIndex++)
	{
		/*获取包络*/
		pEnvelope = elm_GetEnvelopeInfoByID(s_TrainELSeq.TrainEnveLopeID[cycIndex]);
		if (NULL != pEnvelope)
		{
			/**在所有包络中根据ID查找某个CT车包络**/
			if ((TYPE_CT == pEnvelope->envelopeType) && (u16TrainID == pEnvelope->trainID[0]))
			{
				Val = pEnvelope->tailTrainID;
				u8TailVirScreen = GetTrainVirTailScreenPassFlag(u16TrainID);
				break;
			}
			else
			{
				;
			}
		}
		else
		{
			;
		}
		
	}
	if ((DEFAULT_ZERO != Val) && (TRAIN_VIR_SCREEN_PASS_FLAG_VALID != u8TailVirScreen))
	{
		u8Ret = FLAG_SET; 
	}
	else
	{
		u8Ret = FLAG_UNSET; 
	}

	/*- 返回尾筛状态*/
	return u8Ret;
}

/*****************************************************************************
* @name        as_GetTrainsferData
* @brief       获取跟随数据
* @param[in]   UINT32 curIndex 当前索引
* @param[OUT]  UINT8 * pDataBuff 数据存储缓冲区
* @return      计算后的索引  ret>curIndex 获取成功
* @note        无
*****************************************************************************/
UINT32 as_GetTransferData(OUT UINT8 * pDataBuff, IN UINT32 curIndex)
{
	UINT32 ret = curIndex;
	UINT32 copyIndex = curIndex;
	UINT16 wLinkNum = 0U;
	UINT16 u16Index = 0U;
	UINT16 wTmpLinkId = 0U;
	UINT8 chLocalId = GetSystemParaLocalCiId();
	UINT8 chLinkCIId = 0U;/*link所属联锁*/
	UINT32 dwLinkNumIndex =0U;/*数量位置 */
	if (NULL != pDataBuff)
	{
		(void)CommonMemCpy(&pDataBuff[copyIndex], (UINT32)(sizeof(UINT16) * SIZE_MAX_LINE_TRAIN_NUM), s_pCTSortIndex, (UINT32)(sizeof(UINT16) * SIZE_MAX_LINE_TRAIN_NUM));
		copyIndex += (UINT32)(sizeof(UINT16) * SIZE_MAX_LINE_TRAIN_NUM);
		(void)CommonMemCpy(&pDataBuff[copyIndex], (UINT32)(sizeof(CT_SORT_INFO_s) * (SIZE_MAX_COM_VOBC_NUM + 1U)), s_pCTSortInfo, (UINT32)(sizeof(CT_SORT_INFO_s) * (SIZE_MAX_COM_VOBC_NUM + 1U)));
		copyIndex += (UINT32)(sizeof(CT_SORT_INFO_s) * (SIZE_MAX_COM_VOBC_NUM + 1U));
		/*拷贝link列车排序*/
		dwLinkNumIndex = copyIndex;
		copyIndex += 2U;
		for (u16Index = 1U; u16Index <= g_pSortLinkNum; u16Index++)
		{
			wTmpLinkId = g_pSortLinkInfo[u16Index].u16ID;
			chLinkCIId = (UINT8)GetLinkManageTiocById(wTmpLinkId);
			if ((0U != chLocalId) && (chLinkCIId == chLocalId))
			{
				/*仅拷贝本联锁*/
				(void)CommonMemCpy(&pDataBuff[copyIndex],(UINT32)(sizeof(AS_SORT_INFO_s)), &g_pSortLinkInfo[u16Index], (UINT32)(sizeof(AS_SORT_INFO_s)));
				copyIndex += (UINT32)(sizeof(AS_SORT_INFO_s));
				wLinkNum++;
			}
		}
		ShortToChar(wLinkNum, &pDataBuff[dwLinkNumIndex]); /* 写入有车占用的计轴区段数量 */
		ret = copyIndex;
	}
	else
	{
		;
	}
	return ret;
}

/*****************************************************************************
* @name        as_SetTrainsferData
* @brief       设置跟随数据
* @param[in]   UINT32 curIndex 当前索引
* @param[IN]   UINT8 * pDataBuff 数据存储缓冲区
* @return      计算后的索引  ret>curIndex 获取成功
* @note        无
*****************************************************************************/
UINT32 as_SetTransferData(IN UINT8 * pDataBuff, IN UINT32 curIndex)
{
	UINT32 ret = curIndex;
	UINT32 copyIndex = curIndex;
	UINT16 wLinkNum = 0U;
	UINT16 jj = 0U;
	UINT16 wTmpLinkId =0U;
	UINT16 wLinkIndex = 0U;
	if (NULL != pDataBuff)
	{
		(void)CommonMemCpy(s_pCTSortIndex, (UINT32)(sizeof(UINT16) * SIZE_MAX_LINE_TRAIN_NUM), &pDataBuff[copyIndex], (UINT32)(sizeof(UINT16) * SIZE_MAX_LINE_TRAIN_NUM));
		copyIndex += (UINT32)(sizeof(UINT16) * SIZE_MAX_LINE_TRAIN_NUM);
		(void)CommonMemCpy(s_pCTSortInfo, (UINT32)(sizeof(CT_SORT_INFO_s) * (SIZE_MAX_COM_VOBC_NUM + 1U)), &pDataBuff[copyIndex], (UINT32)(sizeof(CT_SORT_INFO_s) * (SIZE_MAX_COM_VOBC_NUM + 1U)));
		copyIndex += (UINT32)(sizeof(CT_SORT_INFO_s) * (SIZE_MAX_COM_VOBC_NUM + 1U));
		/*拷贝列车排序*/
		wLinkNum = ShortFromChar(&pDataBuff[copyIndex]);
		copyIndex += 2u;
		for (jj = 0U; jj < wLinkNum; jj++)
		{
			wTmpLinkId = ShortFromCharLE(&pDataBuff[copyIndex]);
			wLinkIndex = g_pSortLinkIndex[wTmpLinkId];
			if ((DEFAULT_ZERO < wLinkIndex) && (wLinkIndex < AS_LINK_MAX+1U))
			{			
				(void)CommonMemCpy(&g_pSortLinkInfo[wLinkIndex], (UINT32)(sizeof(AS_SORT_INFO_s)), &pDataBuff[copyIndex], (UINT32)(sizeof(AS_SORT_INFO_s)));
				copyIndex += (UINT32)(sizeof(AS_SORT_INFO_s));
			}
		}
		ret = copyIndex;
	}
	else
	{
		;
	}
	return ret;
}

/*****************************************************************************
* @name        CalcTrainOrder
* @brief       计算列车的相对位置
* @param[in]   p1 列车1
* @param[in]   p2 列车2
* @return
*     AS_ORDER_DOWNSTREAM (0x55) 0x55代表p1在p2运行方向下游(p2前)
*     AS_ORDER_UPSTREAM   (0xAA) 0xAA代表p1在p2运行方向上游(p1前)
*     AS_ORDER_FAIL       (0xFF) 计算失败
* @note        无
*****************************************************************************/
static UINT8 CalcAreaOrder(IN const TrainLocStruct* p1, IN const TrainLocStruct* p2)
{
	UINT8 u8Ret = AS_ORDER_FAIL;      /* 函数返回值 */
	UINT8 u8HeadSort = DEFAULT_ZERO;  /* 车头次序 */
	UINT8 u8TailSort = DEFAULT_ZERO;  /* 车尾次序 */
	LOD_STRU E1StartPos = { 0u };     /* 包络1起点 */
	LOD_STRU E1EndPos = { 0u };       /* 包络1终点 */
	LOD_STRU E2StartPos = { 0u };     /* 包络2起点 */
	LOD_STRU E2EndPos = { 0u };       /* 包络2终点 */

	if ((NULL == p1) || (NULL == p2))
	{
		;/*参数错误*/
	}
	else
	{
		/*- 包络1起终点取值 */
		if (EMAP_SAME_DIR == p1->startPos.Dir)
		{
			E1StartPos = p1->endPos;
			E1EndPos = p1->startPos;
		}
		else
		{
			E1StartPos = p1->startPos;
			E1EndPos = p1->endPos;
		}

		/*- 包络2起终点取值 */
		if (EMAP_SAME_DIR == p2->startPos.Dir)
		{
			E2StartPos = p2->endPos;
			E2EndPos = p2->startPos;
		}
		else
		{
			E2StartPos = p2->startPos;
			E2EndPos = p2->endPos;
		}

		/**获取两个点的前后位置关系****************/
		/*0x00U：查询失败；0x01U：第一点位置在前方；0x02U：第二点位置在前方；0x03U：两个参数所标识的点位置重合*/
		u8HeadSort = LinkManage_CheckSortTrainExp(E1StartPos.Lnk, E1StartPos.Off, E2StartPos.Lnk, E2StartPos.Off, EMAP_SAME_DIR);
		u8TailSort = LinkManage_CheckSortTrainExp(E2EndPos.Lnk, E2EndPos.Off, E1EndPos.Lnk, E1EndPos.Off, EMAP_SAME_DIR);

		/*- 1车是否在2车下游 */
		if ((0x01U == u8HeadSort) && (0x02U == u8TailSort))
		{
			/*- 输出1车在上游 */
			u8Ret = AS_ORDER_UPSTREAM;
		}
		/*- 1车是否在2车上游 */
		else if ((0x02U == u8HeadSort) && (0x01U == u8TailSort))
		{
			/*- 输出1车在下游 */
			u8Ret = AS_ORDER_DOWNSTREAM;
		}
		else
		{
			/*- 查询失败(两列车互相不可达?) */
			debug_infor_printf((const)"AS0044: Get relative position error, Result[%d,%d],[%d,%d]~[%d,%d],[%d,%d]~[%d,%d]\n", u8HeadSort, u8TailSort,
				E1StartPos.Lnk, E1StartPos.Off, E1EndPos.Lnk, E1EndPos.Off,
				E2StartPos.Lnk, E2StartPos.Off, E2EndPos.Lnk, E2EndPos.Off);
			u8Ret = AS_ORDER_FAIL;
		}

	}

	return u8Ret;
}

/**
* @brief 比较两个列车的前后关系
* @param[in] const EnvelopeStruct* pEnvelopeA 包络A
* @param[in] const EnvelopeStruct* pEnvelopeB 包络B
* @return 0x01 包络A电子地图方向在左
0x02 包络B在电子地图方向左
0x00 无法比较位置关系
* @note 无
*/
UINT8 as_CalcAreaOrder(IN const TrainLocStruct* pTrainA, IN const TrainLocStruct* pTrainB)
{
	UINT8 RetVal = DEFAULT_ZERO;

	if ((NULL != pTrainA) && (NULL != pTrainB))
	{
		RetVal = CalcAreaOrder(pTrainA, pTrainB);
		switch (RetVal)
		{
		case AS_ORDER_UPSTREAM:    /*A在左*/
			RetVal = 0x01U;
			break;
		case AS_ORDER_DOWNSTREAM:
			RetVal = 0x02U;       /*B在左*/
			break;
		default:
			RetVal = DEFAULT_ZERO;
			break;
		}
	}
	else
	{
		;
	}
	return RetVal;
}

/**
* @brief 打印link排序信息
* @param 无
* @return 无
* @note 无
*/
static void as_DebugPrint(void)
{
	UINT16 wLinkIndex = 0u;
	UINT8 chTrainNum = 0u;
	UINT8 chTrainIndex = 0u;
	UINT8 chLocalId = 0u;
	UINT16 wLinkTioc = 0u;
	TRAIN_SEQUANCE_s TrainList[SIZE_MAX_TRAINOFAC] = { 0u };
	LinkDataConfigStru * strTemp = NULL;
	UINT8 outString[AXIS_SORT_LOG_BUF_SIZE] = { 0U };
	UINT16 outStringLength = 0U;

	chLocalId = GetSystemParaLocalCiId();

	for (wLinkIndex = 0u; wLinkIndex < AS_LINK_MAX; wLinkIndex++)
	{
		strTemp = GetLinkDataByIndex(wLinkIndex);
		if ((0u < strTemp->wId) && (AS_LINK_MAX > strTemp->wId))
		{
			wLinkTioc = GetLinkManageTiocById(strTemp->wId);
			if (wLinkTioc == chLocalId)
			{
				chTrainNum = as_GetLinkTrainList(strTemp->wId, TrainList, SIZE_MAX_LINETRAIN);

				ShortToChar(strTemp->wId, &outString[outStringLength]);  /*Link ID*/
				outStringLength += 2U;
				outString[outStringLength] = chTrainNum;  /*列车数量*/
				outStringLength++;

				for (chTrainIndex = 0u; chTrainIndex < chTrainNum; chTrainIndex++)
				{
					ShortToChar(TrainList[chTrainIndex].u16TrainID, &outString[outStringLength]);  /*列车ID*/
					outStringLength += 2U;
					outString[outStringLength] = TrainList[chTrainIndex].u8TrainType;  /*列车类型*/
					outStringLength++;
					ShortToChar(TrainList[chTrainIndex].u16ELID, &outString[outStringLength]);  /*列车包络ID*/
					outStringLength += 2U;
				}
			}
			else
			{
				; /* 非本控区，不打印。 */
			}
		}
		else
		{
			;
		}
	}

	if (0u == outStringLength)
	{
		;
	}
	else
	{
#ifdef PLATFORM_2OO2

		debug_infor_printf((const)"\nSortLinkData:%d\nLinkId(2)-TrainNum-TrainID(2)-TrainType-TrainEnvelopId(2)", outStringLength);

		debug_out_array(0xAA, outString, outStringLength);
		

#endif

#ifdef PLATFORM_LABVIEW_DEBUG

		Out_Array_Buffer(0, "\nSortLinkData:%d", outStringLength);
		Out_Array_Buffer(0, "\nLinkId(2)-TrainNum-TrainID(2)-TrainType-TrainEnvelopId(2):%d", outStringLength);
		Out_Array_Buffer(16, outString, outStringLength);

#endif
	}
}

/*****************************************************************************
* @name        TrainManage_GetTrainSleepState
* @brief       获取列车休眠状态
* @param[in]   UINT16 TrainID
* @return     0: 获取数据失败
*			  0x55:列车处于休眠状态
*			  0xAA:列车未处于休眠状态
* @note        从列车管理模块获取
* by cgh 20240726
*****************************************************************************/
UINT8 TrainManage_GetTrainSleepState(IN UINT16 TrainID)
{
	UINT8 dir = DEFAULT_ZERO;
	UINT16 u16IDIndex = DEFAULT_ZERO;

	if (TrainID > DEFAULT_ZERO)
	{
		u16IDIndex = GetTrainId(TrainID - 1U);
		dir = GetTrainSleepState(u16IDIndex);
	}
	else
	{
		;
	}
	return dir;
}