/******************************************************************************
** 文件名:  SectionStateProcess.c
** 描 述:   区段状态处理模块，简称ssp
*******************************************************************************/

#include "SectionStateProcess_define.h"
#include "../AxisSort/AxisSort_api.h"
#include "SectionStateProcess_api.h"
#include "AxisSectionConfigDataManage.h"
#include "EnvelopeManageAPI.h"
#include "ELMDataPrepare.h"
#include "LinkConfigDataManage.h"
#include "LogicSectionConfigDataManage.h"


/* 区段状态数据结构 */
typedef struct
{
    UINT16 u16ID;         /* 区段ID */
    UINT8 u8Status;       /* 状态 STATUS_UT,STATUS_CT,STATUS_ARB,STATUS_FREE */
}SSP_STATUS_s;


/* 逻辑区段状态信息 */
static UINT16 s_pSecNum = DEFAULT_ZERO;            /* 逻辑区段数量 */
static UINT16 s_pSecIndex[SIZE_MAX_SECTION + 1U];  /* 逻辑区段索引 */
static SSP_STATUS_s s_pSecState[SIZE_MAX_SECTION + 1U]; /*逻辑区段状态信息*/
static UINT8 outString_lgc[SIZE_MAX_SECTION * 2U] = { 0u };     /*逻辑区段占用状态-维护数据打印数据缓冲*/

/* 计轴状态信息 */
static UINT16 s_pAxisNum = DEFAULT_ZERO;         /* 计轴数量 */
static UINT16 s_pAxisIndex[SIZE_MAX_AC + 1U];    /* 计轴索引 */
static SSP_STATUS_s s_pAxisState[SIZE_MAX_AC + 1U];  /* 计轴状态信息 */ /*预留*/

/*出清所有区段*/
static void FreeAll(void);
/*为所有通信车添加逻辑区段CT占用*/
static void CreateCT(void);
/*处理CT和UT混合，或纯UT*/
static void CreateUT(void);
/*在U16数组中找给定值对应的角标*/
static UINT8 u16Find(IN UINT8 u8Num, IN const UINT16 u16List[], IN UINT16 u16Val, OUT UINT8 *pu8Index);
/*获取通信车的CT占压的逻辑区段序列(安全后端-安全前端)*/
static UINT16 GetCTSecList(IN UINT16 u16TrainID, OUT UINT16 u16SecList[SIZE_MAX_SECTION_BT_TRAIN]);
/*设置计轴所属逻辑区段的状态*/
static void SetACSecState(UINT16 u16ACID, UINT8 u8State);
/*混跑计轴添加UT逻辑区段*/
static void MixACCreateUTSec(UINT16 u16ACID);
/*获取列车的起点所在逻辑区段ID*/
static UINT16 GetTrainOrgnSec(UINT16 u16TrainID);
/*获取列车的终点所在逻辑区段ID*/
static UINT16 GetTrainTmnlSec(UINT16 u16TrainID);
/*打印逻辑区段占用状态*/
static void LogPrintf_LgcOccState(void);
/************以下从外部接口获取**************/
/*获取指定列车等级*/
static UINT8 TrainDataMange_GetTrainLevel(UINT16 TrainID);
/*列车的终点侧(右端)筛选是否有效*/
static UINT8 elm_IsTrainTmnlUT(UINT16 TrainID);
/*列车的起点侧(左端)筛选是否有效*/
static UINT8 elm_IsTrainOrgnUT(UINT16 TrainID);
/*****************************************************************************
* @name        ssp_Init
* @brief       SSP模块初始化
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
void ssp_Init(void)
{
    UINT16 u16ACID = DEFAULT_ZERO;          /* ACID */
    UINT16 u16Index = DEFAULT_ZERO;         /* 循环变量ID */

    /*- 初始化 */
    (void)memset(s_pSecIndex, 0, sizeof(s_pSecIndex));
    (void)memset(s_pSecState, 0, sizeof(s_pSecState));

    s_pSecNum = DEFAULT_ZERO;

    /* 逻辑区段状态数组初始化 */
    for (u16Index = 1U; u16Index <= SIZE_MAX_SECTION; u16Index++)
    {
		/*根据逻辑区段ID看是否能查询对应的计轴ID*/
		u16ACID = GetLgcSecRelativeAxleSecSum(u16Index);
        if (DEFAULT_ZERO != u16ACID)
        {
            if (s_pSecNum < SIZE_MAX_SECTION)
            {
                s_pSecNum++;
                s_pSecIndex[u16Index] = s_pSecNum;
                s_pSecState[s_pSecNum].u16ID = u16Index;
                s_pSecState[s_pSecNum].u8Status = STATUS_UT;
            }
            else
            {
				debug_infor_printf((const)"FATAL:[SSP][ZC%d]本控区内逻辑区段数量过多");
            }
        }
    }

	s_pAxisNum = DEFAULT_ZERO;
	/*- @alias 计轴状态数组初始 */
	for (u16Index = 1U; u16Index <= SIZE_MAX_AC; u16Index++)
	{
		if (s_pAxisNum < SIZE_MAX_AC)
		{
			s_pAxisNum++;
			s_pAxisIndex[u16Index] = s_pAxisNum;
			s_pAxisState[s_pAxisNum].u16ID = u16Index;
			s_pAxisState[s_pAxisNum].u8Status = STATUS_UT;
		}
		else
		{
			debug_infor_printf((const)"FATAL:[SSP]本控区内计轴数量过多");
		}
	}

}


/*****************************************************************************
* @name        ssp_MainProcess
* @brief       SSP模块周期主逻辑
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
void ssp_MainProcess(void)
{
	/*出清所有区段状态 */
	FreeAll();

	/*遍历通信车添加CT占用 */
	CreateCT();

	/*处理UT占用 */
	CreateUT();

	/* 将逻辑区段占用状态传导给逻辑区段模块 */
	SetAllLgcOccupyState();

	/*打印逻辑区段占用信息*/
	LogPrintf_LgcOccState( );
}
/*****************************************************************************
* @name        GetCTSecList
* @brief       获取通信车的CT占压的逻辑区段序列(安全后端-安全前端)
* @param[in]   u16TrainID 列车ID
* @param[out]  u16SecList 逻辑区段序列
* @return      逻辑区段数量
* @note 输出的逻辑区段序列是从始端到终端的，和电子地图方向一致。
*       列车筛选无效端的逻辑区段未剔除
*****************************************************************************/
static UINT16 GetCTSecList(IN UINT16 u16TrainID, OUT UINT16 u16SecList[SIZE_MAX_SECTION_BT_TRAIN])
{
	UINT8 u8LocValid = DEFAULT_ZERO;       /* 位置有效性标志 */
	UINT8 u8OrgUT = DEFAULT_ZERO;      /* 始端筛选状态 */
	UINT8 u8TmmlUT = DEFAULT_ZERO;      /* 终端筛选状态 */
	UINT8 u8TrainDir = DEFAULT_ZERO;       /* 列车运行方向 */
	UINT8 u8FirstSecIndex = DEFAULT_ZERO;  /* 首个CT区段的索引 */
	UINT16 u16SecNum = DEFAULT_ZERO;         /* 逻辑区段数量 */
	UINT16 sTmpList[SIZE_MAX_SECTION_BT_TRAIN] = { 0U };    /* 逻辑区段列表 */
											  
	struct_PathPoint start = { 0u };
	struct_PathPoint end = { 0u };
	UINT8 u8dirTemp = DEFAULT_ZERO;
	UINT8 u8Ret = CI_ERROR;

	u8LocValid = TrainManage_GetTrainLocValid(u16TrainID);

	/*- 列车位置是否有效 */
	if (FLAG_SET == u8LocValid)
	{
		u8TrainDir = GetTrainSafeTailDir(u16TrainID);/*安全车尾方向*/
		u8OrgUT = elm_IsTrainOrgnUT(u16TrainID);
		u8TmmlUT = elm_IsTrainTmnlUT(u16TrainID);

		/*- 列车是否沿逻辑正向运行 */
		if (EMAP_SAME_DIR == u8TrainDir)
		{
			(void)TrainManage_GetTrainSafeLoc(FINDHEADSAFEFLAG, u16TrainID, &end.wLinkId, &end.dwOffset, &u8dirTemp);
			(void)TrainManage_GetTrainSafeLoc(FINDTAILSAFEFLAG, u16TrainID, &start.wLinkId, &start.dwOffset, &u8dirTemp);
		}
		/*- 列车是否沿逻辑反向运行 */
		else if (EMAP_CONVER_DIR == u8TrainDir)
		{
			(void)TrainManage_GetTrainSafeLoc(FINDHEADSAFEFLAG, u16TrainID, &start.wLinkId, &start.dwOffset, &u8dirTemp);
			(void)TrainManage_GetTrainSafeLoc(FINDTAILSAFEFLAG, u16TrainID, &end.wLinkId, &end.dwOffset, &u8dirTemp);
		}
		else
		{
			/*无操作*/
			;
		}

		/*获取车占压的逻辑区段序列，序列是从左到右的输出，即sTmpList[0]是始端所在的逻辑区段*/
		u8Ret = GetLogSecBtwTwoPoints(start, end, &u16SecNum, sTmpList);
		if ((SIZE_MAX_SECTION_BT_TRAIN >= u16SecNum) && (CI_SUCCESS == u8Ret))
		{
			(void)memmove(u16SecList, &sTmpList[u8FirstSecIndex], u16SecNum * sizeof(UINT16));
		}
		else
		{
			;
		}

#if 0
		/***********************以下是剔除ct车筛选无效端所在的逻辑区段，目前需求是ct和ut混合的时候，优先ct，故屏蔽以下代码*****************************************/
		/*- 是否查询失败 */
		if (DEFAULT_ZERO == u16SecNum)
		{
			/*- 无处理 */
			;
		}
		/*- 是否只有1个逻辑区段 */
		else if (1U == u16SecNum)
		{
			/* 只有1个逻辑区段时，至多把一个无筛选端剔除*/
			/*筛选是否无效 */
			if ((FLAG_SET == u8OrgUT) || (FLAG_SET == u8TmmlUT))
			{
				/*- 没有CT区段 */
				u16SecNum = 0u;
			}
		}
		else
		{
			/* 多于2个逻辑区段，把筛选无效端的逻辑区段剔除(维持UT) */
			/*- 始端筛选是否无效 */
			if (FLAG_SET == u8OrgUT)
			{
				/*- 始端筛选不作为CT区段 */
				u8FirstSecIndex++;
				u16SecNum--;
			}

			/*- 终端筛选是否无效 */
			if (FLAG_SET == u8TmmlUT)
			{
				/*- 右区段不作为CT区段 */
				u16SecNum--;
			}
		}
		memmove(u16SecList, &sTmpList[u8FirstSecIndex], u16SecNum * sizeof(UINT16));
#endif
	}
	else
	{
		;
	}
	/*- 返回逻辑区段数量*/
	return u16SecNum;
}
/*****************************************************************************
* @name        CreateUT
* @brief       处理CT和UT混合，或纯UT
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void CreateUT(void)
{
    UINT8 u8OccState = DEFAULT_ZERO;              /* CI占用状态 */
    UINT8 u8Index = DEFAULT_ZERO;                 /* 循环变量 */
    UINT8 u8TrainNum = DEFAULT_ZERO;              /* 列车数量 */
    UINT8 u8OrgUT = DEFAULT_ZERO;             /* 前端筛选状态 */
    UINT8 u8EndUT = DEFAULT_ZERO;             /* 后端筛选状态 */
    UINT8 u8UTTrainCnt = DEFAULT_ZERO;           /* UT车计数器 */
    UINT8 u8ATTrainCnt = DEFAULT_ZERO;           /* AT车计数器 */
    UINT16 u16AxisIndex = DEFAULT_ZERO;           /* 计轴信息索引 */
	UINT16 u16TmpACID = DEFAULT_ZERO;             /* 计轴ID */   

	EnvelopeStruct TrainEL[SIZE_MAX_TRAINOFAC] = { 0U }; /* 列车序列包络 */

	UINT8 u8ACState = DEFAULT_ZERO;              /* 计轴区段状态 */

    /*遍历所有计轴 */
    /*- 计轴索引置1 ; 是否尾部? ; 索引递增*/
    for (u16AxisIndex = 1U; u16AxisIndex <= s_pAxisNum; u16AxisIndex++)
    {
		/*- 获取计轴上的列车序列 */
		u8TrainNum = elm_GetEnvelopeInAC(s_pAxisState[u16AxisIndex].u16ID, TrainEL);
        u8ATTrainCnt = 0U;
        u8UTTrainCnt = 0U;
        /*遍历列车序列 */
		if (SECTION_REL_ENVELOPE_SUM_MAX != u8TrainNum)	
		{
			for (u8Index = DEFAULT_ZERO; u8Index < u8TrainNum; u8Index++)
			{
				if (TYPE_CT == TrainEL[u8Index].envelopeType) /*CT列车才看前后端，CT列车才能用TrainEL[u8Index].trainID[0]*/
				{
					if (FLAG_SET == TrainManage_GetTrainLocValid(TrainEL[u8Index].trainID[0]))
					{
						/*- 列车位置有效 */
						u8ATTrainCnt = u8ATTrainCnt + 1U;
						/*找到始端link所处的计轴ID*/
						u16TmpACID = GetLinkBelongAcId(TrainEL[u8Index].startPos.Lnk);
						if (u16TmpACID == s_pAxisState[u16AxisIndex].u16ID)
						{
							u8OrgUT = elm_IsTrainOrgnUT(TrainEL[u8Index].trainID[0]);
						}
						else
						{
							u8OrgUT = FLAG_UNSET;
						}

						/*找到终端link所处的计轴ID*/
						u16TmpACID = GetLinkBelongAcId(TrainEL[u8Index].endPos.Lnk);
						if (u16TmpACID == s_pAxisState[u16AxisIndex].u16ID)
						{
							u8EndUT = elm_IsTrainTmnlUT(TrainEL[u8Index].trainID[0]);
						}
						else
						{
							u8EndUT = FLAG_UNSET;
						}
						/*- 是否是非通信车或筛选无效列车 */
						if ((FLAG_SET == u8EndUT) || (FLAG_SET == u8OrgUT))
						{
							u8UTTrainCnt = u8UTTrainCnt + 1U;/*UT车数量加1 */
						}
						else
						{
							;
						}
					}
					else
					{
						u8UTTrainCnt = u8UTTrainCnt + 1U;/*UT车数量加1 */
					}

				}
				else
				{
					; /* 仅处理CT列车 */
				}
			}
		}
		else
		{
			;	/*数量非法值不进行处理*/
		}
        /*- 是否计轴有车且全是有筛选的通信车 */
        if ((DEFAULT_ZERO < u8ATTrainCnt) && (DEFAULT_ZERO == u8UTTrainCnt))
        {
            /*- 计轴状态为CT */
            s_pAxisState[u16AxisIndex].u8Status = STATUS_CT;
            /* CT占用已经在前面统一添加过，这里不再处理 */
        }
        /*- 是否计轴混跑 */
        else if ((DEFAULT_ZERO < u8UTTrainCnt) && (DEFAULT_ZERO < u8ATTrainCnt))
        {
			debug_infor_printf((const)"Axis ID:[%d] Is Filled With CT And UT Train\n", s_pAxisState[u16AxisIndex].u16ID);
            /* 计轴占用且存在无筛选列车，说明是CT、UT混跑的计轴 */
            /*- 计轴状态为UT */
            s_pAxisState[u16AxisIndex].u8Status = STATUS_UT;
            /*- 计轴上插入UT逻辑区段 */
            MixACCreateUTSec(s_pAxisState[u16AxisIndex].u16ID);
        }
        else
        {
			u8OccState = elm_PrepareACStatus(s_pAxisState[u16AxisIndex].u16ID);
			u8ACState = aam_GetACAssertStatus(s_pAxisState[u16AxisIndex].u16ID);
			/*- CI是否占用 */
			if (ELM_AC_OCC == u8OccState)
			{
				if ((0u == u8TrainNum) && 
					((AAM_API_AC_ARB == u8ACState) || (AAM_API_AC_REDUNARB == u8ACState) || (AAM_API_AC_REDUNUT == u8ACState)))
				{
					/*arb，或arb冗余，或ut冗余，置逻辑区段空闲，无需处理*/
				}
				else
				{					
					SetACSecState(s_pAxisState[u16AxisIndex].u16ID, STATUS_UT);  /*- 计轴上的所有逻辑区段置UT*/
					s_pAxisState[u16AxisIndex].u8Status = STATUS_UT;  /*更新计轴区段占用状态为UT占用*/
				}
			}
			else
			{
				/*none*/
			}
        }
    }
}

/*****************************************************************************
* @name        FreeAll
* @brief       出清所有轨道
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void FreeAll(void)
{
    UINT16 u16Index = DEFAULT_ZERO;  /* 循环变量 */

    /* 遍历本控区的所有逻辑区段，置为空闲 */
    for (u16Index = 1U; u16Index <= s_pSecNum; u16Index++)
    {
        /* 置逻辑区段状态为空闲 */
        s_pSecState[u16Index].u8Status = STATUS_FREE;
    }

	/* 遍历本控区的所有计轴，置为空闲 */
	for (u16Index = 1U; u16Index <= s_pAxisNum; u16Index++)
	{
		/* 置计轴状态为空闲 */
		s_pAxisState[u16Index].u8Status = STATUS_FREE;
	}
}

/*****************************************************************************
* @name        CalcSecOrder
* @brief       计算逻辑区段相对位置
* @param[in]   u16Sec1 逻辑区段1 ID
* @param[in]   u16Sec2 逻辑区段2 ID
* @return      Sec1指向Sec2的方向
*              EMAP_CONVER_DIR 电子地图反向
*              EMAP_SAME_DIR   电子地图正向
*              DEFAULT_ZERO    位置相同
*              0xFF            计算失败
* @note        无
*****************************************************************************/
static UINT8 CalcSecOrder(UINT16 u16Sec1, UINT16 u16Sec2)
{
    UINT8 u8Rslt = INVALID_8;

	u8Rslt = dsuJudgeLogAandLogBPosition(u16Sec1, u16Sec2, EMAP_SAME_DIR);
	/*- 判断逻辑区段1和逻辑区段2起点的前后顺序*/
	switch (u8Rslt)
	{
	case FLAG_SET:
		u8Rslt = EMAP_CONVER_DIR; /*1在2左*/
		break;
	case FLAG_UNSET:
		u8Rslt = EMAP_SAME_DIR; /*1在2右*/
		break;
	case CI_SUCCESS:
		u8Rslt = DEFAULT_ZERO;  /*相同区段*/
		break;
	default:
		u8Rslt = INVALID_8;
		break;
	}
	return u8Rslt;
   
}

/*****************************************************************************
* @name        MixACCreateUTSec
* @brief       混跑计轴添加UT逻辑区段
* @param[in]   u16ACID
* @return      无
* @note 注意只能用于有CT序列的混跑计轴
*       无CT车的纯UT计轴不能用此函数添加UT区段
*****************************************************************************/
static void MixACCreateUTSec(UINT16 u16ACID)
{
	UINT8 u8Rslt = DEFAULT_ZERO;                 /* 临时变量 */
	INT8 u8SecIndex = 0;             /* 逻辑区段索引 */
	UINT8 u8TrainIndex = DEFAULT_ZERO;           /* 循环变量 */
	UINT8 u8TrainNum = DEFAULT_ZERO;             /* 列车数量 */
	UINT8 u8SecNum = DEFAULT_ZERO;               /* 逻辑区段数量 */
	UINT16 u16SecID = DEFAULT_ZERO;              /* 逻辑区段ID */

	UINT16 u16TmpHeadACID = DEFAULT_ZERO;             /* 头部计轴ID */
	UINT16 u16TmpTailACID = DEFAULT_ZERO;             /* 尾部计轴ID */
	UINT8 u8OrgUT = DEFAULT_ZERO;             /* 前端筛选状态 */
	UINT8 u8EndUT = DEFAULT_ZERO;             /* 后端筛选状态 */
	UINT8 u8TrainHeadDir = DEFAULT_ZERO;	/*列车头方向*/
	UINT8 u8TrainTailDir = DEFAULT_ZERO;	/*列车尾方向*/

	UINT16* plogicSecIdBuf = NULL; /*计轴区段Id数组*/

	EnvelopeStruct TrainEnvelope[SIZE_MAX_TRAINOFAC] = { 0U }; /* 列车序列包络 */

	u8TrainNum = elm_GetEnvelopeInAC(u16ACID, TrainEnvelope);

	/*将计轴区段转化为逻辑区段,获取计轴上的逻辑区段列表,逻辑区段列表为link方向自左向右 */
	u8SecNum = GetAxisSecLogSectionSum(u16ACID);
	plogicSecIdBuf = GetAxisSecLogSectionIdBuf(u16ACID);
	if (0u < u8SecNum)
	{
		/* 遍历列车序列 */
		for (u8TrainIndex = DEFAULT_ZERO; u8TrainIndex < u8TrainNum; u8TrainIndex++)
		{
			/*找到始端link所处的计轴ID*/
			u16TmpTailACID = GetLinkBelongAcId(TrainEnvelope[u8TrainIndex].startPos.Lnk);
			u8OrgUT = elm_IsTrainOrgnUT(TrainEnvelope[u8TrainIndex].trainID[0]);
			if ((u16ACID == u16TmpTailACID) && (FLAG_SET == u8OrgUT))
			{
				u16SecID = GetTrainOrgnSec(TrainEnvelope[u8TrainIndex].trainID[0]);
				u8TrainTailDir = GetTrainSafeTailDir(TrainEnvelope[u8TrainIndex].trainID[0]);
				u8TrainTailDir = ~u8TrainTailDir;

				if (EMAP_SAME_DIR == u8TrainTailDir)
				{
					u8Rslt = u16Find(u8SecNum, plogicSecIdBuf, u16SecID, &u8SecIndex);
					if (CI_SUCCESS == u8Rslt)
					{
						/*往右端所在的逻辑区段偏移一位，因为不考虑右端所在逻辑区段的筛选状态（都当作ct）*/
						u8SecIndex++;
					}
					else
					{
						u8SecIndex = (INT8)u8SecNum;
					}
					while ((UINT8)u8SecIndex < u8SecNum) /*(不包含筛选无效端所在的逻辑区段)*/
					{
						/* 逻辑区段置UT占用 */
						if (STATUS_CT == s_pSecState[s_pSecIndex[s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u16ID]].u8Status)
						{
							break;		/*两车情况遇到通信车占压，不再跨过通信车设置UT占压*/
						}
						else
						{
							s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u8Status = STATUS_UT;
							debug_infor_printf((const)"CT车左筛选无效左逻辑区段[%d]UT占用\n", s_pSecIndex[plogicSecIdBuf[u8SecIndex]]);
							u8SecIndex++;
						}
					}
				}
				else
				{
					u8Rslt = u16Find(u8SecNum, plogicSecIdBuf, u16SecID, &u8SecIndex);
					if (CI_SUCCESS == u8Rslt)
					{
						/*往左端所在的逻辑区段偏移一位，因为不考虑左端所在逻辑区段的筛选状态（都当作ct）*/
						u8SecIndex--;
					}
					else
					{
						u8SecIndex = -1;
					}
					while (0 <= u8SecIndex) /*(不包含筛选无效端所在的逻辑区段)*/
					{
						/* 逻辑区段置UT占用 */
						if (STATUS_CT == s_pSecState[s_pSecIndex[s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u16ID]].u8Status)
						{
							break;		/*两车情况遇到通信车占压，不再跨过通信车设置UT占压*/
						}
						else
						{
							s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u8Status = STATUS_UT;
							debug_infor_printf((const)"CT车右筛选无效右逻辑区段[%d]UT占用\n", s_pSecIndex[plogicSecIdBuf[u8SecIndex]]);
							u8SecIndex--;
						}
					}
				}

			}
			else
			{

			}

			u8SecIndex = 0;
			/*找到终端link所处的计轴ID*/
			u16TmpHeadACID = GetLinkBelongAcId(TrainEnvelope[u8TrainIndex].endPos.Lnk);
			u8EndUT = elm_IsTrainTmnlUT(TrainEnvelope[u8TrainIndex].trainID[0]);
			if ((u16ACID == u16TmpHeadACID) && (FLAG_SET == u8EndUT))
			{
				u16SecID = GetTrainTmnlSec(TrainEnvelope[u8TrainIndex].trainID[0]);
				u8TrainHeadDir = GetTrainSafeHeadDir(TrainEnvelope[u8TrainIndex].trainID[0]);

				if (EMAP_SAME_DIR == u8TrainHeadDir)
				{
					u8Rslt = u16Find(u8SecNum, plogicSecIdBuf, u16SecID, &u8SecIndex);
					if (CI_SUCCESS == u8Rslt)
					{
						/*往右端所在的逻辑区段偏移一位，因为不考虑右端所在逻辑区段的筛选状态（都当作ct）*/
						u8SecIndex++;
					}
					else
					{
						u8SecIndex = (INT8)u8SecNum;
					}
					while ((UINT8)u8SecIndex < u8SecNum) /*(不包含筛选无效端所在的逻辑区段)*/
					{
						/* 逻辑区段置UT占用 */
						if (STATUS_CT == s_pSecState[s_pSecIndex[s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u16ID]].u8Status)
						{
							break;		/*两车情况遇到通信车占压，不再跨过通信车设置UT占压*/
						}
						else
						{
							s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u8Status = STATUS_UT;
							debug_infor_printf((const)"CT车左筛选无效左逻辑区段[%d]UT占用\n", s_pSecIndex[plogicSecIdBuf[u8SecIndex]]);
							u8SecIndex++;
						}
					}
				}
				else
				{
					u8Rslt = u16Find(u8SecNum, plogicSecIdBuf, u16SecID, &u8SecIndex);
					if (CI_SUCCESS == u8Rslt)
					{
						/*往左端所在的逻辑区段偏移一位，因为不考虑左端所在逻辑区段的筛选状态（都当作ct）*/
						u8SecIndex--;
					}
					else
					{
						u8SecIndex = -1;
					}
					while (0 <= u8SecIndex) /*(不包含筛选无效端所在的逻辑区段)*/
					{
						/* 逻辑区段置UT占用 */
						if (STATUS_CT == s_pSecState[s_pSecIndex[s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u16ID]].u8Status)
						{
							break;		/*两车情况遇到通信车占压，不再跨过通信车设置UT占压*/
						}
						else
						{
							s_pSecState[s_pSecIndex[plogicSecIdBuf[u8SecIndex]]].u8Status = STATUS_UT;
							debug_infor_printf((const)"CT车右筛选无效右逻辑区段[%d]UT占用\n", s_pSecIndex[plogicSecIdBuf[u8SecIndex]]);
							u8SecIndex--;
						}
					}
				}
			}
			else
			{

			}
		}
	}
	else
	{
		;
	}

}

/*****************************************************************************
* @name        SetACSecState
* @brief       设置计轴所属逻辑区段的状态
* @param[in]   u16ACID 计轴ID
* @param[in]   u8State 区段状态(STATUS_UT,STATUS_CT,STATUS_ARB,STATUS_FREE)
* @return      无
* @note        无
*****************************************************************************/
static void SetACSecState(UINT16 u16ACID, UINT8 u8State)
{
    UINT8 u8Index = DEFAULT_ZERO;           /* 循环变量 */
    UINT8 u8SecNum = DEFAULT_ZERO;          /* 逻辑区段数量 */
	UINT16* plogicSecIdBuf = NULL; /*计轴区段Id数组*/

	/*- 获取计轴上的逻辑区段列表 */
	u8SecNum = GetAxisSecLogSectionSum(u16ACID);
	plogicSecIdBuf = GetAxisSecLogSectionIdBuf(u16ACID);
	if (0u < u8SecNum) 
	{
		/*- 遍历逻辑区段列表，设置逻辑区段状态*/
		for (u8Index = DEFAULT_ZERO; u8Index < u8SecNum; u8Index++)
		{
			/*是否是本ZC控区的逻辑区段 */
			if (DEFAULT_ZERO < s_pSecIndex[plogicSecIdBuf[u8Index]])
			{
				/* 设置逻辑区段状态 */
				s_pSecState[s_pSecIndex[plogicSecIdBuf[u8Index]]].u8Status = u8State;
				debug_infor_printf((const)"Axis ID:[%d] LogicSection ID:[%d] Is Filled With UT Train\n", u16ACID, s_pSecIndex[plogicSecIdBuf[u8Index]]);
			}
			else
			{
				/*- 不可达分支 */
			}
		}
	}
	else
	{
		;
	}

}

/*****************************************************************************
* @name        CreateCT
* @brief       为所有通信车添加逻辑区段CT占用
* @param[in]   无
* @return      无
* @note        无
*****************************************************************************/
static void CreateCT(void)
{
    UINT8 u8Index = DEFAULT_ZERO;     /* 循环变量 */
    UINT16 u16Num = DEFAULT_ZERO;       /* 区段数量 */
    UINT8 u8Stat = STATUS_UT;         /* 区段状态 */
    UINT16 u16TrainID = DEFAULT_ZERO; /* 列车ID */
	UINT16 u16List[SIZE_MAX_SECTION_BT_TRAIN] = {0u};     /* 区段列表 */
	UINT8 u8TrainLocValid = DEFAULT_ZERO; /*列车位置是否有效*/
	UINT8 u8TrainLevel = DEFAULT_ZERO; /*列车运行等级*/
	UINT8 u8TrainSlpStt = DEFAULT_ZERO;/*列车休眠状态*/

    /*- 列车索引置1 ; 是否尾部? ; 索引递增*/
    for (u16TrainID = 1U; u16TrainID < SIZE_MAX_LINETRAIN; u16TrainID++)
    {
		u8TrainLocValid = TrainManage_GetTrainLocValid(u16TrainID);
		if (FLAG_SET == u8TrainLocValid)
		{
			u8TrainLevel = TrainDataMange_GetTrainLevel(u16TrainID);
			u8TrainSlpStt = TrainManage_GetTrainSleepState(u16TrainID);

			if ((TRAIN_LEVEL_VBTC == u8TrainLevel) || (TRAIN_SLEEP_YES == u8TrainSlpStt))
			{
				/*列车等级是VBTC或者休眠车需要保持CT*/
				u8Stat = STATUS_CT;
			}
			else
			{
				u8Stat = STATUS_AT;
			}
			/*- 查询列车占用的逻辑区段序列 */
			u16Num = GetCTSecList(u16TrainID, u16List);
			if (SIZE_MAX_SECTION_BT_TRAIN >= u16Num )
			{
				/*- @alias 遍历逻辑区段序列，对本控区逻辑区段置CT/AT占用 */
				for (u8Index = DEFAULT_ZERO; u8Index < u16Num; u8Index++)
				{
					if (DEFAULT_ZERO != s_pSecIndex[u16List[u8Index]])
					{
						/*逻辑区段置CT占用 */
						s_pSecState[s_pSecIndex[u16List[u8Index]]].u8Status = u8Stat;
						debug_infor_printf((const)"LogicSection [%d] is CT Occupy\n", u16List[u8Index]);
					}
					else
					{
						;
					}
				}
			}
			else
			{
				;
			}
		}
		else
		{
			;
		}
    }
}


/*****************************************************************************
* @name        GetTrainOrgnSec
* @brief       获取列车的起点所在逻辑区段ID
* @param[in]   u16TrainID 列车ID
* @return      逻辑区段ID(无效时返回0)
* @note        无
*****************************************************************************/
static UINT16 GetTrainOrgnSec(UINT16 u16TrainID)
{
    UINT16 u16RetSgmtID = DEFAULT_ZERO;        /*函数返回值*/
	struct_PathPoint pos = { 0U };
	UINT8 u8dirTemp = DEFAULT_ZERO;

	/*取车尾*/
	(void)TrainManage_GetTrainSafeLoc(FINDTAILSAFEFLAG, u16TrainID, &pos.wLinkId, &pos.dwOffset, &u8dirTemp);
	
    /*- 转换为逻辑区段偏移输出 */
	u16RetSgmtID = GetPointBelongLogSec(pos);

    return u16RetSgmtID;
}

/*****************************************************************************
* @name        GetTrainTmnlSec
* @brief       获取列车的终点所在逻辑区段ID
* @param[in]   u16TrainID 列车ID
* @return      逻辑区段ID(无效时返回0)
* @note        无
*****************************************************************************/
static UINT16 GetTrainTmnlSec(UINT16 u16TrainID)
{
	UINT16 u16RetSgmtID = DEFAULT_ZERO;        /*函数返回值*/
	struct_PathPoint pos = { 0U };
	UINT8 u8dirTemp = DEFAULT_ZERO;

	/*取车头*/
	(void)TrainManage_GetTrainSafeLoc(FINDHEADSAFEFLAG, u16TrainID, &pos.wLinkId, &pos.dwOffset, &u8dirTemp);
	
	/*- 转换为逻辑区段偏移输出 */
	u16RetSgmtID = GetPointBelongLogSec(pos);

	return u16RetSgmtID;
}

/*****************************************************************************
* @name        u16Find
* @brief       在U16数组中找给定值对应的角标
* @param[in]   u8Num 数组长度
* @param[in]   u16List 待搜索的数组
* @param[in]   u16Val  待搜索的值
* @param[out]  pu8Index 值对应的角标
* @return      是否找到: CI_SUCCESS 找到，CI_ERROR 没找到
* @note        无
*****************************************************************************/
static UINT8 u16Find(IN UINT8 u8Num, IN const UINT16 u16List[], IN UINT16 u16Val, OUT UINT8 *pu8Index)
{
    UINT8 u8Ret = CI_ERROR; /* 函数返回值 */
    UINT8 u8Index = DEFAULT_ZERO; /* 循环变量 */

    /*- @alias 便利数组，返回给定值对应的角标及查询结果 */
    for (u8Index = DEFAULT_ZERO; u8Index < u8Num; u8Index++)
    {
        if (u16List[u8Index] == u16Val)
        {
            *pu8Index = u8Index;
            u8Ret = CI_SUCCESS;
            break;
        }
		else
		{
			;
		}
    }
    return u8Ret;
}



/*****************************************************************************
* @name        ssp_GetSecStatus
* @brief       获取逻辑区段状态
* @param[in]   u16SecID 逻辑区段ID
* @return      STATUS_UT,STATUS_CT,STATUS_ARB,STATUS_FREE
* @note        如果不是本控区的逻辑区段，固定返回 STATUS_UT
*****************************************************************************/
UINT8 ssp_GetSecStatus(UINT16 u16SecID)
{
	UINT8 u8State = STATUS_UT; /* 区段状态 */

	/*- 逻辑区段是否在本ZC控区 */
	if ((u16SecID <= SIZE_MAX_SECTION) && (DEFAULT_ZERO != s_pSecIndex[u16SecID]))
	{
		/*- 输出逻辑区段状态 */
		u8State = s_pSecState[s_pSecIndex[u16SecID]].u8Status;
	}
	else
	{
		;
	}

	/*- 返回逻辑区段状态 */
	return u8State;
}


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

/*****************************************************************************
* @name        TrainDataMange_GetTrainLevel
* @brief       获取指定列车等级
* @param[in]   TiranID 列车ID
* @return      列车运行等级
* @note        从列车管理模块中获取
*****************************************************************************/
static UINT8 TrainDataMange_GetTrainLevel(UINT16 TrainID)
{
	UINT8 level = DEFAULT_ZERO;
	UINT16 IDIndex = DEFAULT_ZERO;
	if (TrainID > DEFAULT_ZERO)
	{
		IDIndex = GetTrainId(TrainID - 1U);
		level = GetTrainLevel(IDIndex);
	}
	else
	{
		;
	}
	return level;
}


/*****************************************************************************
* @name        elm_IsTrainOrgnUT
* @brief       CT列车的起点侧(左端)筛选是否有效
* @param[in]   u16TrainID 列车ID
* @return      CT车筛选是否有效: FLAG_SET 有UT；FLAG_UNSET 无
* @note        注：只是CT车的
*****************************************************************************/
static UINT8 elm_IsTrainOrgnUT(UINT16 TrainID)
{
	UINT8 u8Clear = FLAG_UNSET;
	const EnvelopeStruct* pEL = NULL;

	/*根据ID获取包络*/
	pEL = elm_GetEnvelopeInfoByTrainID(TrainID);
	if (NULL != pEL)
	{
		/*- 返回尾端筛选状态 */
		if ((DEFAULT_ZERO != pEL->tailTrainID) && (TYPE_CT == pEL->envelopeType))
		{
			u8Clear = FLAG_SET;
		}
		else
		{
			/*无操作*/
		}
	}
	else
	{
		;
	}
	/*- 返回筛选状态*/
	return u8Clear;
}

/*****************************************************************************
* @name        elm_IsTrainTmnlUT
* @brief       CT列车的终点侧(右端)筛选是否有效
* @param[in]   u16TrainID 列车ID
* @return      CT车筛选是否有效: FLAG_SET 有可疑；FLAG_UNSET 无
* @note        注：只是CT车的
*****************************************************************************/
static UINT8 elm_IsTrainTmnlUT(UINT16 TrainID)
{
	UINT8 u8Clear = FLAG_UNSET;
	const EnvelopeStruct* pEL = NULL;

	/*根据ID获取包络*/
	pEL = elm_GetEnvelopeInfoByTrainID(TrainID);
	if (NULL != pEL)
	{
		/*- 返回头端筛选状态 */
		if ((DEFAULT_ZERO != pEL->headTrainID) && (TYPE_CT == pEL->envelopeType))
		{
			u8Clear = FLAG_SET;
		}
		else
		{
			/*无操作*/
		}
	}
	else
	{
		;
	}

	/*- 返回筛选状态*/
	return u8Clear;

}


/**
* @brief 打印逻辑区段占用状态
* @param 无
* @return 无
*/
static void LogPrintf_LgcOccState(void)
{
	UINT16 wLgcSum = 0u;  /*逻辑区段总数*/
	UINT16 wIndex = 0u;   /*数组缓存索引*/
	UINT16 wLgcId = 0u;
	UINT8 ii = 0u;
	UINT8 wLgcBelongCIId = 0u;
	UINT8 chLgcStatus = 0u;
	UINT8 localCiId = 0u;

	localCiId = GetSystemParaLocalCiId();  /*本机联锁ID*/
	wLgcSum = GetTotalLogSecCurNum();      /*获取逻辑区段总数*/
	/*清空打印数据*/
	CleanString(outString_lgc);
	for (ii = 0u; ii < wLgcSum; ii++)
	{
		wLgcId = GetLogicSecId(ii);
		wLgcBelongCIId = GetLogSecBelongCiId(wLgcId);           /*获取逻辑区段所属联锁ID*/
		/*该逻辑区段所属为本联锁*/
		if (localCiId == wLgcBelongCIId)
		{
			chLgcStatus = ssp_GetSecStatus(wLgcId);

			ShortToChar(wLgcId, &outString_lgc[wIndex]);/*打印逻辑区段ID*/
			wIndex += 2u;
			outString_lgc[wIndex] = chLgcStatus;/*逻辑区段占用状态*/
			wIndex++;
		}
		else
		{
			/*非本联锁逻辑区段，不打印*/
		}
	}
	if (wIndex == 0u)
	{/*无逻辑区段数据，不打印*/
	}
	else
	{
#ifdef PLATFORM_2OO2
		debug_infor_printf((const)"\nLogicSectionOccupyState:%d\nLogicSectionId(2)-LogicSecOccupyState(1):%d", (UINT16)sizeof(SSP_STATUS_s), wIndex);
		debug_out_array(0xAA, outString_lgc, wIndex);
#endif

#ifdef PLATFORM_LABVIEW_DEBUG
		Out_Array_Buffer(0, "\nLogicSectionOccupyState:%d", (UINT16)sizeof(SSP_STATUS_s));
		Out_Array_Buffer(0, "LogicSectionId(2)-LogicSecOccupyState(1):", wIndex);
		Out_Array_Buffer(16, outString_lgc, wIndex);
#endif

	}
}