#include "TrainOnAcManage.h"
#include "AxisSectionDataManage.h"
#include "ELMDataPrepare.h"
#include "AxisSort_api.h"
#include "ReverseCutDataManage.h"
#include "../IO/InputDataProcess.h"

static AcMapStruct g_acMap[AXIS_SECTION_SUM_MAX] = { 0u };		/* 计轴区段映射表 */
static UINT8 g_trainFlag[TRAIN_SUM_MAX] = { 0u };
static UtTrainStruct g_utTrain[TRAIN_SUM_MAX] = { 0u };
static UINT8 g_utTrainSum = 0u;
static UINT8 g_initStatus = TOA_INIT;
static ToaCmdStruct g_cmdStr[TOA_CMD_MAX] = { 0u };
static UINT8 g_cmdNum = 0u;

/**
* @brief 刷新通信车占用
* @param 无
* @return 无
* @note：
*/
static void ToaRefreshCt(void);

/**
* @brief 刷新非通信车占用
* @param 无
* @return 无
* @note：
*/
static void ToaRefreshUt(void);

/**
* @brief 删除元素
* @param wAcIndex 计轴区段映射表下标
* @param wTrainId 列车ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaDeleteAcMapElm(UINT16 wAcIndex, UINT16 wTrainId);

/**
* @brief 添加元素
* @param wAcIndex 计轴区段映射表下标
* @param wTrainId 列车ID
* @param chType   列车类型
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaAddAcMapElm(UINT16 wAcIndex, UINT16 wTrainId, UINT8 chType);

/**
* @brief 获取列车占压计轴区段
* @param wTrainId 列车ID
* @param szAcId 列车占压计轴区段
* @return 列车占压计轴区段数量
* @note：
*/
static UINT8 ToaGetAcInTrain(UINT16 wTrainId, UINT16 szAcId[MAX_AC_IN_TRAIN]);

/**
* @brief 获取列车安全位置
* @param wTrainId 列车ID
* @param szAcId 列车占压计轴区段
* @return 列车占压计轴区段数量
* @note：
*/
static UINT8 ToaGetTrainLoc(UINT16 wTrainId, TrainLocStruct * pLoc);

/**
* @brief 添加故障车
* @param wTrainId 列车ID
* @param chDir UT列车方向
* @param szAcId 列车占压计轴区段
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaAddUtTrain(UINT16 wTrainId, UINT8 chDir, UINT8 chAcNum, UINT16 szAcId[MAX_AC_IN_TRAIN]);

/**
* @brief 删除故障车
* @param wTrainId 列车ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaDeleteUtTrain(UINT16 wTrainId);

/**
* @brief 故障车折返处理
* @param 无
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaUtReturnProc(void);

/**
* @brief 故障车折返执行
* @param wTrainIndex 故障车存储下标
* @return 无
* @note：
*/
static void ToaReturnExc(UINT8 chTrainIndex);

/**
* @brief 故障占用延伸计算
* @param 无
* @return 无
* @note：
*/
static void ToaUtPathCal(void);

/**
* @brief 判断UT占用路径是否能进行延伸计算
* @param[in] chTrainIndex UT列车存储下标
* @return CI_SUCCESS:能进行延伸计算；CI_ERROR:不能进行延伸计算
* @note 无
*/
static UINT8 IsUtPathCanExtend(UINT8 chTrainIndex);

/**
* @brief A车在前
* @param[in] const TrainLocStruct* pTrainA 列车A
* @param[in] const TrainLocStruct* pTrainB 列车B
* @param[in] chDir 方向
* @return CI_SUCCESS:A在前；CI_ERROR:A未在前或判断不出
* @note 无
*/
static UINT8 ToaIsAFront(IN const TrainLocStruct* pTrainA, UINT8 chDir, IN const TrainLocStruct* pTrainB);

/**
* @brief 获取UT列车断通信周期号
* @param wTrainId 列车ID
* @return 周期号
* @note：
*/
static UINT32 ToaGetBreakCyc(UINT16 wTrainId);

/**
* @brief 在UT列车头部追加占压计轴区段
* @param wTrainId 列车ID
* @param wAcId 计轴区段ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaAddUtTrainAc(UINT16 wTrainId, UINT16 wAcId);

/**
* @brief 命令处理
* @note：
*/
static void ToaCmdProc(void);

/*
* @brief 设置故障物理区段列车占压
* @param const UINT16 wPhySecId 物理区段ID
*        const UINT16 wTrainId 列车编号
*        const UINT16 wTrainDir 列车方向
* @note 创建 lxc 20220617
*/
static void SetBreakPhySecWithTrainInfo(const UINT16 wPhySecId, const UINT16 wTrainId, const UINT8 chDir);
/*
* @brief 取消故障物理区段列车占压
* @param const UINT16 wPhySecId 物理区段ID
*        const UINT16 wTrainId 列车编号
*        const UINT16 wTrainDir 列车方向
* @note 创建 lxc 20220617
*/
static void UnLockBreakPhySecWithTrainInfo(const UINT16 wPhySecId, const UINT16 wTrainId, const UINT8 cTrainDir);

/**
* @brief 刷新UT占压序列（ATS人工设置时使用）
* @param wTrainId 列车ID
* @param chDir UT列车方向
* @param chAcNum 计轴区段数量
* @param szAcId 计轴区段ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaRefreshUtTrainAc(UINT16 wTrainId, UINT8 chDir, UINT8 chAcNum, UINT16 szAcId[MAX_AC_IN_TRAIN]);

/**
* @brief 判断计轴区段序列是否空闲
* @param wTrainId 列车ID
* @param cAcSum 计轴区段数量
* @param pAcIdBuf 计轴区段ID
* @return CI_ERROR:占用；CI_SUCCESS:空闲
* @note：
*/
static UINT8 IsAcListFreeToSet(UINT16 wTrainId, UINT8 cAcSum, UINT16* pAcIdBuf);

/**
* @brief 获取当前TIOC所有的通信车列车ID
* @param[out] szTrainId 列车ID缓存
* @return TIOC范围内通信列车数量
*/
static UINT8 ToaGetCommTrainId(UINT16 szTrainId[TRAIN_SUM_MAX_IN_OC]);

/**
* @brief 获取当前TIOC所有的丢失通信车列车ID
* @param[out] szTrainId 列车ID缓存
* @return TIOC范围内非通信列车数量
*/
static UINT8 ToaGetLoseCommTrainId(UINT16 szTrainId[TRAIN_SUM_MAX_IN_OC]);

/**
* @brief 计轴区段无故障车判断
* @param wAcIndex 计轴区段存储下标
* @return CI_ERROR:存在故障车；CI_SUCCESS:不存在故障车
* @note：
*/
static UINT8 IsAcHaveNoBadTrain(UINT16 wAcIndex);

/**
* @brief 获取UT列车存储索引
* @param wTrainId 列车ID
* @return TRAIN_SUM_MAX_IN_OC:失败，其他:索引
* @note：
*/
static UINT8 ToaGetUtIndex(UINT16 wTrainId);

/**
* @brief 删除UT列车尾部采集空闲带岔区段
* @param 无
* @return 无
* @note：
*/
static void ToaDeleteUtTrainTailFreeAc(void);

/**
* @brief UT列车是否已在计轴区段上
* @param wTrainId 列车ID
* @param wAcId 计轴区段ID
* @return CI_SUCCESS:列车已在计轴区段上；CI_ERROR:列车未在计轴区段上
* @note：
*/
static UINT8 IsUtTrainOnAc(UINT16 wTrainId, UINT16 wAcId);

/**
* @brief 调试信息打印
* @param 无
* @return 无
*/
static void ToaDebugInfo(void);

/**
* @brief 判断计轴区段是否能够设置
* @param wTrainId 列车ID
* @param wAcId
* @return CI_ERROR:不能设置；CI_SUCCESS:能够设置
* @note：
*/
static UINT8 IsAcFreeToSet(UINT16 wTrainId, UINT16 wAcId);

/**
* @brief 模块初始化
* @param 无
* @return CI_SUCCESS:初始化成功；CI_ERROR：初始化失败
* @note：
*/
UINT8 ToaInit(void)
{
	UINT8 chRtn = CI_ERROR;
	UINT16 * pAcId = NULL;
	UINT16 wAcSum = 0u;
	UINT16 wIndex = 0u;
	
	g_utTrainSum = 0u;
	chRtn = CommonMemSet(g_trainFlag, TRAIN_SUM_MAX, FLAG_UNSET, TRAIN_SUM_MAX);
	chRtn &= CommonMemSet(g_acMap, (UINT32)(sizeof(AcMapStruct) * AXIS_SECTION_SUM_MAX), 0u, (UINT32)(sizeof(AcMapStruct) * AXIS_SECTION_SUM_MAX));
	chRtn &= CommonMemSet(g_utTrain, (UINT32)(sizeof(UtTrainStruct) * TRAIN_SUM_MAX), 0u , (UINT32)(sizeof(UtTrainStruct) * TRAIN_SUM_MAX));
	chRtn &= CommonMemSet(g_cmdStr, (UINT32)(sizeof(ToaCmdStruct) * TOA_CMD_MAX), 0u , (UINT32)(sizeof(ToaCmdStruct) * TOA_CMD_MAX));
	g_cmdNum = 0u;
	g_initStatus = TOA_INIT;
	wAcSum = elm_PrepareACBuffIndexs(&pAcId);
	/* 将所有计轴区段置为故障车255占用 */
	if ((CI_SUCCESS == chRtn) && (NULL != pAcId))
	{
		for (wIndex = 0u; wIndex < wAcSum; wIndex++)
		{
			chRtn &= ToaAddAcMapElm(pAcId[wIndex], TRAIN_SUM_MAX, TOA_TYPE_UT);
		}
	}
	else
	{
		chRtn = CI_ERROR;
	}
	return chRtn;
}

/**
* @brief 模块解锁
* @param 无
* @return 无
* @note：从初始状态转到正常工作
*/
void ToaUnlock(void)
{
	UINT16 * pAcId = NULL;
	UINT16 wAcSum = 0u;
	UINT16 wIndex = 0u;
	
	/* 复位执行：
	1、清除255故障占用；
	2、模块置为正常工作状态*/
	wAcSum = elm_PrepareACBuffIndexs(&pAcId);
	if (NULL != pAcId)
	{
		for (wIndex = 0u; wIndex < wAcSum; wIndex++)
		{
			(void)ToaDeleteAcMapElm(pAcId[wIndex], TRAIN_SUM_MAX);
		}
		g_initStatus = TOA_NORMAL;
	}
	else
	{
		;
	}
}

/**
* @brief 模块主处理函数
* @param 无
* @return 无
* @note：
*/
void ToaMainProc(void)
{
	/* 刷新CT车占用 */
	ToaRefreshCt();

	/* 刷新UT车占用 */
	ToaRefreshUt();

	/* 维护日志打印 */
	ToaDebugInfo();
}

/**
* @brief 刷新通信车占用
* @param 无
* @return 无
* @note：
*/
static void ToaRefreshCt(void)
{
	UINT16 wAcIndex = 0u;
	UINT8 chTrainIndex = 0u;
	UINT8 chCtTrainNum = 0u;
	UINT16 szTrainId[TRAIN_SUM_MAX_IN_OC] = { 0u };
	UINT8 chAcNum = 0u;
	UINT16 szAcId[MAX_AC_IN_TRAIN] = { 0u };
	UINT8 chAcIndex = 0u;
	UINT16 wPhyId = 0u;
	UINT8 chIndex = 0u;
	
	/* 第一步：清除计轴区段所有通信车占用 */
	for (wAcIndex = 0u; wAcIndex < AXIS_SECTION_SUM_MAX; wAcIndex++)
	{
		if (0u < g_acMap[wAcIndex].chTrainNum)
		{
			for (chTrainIndex = (g_acMap[wAcIndex].chTrainNum - 1u); 0u <= chTrainIndex; chTrainIndex--) /*0u <= chTrainIndex在下面有中断判断*/
			{
				if ((TOA_TYPE_CT == g_acMap[wAcIndex].strTrain[chTrainIndex].chTrainType))
				{
					(void)ToaDeleteAcMapElm(wAcIndex, g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId);
				}
				else
				{
					; /* 继续遍历 */
				}
				if (0u == chTrainIndex)
				{
					break;
				}
				else
				{
					;
				}
			}
		}
		else
		{
			;
		}
	}

	/* 第二步：遍历所有通信车，将通信车落到计轴区段上 */
	chCtTrainNum = ToaGetCommTrainId(szTrainId);
	for (chTrainIndex = 0u; chTrainIndex < chCtTrainNum; chTrainIndex++)
	{
		chIndex = (UINT8)(szTrainId[chTrainIndex] & 0x00ffu);
		if (FLAG_SET == g_trainFlag[chIndex])
		{
			(void)ToaDeleteUtTrain(szTrainId[chTrainIndex]);
		}
		else
		{
			;
		}

		chAcNum = ToaGetAcInTrain(szTrainId[chTrainIndex], szAcId);
		for (chAcIndex = 0u; chAcIndex < chAcNum; chAcIndex++)
		{
			wPhyId = GetAxisSecRelativePhySecId(szAcId[chAcIndex]);
			SetPhySecCurOccupyState(wPhyId, SECTION_OCCUPY_YES);
			(void)ToaAddAcMapElm(szAcId[chAcIndex], szTrainId[chTrainIndex], TOA_TYPE_CT);
		}
	}
}

/**
* @brief 刷新非通信车占用
* @param 无
* @return 无
* @note：
*/
static void ToaRefreshUt(void)
{
	UINT8 chUtTrainNum = 0u;
	UINT16 szTrainId[TRAIN_SUM_MAX_IN_OC] = { 0u };
	UINT8 chTrainIndex = 0u;
	UINT8 chAcNum = 0u;
	UINT16 szAcId[MAX_AC_IN_TRAIN] = { 0u };
	UINT8 chAcIndex = 0u;
	UINT8 chFunRtn = CI_ERROR;
	UINT8 chDir = 0u;
	UINT8 chIndex = 0u;

	/* 第一步：将本周期断通信的降级车落到计轴区段 */
	chUtTrainNum = ToaGetLoseCommTrainId(szTrainId);
	for (chTrainIndex = 0u; chTrainIndex < chUtTrainNum; chTrainIndex++)
	{
		chIndex = (UINT8)(szTrainId[chTrainIndex] & 0x00ffu);
		if (FLAG_UNSET == g_trainFlag[chIndex])
		{
			chDir = GetTrainDir(szTrainId[chTrainIndex]);
			chAcNum = ToaGetAcInTrain(szTrainId[chTrainIndex], szAcId);
			if ((0u < chAcNum) && (MAX_AC_IN_TRAIN >= chAcNum))
			{
				chFunRtn = ToaAddUtTrain(szTrainId[chTrainIndex], chDir, chAcNum, szAcId);
				if (CI_SUCCESS == chFunRtn)
				{
					for (chAcIndex = 0u; chAcIndex < chAcNum; chAcIndex++)
					{
						(void)ToaAddAcMapElm(szAcId[chAcIndex], szTrainId[chTrainIndex], TOA_TYPE_UT);
					}
				}
				else
				{
					;
				}
			}
			else
			{
				;
			}
		}
		else
		{
			; /* 已为该列车完成初始化 */
		}
	}

	/* 第二步：自动解锁车尾采集空闲区段 */
	ToaDeleteUtTrainTailFreeAc();

	/* 第三步：命令处理 */
	ToaCmdProc();

	/* 第四步：折返处理 */
	(void)ToaUtReturnProc();

	/* 第五步：延伸 */
	ToaUtPathCal();
}

/**
* @brief 删除元素
* @param wAcIndex 计轴区段映射表下标
* @param wTrainId 列车ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaDeleteAcMapElm(UINT16 wAcIndex, UINT16 wTrainId)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chTrainIndex = 0u;
	UINT8 chIndex = 0u;

	if ((0u != wTrainId) && (AXIS_SECTION_SUM_MAX > wAcIndex))
	{
		for (chTrainIndex = 0u; chTrainIndex < g_acMap[wAcIndex].chTrainNum; chTrainIndex++)
		{
			if (wTrainId == g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId)
			{
				g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId = 0u;
				g_acMap[wAcIndex].strTrain[chTrainIndex].chTrainType = TOA_TYPE_INVALID;
				break;
			}
		}

		if (chTrainIndex == g_acMap[wAcIndex].chTrainNum)
		{
			; /* 计轴区段上无对应列车 */
		}
		else if (chTrainIndex == (g_acMap[wAcIndex].chTrainNum - 1u))
		{
			/* 需删除元素是数组中最后一个元素 */
			g_acMap[wAcIndex].chTrainNum--;
			chRtn = CI_SUCCESS;
		}
		else
		{
			for (chIndex = chTrainIndex; chIndex < (g_acMap[wAcIndex].chTrainNum - 1u); chIndex++)
			{
				g_acMap[wAcIndex].strTrain[chIndex].wTrainId = g_acMap[wAcIndex].strTrain[chIndex + 1u].wTrainId;
				g_acMap[wAcIndex].strTrain[chIndex].chTrainType = g_acMap[wAcIndex].strTrain[chIndex + 1u].chTrainType;
			}
			g_acMap[wAcIndex].chTrainNum--;
			chRtn = CI_SUCCESS;
		}
	}
	else
	{
		; /* 入参不合法 */
	}

	debug_infor_printf((const)"Toa ac:%d delete train:%x\n", wAcIndex, wTrainId);

	return chRtn;
}

/**
* @brief 添加元素
* @param wAcIndex 计轴区段映射表下标
* @param wTrainId 列车ID
* @param chType   列车类型
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaAddAcMapElm(UINT16 wAcIndex, UINT16 wTrainId, UINT8 chType)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chTrainIndex = 0u;

	for (chTrainIndex = 0u; chTrainIndex < g_acMap[wAcIndex].chTrainNum; chTrainIndex++)
	{
		if (wTrainId == g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId)
		{
			/* 列车已在该计轴区段上 */
			break;
		}
	}

	if ((chTrainIndex == g_acMap[wAcIndex].chTrainNum) && (MAX_TRAIN_ON_AC > g_acMap[wAcIndex].chTrainNum))
	{
		/* 添加元素 */
		g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId = wTrainId;
		g_acMap[wAcIndex].strTrain[chTrainIndex].chTrainType = chType;
		g_acMap[wAcIndex].chTrainNum++;
		chRtn = CI_SUCCESS;
		debug_infor_printf((const)"Toa ac:%d add train:%x type:%d\n", wAcIndex, wTrainId, chType);
	}
	else
	{
		; /* 列车已在该计轴区段上 */
	}
	return chRtn;
}

/**
* @brief 获取列车占压计轴区段
* @param wTrainId 列车ID
* @param szAcId 列车占压计轴区段
* @return 列车占压计轴区段数量
* @note：内部优化 20220808 入参检查
*/
static UINT8 ToaGetAcInTrain(UINT16 wTrainId, UINT16 szAcId[MAX_AC_IN_TRAIN])
{
	LOD_STRU strStart = { 0u };
	LOD_STRU strEnd = { 0u };
	UINT8 chRtn = 0u;

	/** 入参检查*/
	if (NULL != szAcId)
	{
		strEnd.Lnk = GetTrainSafeHeadLink(wTrainId);
		strEnd.Off = GetTrainSafeHeadOffset(wTrainId);
		strEnd.Dir = GetTrainSafeHeadDir(wTrainId);
		strStart.Lnk = GetTrainSafeTailLink(wTrainId);
		strStart.Off = GetTrainSafeTailOffset(wTrainId);
		strStart.Dir = GetTrainSafeTailDir(wTrainId);

		chRtn = elm_PrepareACBtwPoints(strStart, strEnd, szAcId);
	}
	else
	{
		chRtn = 0u;
	}

	return chRtn;
}

/**
* @brief 获取列车安全位置
* @param wTrainId 列车ID
* @param szAcId 列车占压计轴区段
* @return 列车占压计轴区段数量
* @note：
*/
static UINT8 ToaGetTrainLoc(UINT16 wTrainId, TrainLocStruct * pLoc)
{
	UINT8 chRtnVal = CI_ERROR;
	UINT16 wTrainID = (UINT16)(0x1400u + (wTrainId & 0x00ffu));

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

/**
* @brief 添加故障车
* @param wTrainId 列车ID
* @param chDir UT列车方向
* @param szAcId 列车占压计轴区段
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：内部优化 20220808 入参检查
*/
static UINT8 ToaAddUtTrain(UINT16 wTrainId, UINT8 chDir, UINT8 chAcNum, UINT16 szAcId[MAX_AC_IN_TRAIN])
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chIndex = 0u;

	/** 入参检查*/
	if (NULL != szAcId)
	{
		if (((DIR_SAME == chDir) || (DIR_CONVERT == chDir)) && (0u != wTrainId) && (TRAIN_SUM_MAX > g_utTrainSum))
		{
			g_utTrain[g_utTrainSum].wTrainId = wTrainId;
			g_utTrain[g_utTrainSum].dwUtCyc = Get2oo2CurCycleNum();
			g_utTrain[g_utTrainSum].chDir = chDir;
			g_utTrain[g_utTrainSum].chAcNum = chAcNum;
			chRtn = CommonMemCpy(g_utTrain[g_utTrainSum].szAcId, (UINT32)(sizeof(UINT16) * chAcNum), szAcId, (UINT32)(sizeof(UINT16) * chAcNum));
		}
		else
		{
			;
		}

		if (CI_SUCCESS == chRtn)
		{
			chIndex = (UINT8)(wTrainId & 0x00ffu);
			if (TRAIN_SUM_MAX > chIndex)
			{
				g_trainFlag[chIndex] = FLAG_SET;
				g_utTrainSum++;
				debug_infor_printf((const)"Toa add ut train:%x\n", wTrainId);
			}
			else
			{
				chRtn = CI_ERROR;
			}
		}
		else
		{
			;
		}
	}
	else
	{
		chRtn = CI_ERROR;
	}

	return chRtn;
}

/**
* @brief 删除故障车
* @param wTrainId 列车ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaDeleteUtTrain(UINT16 wTrainId)
{
	UINT8 chTrainIndex = 0u;
	UINT8 chRtn = CI_ERROR;
	UINT8 chIndex = 0u;
	UINT16 wAcIndex = 0u;
	UINT8 chCommState = 0u;

	if (0u != wTrainId)
	{
		for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
		{
			if (wTrainId == g_utTrain[chTrainIndex].wTrainId)
			{
				break;
			}
		}

		if (chTrainIndex == g_utTrainSum)
		{
			; /* 没找到该降级车 */
		}
		else if (chTrainIndex == (g_utTrainSum - 1u))
		{
			/* 最后一个元素直接删除 */
			g_utTrainSum--;
			chRtn = CI_SUCCESS;
		}
		else
		{
			for (chIndex = chTrainIndex; chIndex < (g_utTrainSum - 1u); chIndex++)
			{
				g_utTrain[chIndex].wTrainId = g_utTrain[chIndex + 1u].wTrainId;
				g_utTrain[chIndex].dwUtCyc = g_utTrain[chIndex + 1u].dwUtCyc;
				g_utTrain[chIndex].chDir = g_utTrain[chIndex + 1u].chDir;
				g_utTrain[chIndex].chAcNum = g_utTrain[chIndex + 1u].chAcNum;
				(void)CommonMemCpy(g_utTrain[chIndex].szAcId, (UINT32)(sizeof(UINT16) * MAX_AC_IN_TRAIN), g_utTrain[chIndex + 1u].szAcId, (UINT32)(sizeof(UINT16) * MAX_AC_IN_TRAIN));
			}
			g_utTrainSum--;
			chRtn = CI_SUCCESS;
			debug_infor_printf((const)"Toa delete ut train:%x\n", wTrainId);
		}
	}
	else
	{
		;
	}

	if (CI_SUCCESS == chRtn)
	{
		/* 清除计轴区段占压信息 */
		for (wAcIndex = 0u; wAcIndex < AXIS_SECTION_SUM_MAX; wAcIndex++)
		{
			for (chTrainIndex = 0u; chTrainIndex < g_acMap[wAcIndex].chTrainNum; chTrainIndex++)
			{
				if (g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId == wTrainId)
				{
					(void)ToaDeleteAcMapElm(wAcIndex, g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId);
					break;
				}
			}
		}
		chIndex = (UINT8)(wTrainId & 0x00ffu);
		g_trainFlag[chIndex] = FLAG_UNSET;
		chCommState = GetTrainTransitmitStat(wTrainId);
		if (TRAIN_COMM_STATE_BAD == chCommState)
		{
			(void)SetTrainTransmitStat(wTrainId, TRAIN_COMM_STATE_UNKNOWN);
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}

	return chRtn;
}

/**
* @brief 故障车折返处理
* @param 无
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaUtReturnProc(void)
{
	UINT8 chTrainIndex = 0u;
	UINT16 wAcId = 0u;
	UINT16 wRouteId = 0u;
	UINT8 chRouteType = 0u;
	UINT16 wPhyId = 0u;
	UINT16 wLastPhyId = 0u;
	UINT16 wReturnSignalSum = 0u;
	UINT16 * pReturnSignalId = NULL;
	UINT16 wIndex = 0u;
	UINT8 chState = 0u;
	UINT8 chNeedReturn = FLAG_UNSET;
	UINT8 chRtn = CI_ERROR;
	UINT8 chDir = 0u;
	UINT8 SignalCurColor = 0u;		/*指定ID信号机当前显示颜色*/

	for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
	{
		chNeedReturn = FLAG_UNSET;
		wAcId = g_utTrain[chTrainIndex].szAcId[0];
		wPhyId = GetAxisSecRelativePhySecId(wAcId);
		wRouteId = GetPhySecRLockBelongRouteId(wPhyId);
		chRouteType = GetRouteType(wRouteId);
		wLastPhyId = GetRouteLastPhySectionId(wRouteId);
		if ((ROUTE_TYPE_RETURN == chRouteType) && (wPhyId == wLastPhyId))
		{
			wReturnSignalSum = GetRouteReturnSignalSum(wRouteId);
			pReturnSignalId = GetRouteReturnSignalIdBuf(wRouteId);
			if (NULL != pReturnSignalId)
			{
				for (wIndex = 0u; wIndex < wReturnSignalSum; wIndex++)
				{
					SignalCurColor = GetSignalCurColor(pReturnSignalId[wIndex]);
					chState = GetSignalOpenCloseState(SignalCurColor);
					if (SIGNAL_OPEN == chState)
					{
						break;
					}
					else
					{
						;
					}
				}
				if (wIndex < wReturnSignalSum)
				{
					chDir = GetSignalDirection(pReturnSignalId[wIndex]);
					if (chDir != g_utTrain[chTrainIndex].chDir)
					{
						chNeedReturn = FLAG_SET;
					}
					else
					{
						;
					}
				}
				else
				{
					;
				}
			}
			else
			{
				break;
			}
		}
		else
		{
			;
		}

		if (FLAG_SET == chNeedReturn)
		{
			ToaReturnExc(chTrainIndex);
		}
		else
		{
			; /* 继续遍历 */
		}
	}
	if (chTrainIndex < g_utTrainSum)
	{
		;
	}
	else
	{
		chRtn = CI_SUCCESS;
	}

	return chRtn;
}

/**
* @brief 故障车折返执行
* @param wTrainIndex 故障车存储下标
* @return 无
* @note：
*/
static void ToaReturnExc(UINT8 chTrainIndex)
{
	UINT8 chAcNum = 0u;
	UINT16 szTemp[MAX_AC_IN_TRAIN] = { 0u };
	UINT8 chIndex = 0u;
	chAcNum = g_utTrain[chTrainIndex].chAcNum;
	for (chIndex = 0u; chIndex < chAcNum; chIndex++)
	{
		szTemp[chIndex] = g_utTrain[chTrainIndex].szAcId[chAcNum - chIndex - 1u];
	}
	debug_infor_printf((const)"ut train:%x return\n", g_utTrain[chTrainIndex].wTrainId);
	g_utTrain[chTrainIndex].chDir = ~g_utTrain[chTrainIndex].chDir;
	if (MAX_AC_IN_TRAIN > chAcNum)
	{
		(void)CommonMemCpy(g_utTrain[chTrainIndex].szAcId, (UINT32)(sizeof(UINT16) * chAcNum), szTemp, (UINT32)(sizeof(UINT16) * chAcNum));
	}
	else
	{
		;	/*拷贝信息大于拷贝的空间，不进行拷贝*/
	}
}

/**
* @brief 故障占用延伸计算
* @param 无
* @return 无
* @note：
*/
static void ToaUtPathCal(void)
{
	UINT8 chTrainIndex = 0u;
	UINT8 chFunRtn = CI_ERROR;
	UINT16 wAcId = 0u;
	UINT16 wNextAcId = 0u;
	UINT16 wNextPhyId = 0u;
	UINT16 wRLockRouteId = 0U;
	UINT16 wPLockRouteId = 0U;
	UINT8 chAcNum = 0u;
	UINT8 chNextAcNum = 0u;
	UINT16 szNextAcId[AC_MAXCNT_IN_SWITCH] = { 0u };
	UINT8 chDir = 0u;
	UINT8 chLockDir = 0U;
	UINT8 chLockState = 0u;
	UINT8 chLogicNum = 0u;
	UINT16 *pLogicId = NULL;
	LogicTrainResStruct * pstLogicResTrainInfo = NULL;
	UINT8 chResShareFlag = 0u;
	UINT8 chLogIndex = 0u;
	UINT8 chLinkLogicDirUpAndDown = 0U;
	UINT16 wTrainId = 0u;
	UINT8 cDirectionPointFlag = 0U;			/*是否具有方向变化点标志*/

	chLinkLogicDirUpAndDown = GetLinkLogicDirUpAndDown();
	for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
	{
		do
		{
			/* 列车延伸判断 */
			chFunRtn = IsUtPathCanExtend(chTrainIndex);
			if (CI_SUCCESS == chFunRtn)
			{/* UT可延伸，获取延伸下一计轴区段 */
				wTrainId = g_utTrain[chTrainIndex].wTrainId;
				chAcNum = g_utTrain[chTrainIndex].chAcNum;
				wAcId = g_utTrain[chTrainIndex].szAcId[chAcNum - 1u];
				chDir = g_utTrain[chTrainIndex].chDir;
				chNextAcNum = elm_PrepareAdjacentAC(wAcId, chDir, szNextAcId, &cDirectionPointFlag);
				if ((0u == chNextAcNum) || (UINT8_MAX == chNextAcNum))
				{
					chFunRtn = CI_ERROR;
				}
				else
				{

				}
			}
			else
			{
				;/* 不能延伸，遍历下一列UT车 */
			}

			if (CI_SUCCESS == chFunRtn)
			{/* 下一计轴区段锁闭、锁闭方向判断 */
				wNextAcId = szNextAcId[0];
				wNextPhyId = GetAxisSecRelativePhySecId(wNextAcId);
				chLockState = GetPhySecLockState(wNextPhyId);
				chLockDir = GetPhySecLockDirection(wNextPhyId);

				if (chLinkLogicDirUpAndDown == chLockDir)
				{
					chLockDir = DIR_CONVERT;
				}
				else
				{
					chLockDir = DIR_SAME;
				}

				if ((PHYSICAL_SECTION_LOCK_NORMAL == chLockState) || (PHYSICAL_SECTION_LOCK_PROTECT == chLockState))
				{
					if (chLockDir == chDir)
					{
						;
					}
					else
					{
						chFunRtn = CI_ERROR;
					}
				}
				else
				{
					chFunRtn = CI_ERROR;
				}
			}
			else
			{
				;
			}

			/* 没有其他列车占用 */
			if (CI_SUCCESS == chFunRtn)
			{
				chFunRtn = IsAcFree(wNextAcId);
			}
			else
			{
				;
			}

			if (CI_SUCCESS == chFunRtn)
			{/* 延伸区段有该车资源或者为公共资源 */
				chLogicNum = GetAxisSecLogSectionSum(wNextAcId);
				pLogicId = GetAxisSecLogSectionIdBuf(wNextAcId);
				if ((0u != chLogicNum) && (NULL != pLogicId))
				{
					for (chLogIndex = 0u; chLogIndex < chLogicNum; chLogIndex++)
					{
						pstLogicResTrainInfo = GetLogSecTrainInfoById(pLogicId[chLogIndex], wTrainId);
						chResShareFlag = GetLogSecResShareFlag(pLogicId[chLogIndex]);
						if ((NULL != pstLogicResTrainInfo) ||
							(LOGIC_SECTION_RES_SHARE_YES == chResShareFlag))
						{
							break;
						}
						else
						{
							;
						}
					}

					if (chLogIndex < chLogicNum)
					{
						chFunRtn = CI_SUCCESS;
					}
					else
					{
						chFunRtn = CI_ERROR;
					}
				}
				else
				{
					chFunRtn = CI_ERROR;
				}
			}
			else
			{
				;
			}

			/* 延伸执行 */
			if (CI_SUCCESS == chFunRtn)
			{
				if (MAX_AC_IN_TRAIN > chAcNum)
				{
					(void)ToaAddUtTrainAc(wTrainId, wNextAcId);
				}
				else
				{
					;
				}
			}
			else
			{
				;
			}
		}while (CI_SUCCESS == chFunRtn);
	}
}

/**
* @brief 判断UT占用路径是否能进行延伸计算
* @param[in] chTrainIndex UT列车存储下标
* @return CI_SUCCESS:能进行延伸计算；CI_ERROR:不能进行延伸计算
* @note 无
*/
static UINT8 IsUtPathCanExtend(UINT8 chTrainIndex)
{
	UINT8 chRtn = CI_ERROR;
	UINT16 wAcId = 0u;
	UINT8 chIndex = 0u;
	TrainLocStruct strBase = { 0u };
	TrainLocStruct strTemp = { 0u };
	UINT8 chCommState = 0u;
	UINT32 dwCyc = 0u;
	UINT32 dwSysCyc = 0u;
	
	wAcId = g_utTrain[chTrainIndex].szAcId[g_utTrain[chTrainIndex].chAcNum - 1u];

	chRtn = IsAcFree(wAcId);
	if(CI_SUCCESS == chRtn)
	{
		(void)ToaInit();
	}
	else
	{
		if ((AXIS_SECTION_SUM_MAX > wAcId) &&
			(1u == g_acMap[wAcId].chTrainNum) && (g_utTrain[chTrainIndex].wTrainId == g_acMap[wAcId].strTrain[0].wTrainId))
		{/* 计轴区段仅本车一列车 */
			chRtn = CI_SUCCESS;
		}
		else if (1u == g_acMap[wAcId].chTrainNum)
		{
			/* 异常分支 */
			(void)ToaInit();
		}
		else
		{
			dwSysCyc = Get2oo2CurCycleNum();
			if (dwSysCyc == g_utTrain[chTrainIndex].dwUtCyc)
			{
				chRtn = CI_SUCCESS;
			}
			else
			{
				chRtn = CI_ERROR;
			}

			/* 延伸列车安全位置获取 */
			chRtn &= ToaGetTrainLoc(g_utTrain[chTrainIndex].wTrainId, &strBase);
			if (CI_SUCCESS == chRtn)
			{
				for (chIndex = 0u; chIndex < g_acMap[wAcId].chTrainNum; chIndex++)
				{
					if (g_acMap[wAcId].strTrain[chIndex].wTrainId == g_utTrain[chTrainIndex].wTrainId)
					{
						;
					}
					else
					{
						chCommState = GetTrainTransitmitStat(g_acMap[wAcId].strTrain[chIndex].wTrainId);
						if (TRAIN_COMM_STATE_BAD == chCommState)
						{
							dwCyc = ToaGetBreakCyc(g_acMap[wAcId].strTrain[chIndex].wTrainId);
						}
						else
						{
							;
						}
						if ((TRAIN_COMM_STATE_GOOD == chCommState) || (dwSysCyc == dwCyc))
						{
							chRtn = ToaGetTrainLoc(g_acMap[wAcId].strTrain[chIndex].wTrainId, &strTemp);
							chRtn &= ToaIsAFront(&strBase, strBase.startPos.Dir, &strTemp);
						}
						else
						{
							chRtn = CI_ERROR;
						}
						if(CI_ERROR == chRtn)
						{
							break;
						}
						else
						{
							;
						}
					}
				}
			}
			else
			{
				;
			}
		}
	}
	return chRtn;
}

/**
* @brief A车在前
* @param[in] const TrainLocStruct* pTrainA 列车A
* @param[in] const TrainLocStruct* pTrainB 列车B
* @param[in] chDir 方向
* @return CI_SUCCESS:A在前；CI_ERROR:A未在前或判断不出
* @note 无
*/
static UINT8 ToaIsAFront(IN const TrainLocStruct* pTrainA, UINT8 chDir, IN const TrainLocStruct* pTrainB)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chFunRtn = 0u;
	if ((NULL == pTrainA) || (NULL == pTrainB))
	{
		/** 入口参数错误*/
	}
	else if ((EMAP_SAME_DIR != chDir) && (EMAP_CONVER_DIR != chDir))
	{
		/** 入口参数错误*/
	}
	else
	{
		chFunRtn = as_CalcAreaOrder(pTrainA, pTrainB);

		if ((0x01u != chFunRtn) && (0x02u != chFunRtn))
		{
			/** 查询错误*/
		}
		else if (EMAP_SAME_DIR == chDir)
		{
			chRtn = (0x01u == chFunRtn) ? CI_ERROR : CI_SUCCESS;
		}
		else
		{
			chRtn = (0x01u == chFunRtn) ? CI_SUCCESS : CI_ERROR;
		}
	}
	return chRtn;
}

/**
* @brief 获取UT列车断通信周期号
* @param wTrainId 列车ID
* @return 周期号
* @note：
*/
static UINT32 ToaGetBreakCyc(UINT16 wTrainId)
{
	UINT8 chTrainIndex = 0u;
	UINT32 dwCyc = 0u;
	for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
	{
		if (g_utTrain[chTrainIndex].wTrainId == wTrainId)
		{
			dwCyc = g_utTrain[chTrainIndex].dwUtCyc;
			break;
		}
		else
		{
			;
		}
	}
	return dwCyc;
}

/**
* @brief 判断计轴区段是否空闲
* @param wAcIndex 计轴区段存储下标
* @return CI_ERROR:占用；CI_SUCCESS:空闲
* @note：
*/
UINT8 IsAcFree(UINT16 wAcIndex)
{
	UINT8 chRtn = CI_ERROR;

	if (AXIS_SECTION_SUM_MAX > wAcIndex)
	{
		if (0u == g_acMap[wAcIndex].chTrainNum)
		{
			chRtn = CI_SUCCESS;
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}
	return chRtn;
}

/**
* @brief 判断计轴区段序列是否空闲
* @param wTrainId 列车ID
* @param cAcSum 计轴区段数量
* @param pAcIdBuf 计轴区段ID
* @return CI_ERROR:占用；CI_SUCCESS:空闲
* @note：
*/
static UINT8 IsAcListFreeToSet(UINT16 wTrainId, UINT8 cAcSum, UINT16* pAcIdBuf)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 ii = 0u;
	UINT16 wAcIndex = 0u;
	UINT8 chIndex = 0u;
	UINT8 chFunRtn = CI_ERROR;

	if ((0u != cAcSum) && (NULL != pAcIdBuf) && (MAX_AC_IN_TRAIN >= cAcSum))
	{
		chRtn = CI_SUCCESS;
		for (ii = 0u; ii < cAcSum;ii++)
		{
			/* 判断列车是否已在计轴区段上 */
			chFunRtn = IsUtTrainOnAc(wTrainId, pAcIdBuf[ii]);
			if (CI_ERROR == chFunRtn)
			{
				wAcIndex = pAcIdBuf[ii];
				if (AXIS_SECTION_SUM_MAX > wAcIndex)
				{
					if (0u == g_acMap[wAcIndex].chTrainNum)
					{
						; /* 计轴区段无车 */
					}
					else
					{
						for (chIndex = 0u; chIndex < g_acMap[wAcIndex].chTrainNum; chIndex++)
						{/* 遍历计轴区段列车，查找非255的其他列车 */
							if ((g_acMap[wAcIndex].strTrain[chIndex].wTrainId != wTrainId) && (TRAIN_SUM_MAX != g_acMap[wAcIndex].strTrain[chIndex].wTrainId))
							{
								chRtn = CI_ERROR;
								break;
							}
						}
					}
				}
				else
				{
					chRtn = CI_ERROR;
				}

				if (CI_ERROR == chRtn)
				{
					break;
				}
				else
				{
					;
				}
			}
			else
			{
				;
			}
		}
	}

	return chRtn;
}

/**
* @brief 删除UT列车尾部占压计轴区段
* @param wTrainId 列车ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
UINT8 ToaDeleteUtTrainAc(UINT16 wTrainId)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chTrainIndex = 0u;
	UINT8 chIndex = 0u;

	if (0u != wTrainId)
	{
		for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
		{
			if (wTrainId == g_utTrain[chTrainIndex].wTrainId)
			{
				break;
			}
			else
			{
				;
			}
		}

		if (chTrainIndex == g_utTrainSum)
		{
			; /* 无该UT车 */
		}
		else
		{
			/* 仅占用一个计轴区段，直接清除该UT列车 */
			if ((1u == g_utTrain[chTrainIndex].chAcNum) || (0u == g_utTrain[chTrainIndex].chAcNum))
			{
				(void)ToaDeleteUtTrain(g_utTrain[chTrainIndex].wTrainId);
			}
			else
			{
				(void)ToaDeleteAcMapElm(g_utTrain[chTrainIndex].szAcId[0], g_utTrain[chTrainIndex].wTrainId);
				for (chIndex = 0u; chIndex < (g_utTrain[chTrainIndex].chAcNum - 1u); chIndex++)
				{
					g_utTrain[chTrainIndex].szAcId[chIndex] = g_utTrain[chTrainIndex].szAcId[chIndex + 1u];
				}
				g_utTrain[chTrainIndex].chAcNum--;
			}
			chRtn = CI_SUCCESS;
		}
	}
	else
	{
		; /* 入参不合法 */
	}
	return chRtn;
}

/**
* @brief 在UT列车头部追加占压计轴区段
* @param wTrainId 列车ID
* @param wAcId 计轴区段ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
static UINT8 ToaAddUtTrainAc(UINT16 wTrainId, UINT16 wAcId)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chTrainIndex = 0u;
	UINT8 chIndex = 0u;
	UINT8 chAcSwitchNum = 0u;
	UINT8 chState = 0u;

	if ((TRAIN_SUM_MAX != wTrainId) && (0u != wTrainId) && (AXIS_SECTION_SUM_MAX > wAcId))
	{
		for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
		{
			if (wTrainId == g_utTrain[chTrainIndex].wTrainId)
			{/* 找到列车，记录下标，跳出 */
				break;
			}
			else
			{
				;
			}
		}

		if (chTrainIndex == g_utTrainSum)
		{/* 未找到对应UT车 */
			;
		}
		else
		{
			if (MAX_AC_IN_TRAIN > g_utTrain[chTrainIndex].chAcNum)
			{/* 追加占用 */
				chRtn = ToaAddAcMapElm(wAcId, wTrainId, TOA_TYPE_UT);
				g_utTrain[chTrainIndex].szAcId[g_utTrain[chTrainIndex].chAcNum] = wAcId;
				g_utTrain[chTrainIndex].chAcNum++;
			}
			else
			{
				;
			}
		}
	}
	else
	{
		; /* 入参不合法 */
	}
	return chRtn;
}

/**
* @brief 根据列车ID获取列车占压计轴区段序列
* @param wTrainId 列车ID
* @param szAcId 计轴区段ID
* @return 列车占压计轴区段数量
* @note：
*/
UINT8 ToaGetUtTrainAc(UINT16 wTrainId, UINT16 szAcId[MAX_AC_IN_TRAIN])
{
	UINT8 chAcNum = 0u;
	UINT8 chTrainIndex = 0u;
	UINT8 chFunRtn = CI_ERROR;
	
	/** 入参检查*/
	if (NULL != szAcId)
	{
		for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
		{
			if (wTrainId == g_utTrain[chTrainIndex].wTrainId)
			{
				chAcNum = g_utTrain[chTrainIndex].chAcNum;
				if (MAX_AC_IN_TRAIN > chAcNum)
				{
					chFunRtn = CommonMemCpy(szAcId, (UINT32)(sizeof(UINT16) * chAcNum), g_utTrain[chTrainIndex].szAcId, (UINT32)(sizeof(UINT16) * chAcNum));
				}
				else
				{
					;	/*拷贝信息大于拷贝空间，不进行拷贝*/
				}
				break;
			}
			else
			{
				;
			}
		}
		if (CI_ERROR == chFunRtn)
		{
			chAcNum = 0u;
		}
		else
		{
			;
		}
	}
	else
	{
		chAcNum = 0u;
	}
	return chAcNum;
}

/**
* @brief 获取UT列车方向
* @param wTrainId 列车ID
* @return 方向
* @note：
*/
UINT8 ToaGetUtTrainDir(UINT16 wTrainId)
{
	UINT8 chDir = 0u;
	UINT8 chTrainIndex = 0u;

	for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
	{
		if (wTrainId == g_utTrain[chTrainIndex].wTrainId)
		{
			chDir = g_utTrain[chTrainIndex].chDir;
			break;
		}
		else
		{
			;
		}
	}
	
	return chDir;
}

/**
* @brief 刷新UT占压序列（ATS人工设置时使用）
* @param wTrainId 列车ID
* @param chDir UT列车方向
* @param chAcNum 计轴区段数量
* @param szAcId 计轴区段ID
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：内部优化 20220808 入参检查
*/
static UINT8 ToaRefreshUtTrainAc(UINT16 wTrainId, UINT8 chDir, UINT8 chAcNum, UINT16 szAcId[MAX_AC_IN_TRAIN])
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chTrainIndex = 0u;
	UINT8 chIndex = 0u;
	UINT8 chAcSwitchNum = 0u;
	UINT8 chState = 0u;

	/** 入参检查*/
	if (((DIR_SAME == chDir) || (DIR_CONVERT == chDir))
		&& (TRAIN_SUM_MAX != wTrainId) && (0u != wTrainId) 
		&& (MAX_AC_IN_TRAIN >= chAcNum)
		&& (NULL != szAcId))
	{
		for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
		{
			if (wTrainId == g_utTrain[chTrainIndex].wTrainId)
			{
				break;
			}
			else
			{
				;
			}
		}

		if (chTrainIndex == g_utTrainSum)
		{
			chRtn = ToaAddUtTrain(wTrainId, chDir, chAcNum, szAcId);
		}
		else
		{
			g_utTrain[chTrainIndex].chAcNum = chAcNum;
			chRtn = CommonMemCpy(g_utTrain[chTrainIndex].szAcId, (UINT32)(sizeof(UINT16) * chAcNum), szAcId, (UINT32)(sizeof(UINT16) * chAcNum));
		}

		if (CI_SUCCESS == chRtn)
		{
			for (chIndex = 0u; chIndex < chAcNum; chIndex++)
			{
				(void)ToaAddAcMapElm(szAcId[chIndex], wTrainId, TOA_TYPE_UT);
			}
		}
		else
		{
			;
		}
	}
	else
	{
		; /* 入参不合法 */
	}
	return chRtn;
}

/**
* @brief 添加命令
* @param chCmdType 命令类型
* @param wTrainId 列车ID
* @param dwCmdId 命令ID
* @param wTerminalId 终端ID
* @param chVirCi 虚拟联锁ID
* @param dwCmdParam 命令参数
* @return CI_ERROR:失败；CI_SUCCESS:成功
* @note：
*/
UINT8 ToaAddCmd(UINT8 chCmdType, UINT16 wTrainId, UINT32 dwCmdId, UINT16 wTerminalId, UINT8 chVirCi, UINT32 dwCmdParam)
{
	UINT8 chRtn = CI_ERROR;
	if (((TOA_CMD_TYPE_SET == chCmdType) || (TOA_CMD_TYPE_CANCEL_FIRST == chCmdType) || (TOA_CMD_TYPE_CANCEL_SECOND == chCmdType)
		|| (TOA_CMD_TYPE_RESET_FIRST == chCmdType) || (TOA_CMD_TYPE_RESET_SECOND == chCmdType))
		&& (TOA_CMD_MAX > g_cmdNum))
	{
		chRtn = CI_SUCCESS;
	}
	else
	{
		;
	}

	if (CI_SUCCESS == chRtn)
	{
		g_cmdStr[g_cmdNum].chCmdType = chCmdType;
		g_cmdStr[g_cmdNum].wTrainId = wTrainId;
		g_cmdStr[g_cmdNum].dwCmdId = dwCmdId;
		g_cmdStr[g_cmdNum].wTerminalId = wTerminalId;
		g_cmdStr[g_cmdNum].chVirCi = chVirCi;
		g_cmdStr[g_cmdNum].dwCmdParam = dwCmdParam;

		g_cmdNum++;

		debug_infor_printf((const)"Toa add cmd:%x tid:%x cid:%x terid:%x vid:%x param:%x\n", chCmdType, wTrainId, dwCmdId, wTerminalId, chVirCi, dwCmdParam);
	}
	else
	{
		;
	}
	return chRtn;
}

/**
* @brief 命令处理
* @note：
*/
static void ToaCmdProc(void)
{
	UINT8 chIndex = 0u;
	UINT8 chCmdType = 0u;
	UINT8 chDir = 0u;
	UINT16 wTrainId = 0u;
	UINT8 chFunRtn = CI_FALSE;
	UINT8 chBelongVirCi = 0u;
	UINT8 chVirCi = 0u;
	UINT8 chOrderCheck = CI_ERROR;
	UINT8 chCheckRtn = AFFIRM_FAIL;
	UINT32 dwCmdId = 0u;
	UINT16 wTerminalId = 0u;
	UINT8 startFLockFlag = 0u;
	UINT8 allSwitchYLockFlag = 0u;
	UINT16 wCmdDeviceId = 0u;
	UINT8 chCmdDeviceType = 0u;
	UINT8 chTiocSysMode;

	allSwitchYLockFlag = GetAllSwitchYLockFlag();
	startFLockFlag = GetStartFLockFlag();
	chTiocSysMode = GetTiocSystemMode();
	if ((REVERSE_MODE_MAIN != chTiocSysMode) || (CI_START_FLOCK_YES == startFLockFlag) || (CI_ALL_SWITCH_YLOCK_YES == allSwitchYLockFlag))
	{
		;
	}
	else
	{
		for (chIndex = 0u; chIndex < g_cmdNum; chIndex++)
		{
			chCmdType = g_cmdStr[chIndex].chCmdType;
			chDir = (UINT8)(g_cmdStr[chIndex].dwCmdParam & 0xffu);
			chCmdDeviceType = (UINT8)(g_cmdStr[chIndex].dwCmdParam >> 8u);
			wCmdDeviceId = (UINT16)(g_cmdStr[chIndex].dwCmdParam >> 16u);
			wTrainId = g_cmdStr[chIndex].wTrainId;
			chVirCi = g_cmdStr[chIndex].chVirCi;
			dwCmdId = g_cmdStr[chIndex].dwCmdId;
			wTerminalId = g_cmdStr[chIndex].wTerminalId;

			switch (chCmdType)
			{
			case TOA_CMD_TYPE_SET:
				SetBreakPhySecWithTrainInfo(wCmdDeviceId, wTrainId, chDir);
				break;
			case TOA_CMD_TYPE_CANCEL_FIRST:
				if (TOA_NORMAL == g_initStatus)
				{
					/* 取消故障列车一次*/
					chFunRtn = CheckTheDevIsNotOfDiffLine(CI_DEVICE_TYPE_PHYSEC, wCmdDeviceId);
					if (CI_TRUE == chFunRtn)
					{
						chBelongVirCi = GetPhySecBelongVirCiId(wCmdDeviceId);
						chOrderCheck = CheckOrderWhetherDoing(chVirCi, chBelongVirCi, chCmdType, wCmdDeviceId);
						if (CI_SUCCESS == chOrderCheck)
						{
							chCheckRtn = AFFIRM_SUCCESS;
						}
						else
						{
							chCheckRtn = AFFIRM_FAIL;
						}
					}
					else
					{
						chCheckRtn = AFFIRM_FAIL;
					}
					SetCiSendCmdBackData_OrderBack(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, RESPONSE_FIRST, chCheckRtn, chVirCi);
				}
				else
				{
					;
				}
				break;
			case TOA_CMD_TYPE_CANCEL_SECOND:
				if (TOA_NORMAL == g_initStatus)
				{
					chCheckRtn = CheckSecondOrderValid(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, chVirCi);
					if (CI_SUCCESS == chCheckRtn)
					{
						chCheckRtn = CheckTheDevIsNotOfDiffLine(CI_DEVICE_TYPE_PHYSEC, wCmdDeviceId);

						if (CI_TRUE == chCheckRtn)
						{
							chBelongVirCi = GetPhySecBelongVirCiId(wCmdDeviceId);
							chOrderCheck = CheckOrderWhetherDoing(chVirCi, chBelongVirCi, chCmdType, wCmdDeviceId);
							if (CI_SUCCESS == chOrderCheck)
							{
								chCheckRtn = AFFIRM_SUCCESS;
								/* 取消故障列车处理 */
								UnLockBreakPhySecWithTrainInfo(wCmdDeviceId, wTrainId, chDir);
							}
							else
							{
								chCheckRtn = AFFIRM_FAIL;
							}
						}
						else
						{
							chCheckRtn = AFFIRM_FAIL;
						}
					}
					else
					{
						chCheckRtn = AFFIRM_FAIL;
					}
					SetCiSendCmdBackData_OrderBack(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, RESPONSE_SECOND, chCheckRtn, chVirCi);
				}
				else
				{
					;
				}
				break;
			case TOA_CMD_TYPE_RESET_FIRST:
				if (TOA_INIT == g_initStatus)
				{
					SetCiSendCmdBackData_OrderBack(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, RESPONSE_FIRST, AFFIRM_SUCCESS, chVirCi);
				}
				else
				{
					SetCiSendCmdBackData_OrderBack(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, RESPONSE_FIRST, AFFIRM_FAIL, chVirCi);
				}
				break;
			case TOA_CMD_TYPE_RESET_SECOND:
				if (TOA_INIT == g_initStatus)
				{
					chCheckRtn = CheckSecondOrderValid(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, chVirCi);
					if (CI_SUCCESS == chCheckRtn)
					{
						ToaUnlock();

						SetCiSendCmdBackData_OrderBack(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, RESPONSE_SECOND, AFFIRM_SUCCESS, chVirCi);
					}
					else
					{
						SetCiSendCmdBackData_OrderBack(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, RESPONSE_SECOND, AFFIRM_FAIL, chVirCi);
					}
				}
				else
				{
					SetCiSendCmdBackData_OrderBack(dwCmdId, wCmdDeviceId, chCmdDeviceType, wTerminalId, chCmdType, RESPONSE_SECOND, AFFIRM_FAIL, chVirCi);
				}
				break;
			default:
				/*错误或不可达分支*/
				break;
			}
		}
	}
	/* 执行完毕清除命令 */
	ToaClearCmd();
}

/*
* @brief 设置故障物理区段列车占压
* @param const UINT16 wPhySecId 物理区段ID
*        const UINT16 wTrainId 列车编号
*        const UINT16 wTrainDir 列车方向
* @note 创建 lxc 20220617
*/
static void SetBreakPhySecWithTrainInfo(const UINT16 wPhySecId, const UINT16 wTrainId, const UINT8 chDir)
{
	UINT16 wAxisSecId = 0u;
	UINT8 cKeepWorkFlag = CI_ERROR;

	UINT8 cASASum = 0u;
	UINT16 szASAIdBuf[MAX_AC_IN_TRAIN] = { 0u };
	UINT8 cTrainDir = 0U;
	UINT8 cASBSum = 0u;
	UINT16 szASBIdBuf[MAX_AC_IN_TRAIN] = { 0u };

	UINT8 cAxisSecSum = 0u;
	UINT16 szAxisSecIdBuf[MAX_AC_IN_TRAIN] = { 0u };
	UINT8 chLinkLogicDirUpAndDown = 0U;
	UINT8 ii = 0u;
	UINT16 wTmpPhySecId = 0u;
	UINT8 cPhySecLockSatae = PHYSICAL_SECTION_LOCK_NO;
	UINT8 cPhySecLockDir = CI_SYSTEM_DIRECTION_NONE;
	UINT8 cPhySecLockLinkDir = DIR_INVALID;
	UINT8 cTrainTrainSitmitStat = TRAIN_COMM_STATE_UNKNOWN;
	UINT8 cLocalTrainDir = TRAIN_DIR_DEF;
	UINT16 wRouteId = 0u;

	
	chLinkLogicDirUpAndDown = GetLinkLogicDirUpAndDown();

	if (((EMAP_SAME_DIR == chDir) || (EMAP_CONVER_DIR == chDir))
		&&((0x55u == chLinkLogicDirUpAndDown) || (0xAAu == chLinkLogicDirUpAndDown)))
	{
		cKeepWorkFlag = CI_SUCCESS;
		if (chLinkLogicDirUpAndDown == chDir)
		{
			cTrainDir = DIR_CONVERT;
		}
		else
		{
			cTrainDir = DIR_SAME;
		}
	}
	else
	{
		cKeepWorkFlag = CI_ERROR;
	}

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 获取列车ID与类型，判断是否存在的通信车 */
		cTrainTrainSitmitStat = GetTrainTransitmitStat(wTrainId);
		if (TRAIN_COMM_STATE_GOOD != cTrainTrainSitmitStat)
		{
			/* 获取数据失败情况 */
			if (CI_ERROR == cTrainTrainSitmitStat)
			{
				
				cKeepWorkFlag = CI_ERROR;
			}
			/* 其他通信故障情况 */
			else 
			{
				cKeepWorkFlag = CI_SUCCESS;
			}
		}
		else
		{
			/* 失败 */
			cKeepWorkFlag = CI_ERROR;
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_TRAIN_DIR_ERR, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);
		}
	}
	else
	{
		;
	}
	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 通过物理区段，获取计轴区段 */
		wAxisSecId = GetAxisSecIdByPhySecIdAndSwSta(wPhySecId);
		if (UINT16_MAX == wAxisSecId)
		{
			/* 拓扑关系检查失败*/
			cKeepWorkFlag = CI_ERROR;
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_DISCONTINUITY, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);

		}
		else
		{
			cKeepWorkFlag = CI_SUCCESS;
		}
	}
	else
	{
		;
	}

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		cKeepWorkFlag = IsAcFreeToSet(wTrainId, wAxisSecId);
		if (CI_ERROR == cKeepWorkFlag)
		{
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_OTHER_CT, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 列车存在，判断与已存在的列车是否方向一致 */
		cLocalTrainDir = ToaGetUtTrainDir(wTrainId);
		cASBSum = ToaGetUtTrainAc(wTrainId, szASBIdBuf);

		if ((DIR_SAME == cTrainDir) || (DIR_CONVERT == cTrainDir))
		{
			if ((0u != cASBSum) && (cTrainDir != cLocalTrainDir))
			{
				/* 与既有UT车方向不一致 */
				cKeepWorkFlag = CI_ERROR;
			}
			else
			{
				;
			}
		}
		else
		{
			/* 方向校验失败 */
			cKeepWorkFlag = CI_ERROR;
		}

		if (CI_ERROR == cKeepWorkFlag)
		{
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_TRAIN_DIR_ERR, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);
		}
		else
		{
		}
	}
	else
	{
		;
	}

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 获取设置之后连通的计轴区段序列,传入两段列车计轴区段 */
		cASASum = 1u;
		szASAIdBuf[0] = wAxisSecId;

		if (0u == cASBSum)
		{
			szAxisSecIdBuf[0] = wAxisSecId;
			cAxisSecSum = 1u;
		}
		else
		{
			cAxisSecSum = GetAxisSecListByStartingAndEnd(cASASum, szASAIdBuf, cASBSum, szASBIdBuf, cTrainDir, szAxisSecIdBuf);
		}

		if (0u == cAxisSecSum)
		{
			/* 拓扑关系检查失败 */
			cKeepWorkFlag = CI_ERROR;
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_DISCONTINUITY, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 连通的序列内是否存在其他列车 */
		cKeepWorkFlag = IsAcListFreeToSet(wTrainId, cAxisSecSum, szAxisSecIdBuf);

		if (CI_ERROR == cKeepWorkFlag)
		{
			cKeepWorkFlag = CI_ERROR;
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_OTHER_CT, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 连通的序列内物理区段锁闭方向是否与列车方向一致 */
		for (ii = 0u; ii < cAxisSecSum; ii++)
		{
			/* 获取计轴区段关联的物理区段 */
			wTmpPhySecId = GetAxisSecRelativePhySecId(szAxisSecIdBuf[ii]);
			cPhySecLockSatae = GetPhySecLockState(wTmpPhySecId);
			cPhySecLockDir = GetPhySecLockDirection(wTmpPhySecId);

			if (chLinkLogicDirUpAndDown == cPhySecLockDir)
			{
				cPhySecLockLinkDir = DIR_CONVERT;
			}
			else
			{
				cPhySecLockLinkDir = DIR_SAME;
			}
			if ((0u != wTmpPhySecId) && (UINT16_MAX != wTmpPhySecId))
			{
				if ((PHYSICAL_SECTION_LOCK_START == cPhySecLockSatae)
					|| (PHYSICAL_SECTION_LOCK_EXCEPT == cPhySecLockSatae))
				{
					cKeepWorkFlag = CI_ERROR;
				}
				else if ((PHYSICAL_SECTION_LOCK_NO != cPhySecLockSatae) && (cPhySecLockLinkDir != cTrainDir))
				{
					wRouteId = GetPhySecPLockBelongRouteId(wTmpPhySecId);
					if (0u == wRouteId)
					{
						wRouteId = GetPhySecRLockBelongRouteId(wTmpPhySecId);
					}
					else
					{
						;
					}
					/* 锁闭方向不一致 */
					cKeepWorkFlag = CI_ERROR;
				}
				else
				{
					/*无操作*/
				}
			}
			else
			{
				;
			}

			if (CI_ERROR == cKeepWorkFlag)
			{
				SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_LOOK_DIR_ERR, CI_DEVICE_TYPE_ROUTE, wRouteId, 0u, 0u, wTrainId);

				break;
			}
			else
			{
				;
			}
		}
	}
	else
	{
		;
	}


	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 设置故障车位置 */
		cKeepWorkFlag = ToaRefreshUtTrainAc(wTrainId, cTrainDir, cAxisSecSum, szAxisSecIdBuf);

		if (CI_ERROR == cKeepWorkFlag)
		{
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_SPE_DISCONTINUITY, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}
}

/*
* @brief 取消故障物理区段列车占压
* @param const UINT16 wPhySecId 物理区段ID
*        const UINT16 wTrainId 列车编号
*        const UINT16 wTrainDir 列车方向
* @note 创建 lxc 20220617
*/
static void UnLockBreakPhySecWithTrainInfo(const UINT16 wPhySecId, const UINT16 wTrainId, const UINT8 cTrainDir)
{
	UINT16 wAxisSecId = 0u;
	UINT8 cKeepWorkFlag = CI_ERROR;
	UINT8 sendLevel = ESEND_LEVEL_ATS;
	UINT8 functionId = 0u;

	UINT8 cAxisSecSum = 0u;
	UINT16 szAxisSecIdBuf[MAX_AC_IN_TRAIN] = { 0u };

	UINT8 chIndex = 0u;

	UINT16 wPhyId = 0u;
	UINT8 chOccState = 0u;
	UINT8 chSwitchNum = 0u;

	/* 通过物理区段，获取计轴区段 */
	wAxisSecId = GetAxisSecIdByPhySecIdAndSwSta(wPhySecId);
	if (UINT16_MAX == wAxisSecId)
	{
		/* 道岔状态错误 */
		cKeepWorkFlag = CI_ERROR;
		SetCiSendCmdBackInfoWithTrainId(CI_BACK_CPE_PHYSEC_ID_ERR, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);

	}
	else
	{
		cKeepWorkFlag = CI_SUCCESS;
	}

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 获取列车的计轴区段序列 */
		cAxisSecSum = ToaGetUtTrainAc(wTrainId, szAxisSecIdBuf);

		if (0u == cAxisSecSum)
		{
			/* 是否存在该车 */
			cKeepWorkFlag = CI_ERROR;
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_CPE_TRAIN_ID_ERR, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);

		}
		else if (wAxisSecId != szAxisSecIdBuf[0])
		{
			/* 判断是否为列车车尾 */
			cKeepWorkFlag = CI_ERROR;
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_CPE_PHYSEC_ID_ERR, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);

		}
		else
		{
			; /* 成功 */
		}

	}

#if 0
	/* 岔区占用且仅有此车占用，不可解锁 */
	if (CI_SUCCESS == cKeepWorkFlag)
	{
		chSwitchNum = GetAxisSwitchSum(wAxisSecId);
		chOccState = GetPhySecCurOccupyState(wPhySecId);
		if ((0u != chSwitchNum) && (SECTION_OCCUPY_YES == chOccState) && (1u == g_acMap[wAxisSecId].chTrainNum))
		{
			cKeepWorkFlag = CI_ERROR;
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}
#endif

	if (CI_SUCCESS == cKeepWorkFlag)
	{
		/* 取消物理区段故障列车信息 */
		cKeepWorkFlag = ToaDeleteUtTrainAc(wTrainId);
		if (CI_ERROR == cKeepWorkFlag)
		{
			SetCiSendCmdBackInfoWithTrainId(CI_BACK_CPE_PHYSEC_ID_ERR, CI_DEVICE_TYPE_PHYSEC, wPhySecId, 0u, 0u, wTrainId);

		}
		else
		{
			chIndex = ToaGetUtIndex(wTrainId);
			if (TRAIN_SUM_MAX_IN_OC != chIndex)
			{
				wPhyId = GetAxisSecRelativePhySecId(g_utTrain[chIndex].szAcId[0]);
				(void)CancelOutFirstFaultOccUnlock(wPhyId);
			}
			else
			{
				;
			}
		}
	}
}

/*
* @brief 物理区段是否空闲
* @param wPhyId 物理区段ID
* @return CI_ERROR:占用；CI_SUCCESS:空闲
* @note 
*/
UINT8 IsPhyFree(UINT16 wPhyId)
{
	UINT8 chAcNum = 0u;
	UINT16 * pAcId = NULL;
	UINT8 chIndex = 0u;
	UINT8 chRtn = CI_ERROR;
	
	chAcNum = GetPAxisSectionSum(wPhyId);
	pAcId = GetPAxisSectionIdBuf(wPhyId);

	if (0u == chAcNum) 
	{
		;
	}
	else
	{
		for (chIndex = 0u; chIndex < chAcNum; chIndex++)
		{
			chRtn = IsAcHaveNoBadTrain(pAcId[chIndex]);
			if (CI_ERROR == chRtn)
			{
				break;
			}
			else
			{
				;
			}
		}
	}
	return chRtn;
}

/*
* @brief 获取当前降级车数量
* @param 无
* @return 当前降级车数量
* @note
*/
UINT8 ToaGetUtTrainNum(void)
{
	return g_utTrainSum;
}

/*
* @brief 获取当前降级车ID数组
* @param szUtId ID缓冲区
* @return CI_ERROR:获取失败；CI_SUCCESS:获取成功
* @note 内部优化 20220808 入参检查
*/
UINT8 ToaGetUtTrainIdBuf(UINT16 szUtId[TRAIN_SUM_MAX])
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chIndex = 0u;

	/** 入参检查*/
	if (NULL != szUtId)
	{
		if (TRAIN_SUM_MAX > g_utTrainSum)
		{
			for (chIndex = 0u; chIndex < g_utTrainSum; chIndex++)
			{
				if (0u != g_utTrain[chIndex].wTrainId)
				{
					szUtId[chIndex] = g_utTrain[chIndex].wTrainId;
				}
				else
				{
					break;
				}
			}

			if (chIndex == g_utTrainSum)
			{
				chRtn = CI_SUCCESS;
			}
			else
			{
				;
			}
		}
		else
		{
			;
		}
	}
	else
	{

	}
	return chRtn;
}

/*
* @brief 获取指定物理区段降级车数量
* @param wPhyId 物理区段ID
* @return 降级车数量
TRAIN_SUM_MAX：失败
* @note
*/
UINT8 ToaGetPhyUtNum(UINT16 wPhyId)
{
	UINT8 chAcNum = 0u;
	UINT16 * pAcId = NULL;
	UINT8 chRtn = TRAIN_SUM_MAX;
	UINT8 chIndex = 0u;
	UINT8 chTrainIndex = 0u;
	chAcNum = GetPAxisSectionSum(wPhyId);
	pAcId = GetPAxisSectionIdBuf(wPhyId);
	if(0u == chAcNum)
	{
		;
	}
	else
	{
		chRtn = 0u;
		for (chIndex = 0u; chIndex < chAcNum; chIndex++)
		{
			for (chTrainIndex = 0u; chTrainIndex < g_acMap[pAcId[chIndex]].chTrainNum; chTrainIndex++)
			{
				if (TOA_TYPE_UT == g_acMap[pAcId[chIndex]].strTrain[chTrainIndex].chTrainType)
				{
					chRtn++;
				}
				else
				{
					;
				}
			}
		}
	}
	return chRtn;
}

/*
* @brief 获取指定物理区段降级车ID
* @param wPhyId 物理区段ID
* @param szUtId 列车ID缓冲区
* @return CI_SUCCESS:获取成功；CI_ERROR:获取失败
* @note 内部优化 20220808 入参检查
*/
UINT8 ToaGetPhyUtId(UINT16 wPhyId, UINT16 szUtId[TRAIN_SUM_MAX])
{
	UINT8 chAcNum = 0u;
	UINT16 * pAcId = NULL;
	UINT8 chRtn = CI_ERROR;
	UINT8 chIndex = 0u;
	UINT8 chTrainIndex = 0u;
	UINT8 chUtNum = 0u;
	chAcNum = GetPAxisSectionSum(wPhyId);
	pAcId = GetPAxisSectionIdBuf(wPhyId);
	/** 入参检查*/
	if ((0u == chAcNum) || (NULL == szUtId))
	{
		;
	}
	else
	{
		for (chIndex = 0u; chIndex < chAcNum; chIndex++)
		{
			for (chTrainIndex = 0u; chTrainIndex < g_acMap[pAcId[chIndex]].chTrainNum; chTrainIndex++)
			{
				if (TOA_TYPE_UT == g_acMap[pAcId[chIndex]].strTrain[chTrainIndex].chTrainType)
				{
					szUtId[chUtNum++] = g_acMap[pAcId[chIndex]].strTrain[chTrainIndex].wTrainId;
				}
				else
				{
					;
				}
			}
		}
		chRtn = CI_SUCCESS;
	}
	return chRtn;
}

/*
* @brief 清除命令
* @param 无
* @return 无
* @note
*/
void ToaClearCmd(void)
{
	g_cmdNum = 0u;
	(void)CommonMemSet(g_cmdStr, (UINT32)(sizeof(ToaCmdStruct) * TOA_CMD_MAX), 0u, (UINT32)(sizeof(ToaCmdStruct) * TOA_CMD_MAX));
}

/**
* @brief 获取当前TIOC所有的通信车列车ID
* @param[out] szTrainId 列车ID缓存
* @return TIOC范围内通信列车数量
*/
static UINT8 ToaGetCommTrainId(UINT16 szTrainId[TRAIN_SUM_MAX_IN_OC])
{
	/*- 局部变量定义 */
	UINT8 chTrainNum = 0u;
	UINT8 chIndex = 0u;
	UINT16 wTrainId = 0u;
	UINT8 chTransmitState = 0u;

	/** 入口参数校验*/
	if (NULL == szTrainId)
	{
		/** 入口参数错误 */
		;
	}
	else
	{
		/** 获取通信列车 */
		for (chIndex = 0u; chIndex < TRAIN_SUM_MAX; chIndex++)
		{
			/** 获取列车类型 + ID*/
			wTrainId = GetTrainId(chIndex);

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

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

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

/**
* @brief 获取当前TIOC所有的丢失通信车列车ID
* @param[out] szTrainId 列车ID缓存
* @return TIOC范围内丢失通信列车数量
*/
static UINT8 ToaGetLoseCommTrainId(UINT16 szTrainId[TRAIN_SUM_MAX_IN_OC])
{
	/*- 局部变量定义 */
	UINT8 chTrainNum = 0u;
	UINT8 chIndex = 0u;
	UINT16 wTrainId = 0u;
	UINT8 chTransmitState = 0u;

	/** 入口参数校验*/
	if (NULL == szTrainId)
	{
		/** 入口参数错误 */
		;
	}
	else
	{
		/** 获取通信列车 */
		for (chIndex = 0u; chIndex < TRAIN_SUM_MAX; chIndex++)
		{
			/** 获取列车类型 + ID*/
			wTrainId = GetTrainId(chIndex);

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

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

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

/**
* @brief 计轴区段无故障车判断
* @param wAcIndex 计轴区段存储下标
* @return CI_ERROR:存在故障车；CI_SUCCESS:不存在故障车
* @note：
*/
static UINT8 IsAcHaveNoBadTrain(UINT16 wAcIndex)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chIndex = 0u;

	if (AXIS_SECTION_SUM_MAX > wAcIndex)
	{
		chRtn = CI_SUCCESS;
		for (chIndex = 0u; chIndex < g_acMap[wAcIndex].chTrainNum; chIndex++)
		{
			if (TOA_TYPE_UT == g_acMap[wAcIndex].strTrain[chIndex].chTrainType)
			{
				chRtn = CI_ERROR;
				break;
			}
			else
			{
				;
			}
		}
	}
	else
	{
		;
	}
	return chRtn;
}

/**
* @brief 获取UT列车存储索引
* @param wTrainId 列车ID
* @return TRAIN_SUM_MAX_IN_OC:失败，其他:索引
* @note：
*/
static UINT8 ToaGetUtIndex(UINT16 wTrainId)
{
	UINT8 chIndex = 0u;
	for (chIndex = 0u; chIndex < g_utTrainSum; chIndex++)
	{
		if (g_utTrain[chIndex].wTrainId == wTrainId)
		{
			break;
		}
		else
		{
			;
		}
	}
	if (chIndex == g_utTrainSum)
	{
		chIndex = TRAIN_SUM_MAX_IN_OC;
	}
	else
	{
		;
	}
	return chIndex;
}

/**
* @brief 获取物理区段占压列车
* @param wPhyId 物理区段ID
* @param szUtId 列车ID
* @return MAX_AC_IN_TRAIN:失败，其他:列车数量
* @note：内部优化 20220808 入参检查
*/
UINT8 ToaGetPhyTrain(UINT16 wPhyId, UINT16 szTrainId[MAX_AC_IN_TRAIN])
{
	UINT8 chAcNum = 0u;
	UINT16 *pAcId = NULL;
	UINT8 chAcIndex = 0u;
	UINT8 chTrainIndex = 0u;
	UINT8 chTrainNum = 0u;
	chAcNum = GetPAxisSectionSum(wPhyId);
	pAcId = GetPAxisSectionIdBuf(wPhyId);
	/** 入参检查*/
	if ((NULL != pAcId) && (NULL != szTrainId))
	{
		for (chAcIndex = 0u; chAcIndex < chAcNum; chAcIndex++)
		{
			for (chTrainIndex = 0u; chTrainIndex < g_acMap[pAcId[chAcIndex]].chTrainNum; chTrainIndex++)
			{
				szTrainId[chTrainNum++] = g_acMap[pAcId[chAcIndex]].strTrain[chTrainIndex].wTrainId;
			}
		}
	}
	else
	{
		chTrainNum = MAX_AC_IN_TRAIN;
	}
	return chTrainNum;
}

/**
* @brief 删除UT列车尾部采集空闲带岔区段
* @param 无
* @return 无
* @note：
*/
static void ToaDeleteUtTrainTailFreeAc(void)
{
	UINT8 chTrainIndex = 0u;
	UINT8 chIndex = 0u;
	UINT8 chState = 0u;
	UINT16 wPhyId = 0u;
	UINT16 wGdRelayId = 0u;

	for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
	{/* 判断车尾区段是否有采集 */
		
		wPhyId = GetAxisSecRelativePhySecId(g_utTrain[chTrainIndex].szAcId[0]);
		wGdRelayId = GetPhySecGdRelayId(wPhyId);  /*获取物理区段轨道继电器ID*/
		chState = GetPhySecCurOccupyState(wPhyId);

		/* 道岔区段空闲 */
		if ((0u != g_utTrain[chTrainIndex].chAcNum) && (UINT16_MAX != wGdRelayId) && (0u != wGdRelayId) && (SECTION_OCCUPY_NO == chState))
		{
			(void)ToaDeleteAcMapElm(g_utTrain[chTrainIndex].szAcId[0], g_utTrain[chTrainIndex].wTrainId);
			for (chIndex = 0u; chIndex < (g_utTrain[chTrainIndex].chAcNum - 1u); chIndex++)
			{
				g_utTrain[chTrainIndex].szAcId[chIndex] = g_utTrain[chTrainIndex].szAcId[chIndex + 1u];
			}
			g_utTrain[chTrainIndex].chAcNum--;
		}
		else
		{
			;
		}

		if (0u == g_utTrain[chTrainIndex].chAcNum)
		{
			(void)ToaDeleteUtTrain(g_utTrain[chTrainIndex].wTrainId);
		}
		else
		{
			;
		}
	}
}

/**
* @brief UT列车是否已在计轴区段上
* @param wTrainId 列车ID
* @param wAcId 计轴区段ID
* @return CI_SUCCESS:列车已在计轴区段上；CI_ERROR:列车未在计轴区段上
* @note：
*/
static UINT8 IsUtTrainOnAc(UINT16 wTrainId, UINT16 wAcId)
{
	UINT8 chRtn = CI_ERROR;
	UINT8 chIndex = 0u;
	if (AXIS_SECTION_SUM_MAX <= wAcId)
	{
		;
	}
	else
	{
		for (chIndex = 0u; chIndex < g_acMap[wAcId].chTrainNum; chIndex++)
		{
			if ((wTrainId == g_acMap[wAcId].strTrain[chIndex].wTrainId) && (TOA_TYPE_UT == g_acMap[wAcId].strTrain[chIndex].chTrainType))
			{/* UT列车已在该计轴区段上 */
				chRtn = CI_SUCCESS;
				break;
			}
			else
			{
				;
			}
		}
	}
	return chRtn;
}

/**
* @brief 获取TOA跟随数据
* @param UINT8 *pDataBuff 跟随数据存储缓冲区
* @param UINT32 curIndex 当前索引
* @return 计算后的索引
*/
UINT32 ToaGetTransferData(OUT UINT8 *pDataBuff, IN UINT32 curIndex)
{
	UINT32 ret = curIndex;
	UINT32 copyIndex = curIndex + 2u;/* 留出计轴区段数量位置 */
	UINT16 wIndex = 0u;
	UINT16 wTrainId = 0u;
	UINT8 chTransmitStat = 0u;
	UINT8 chTrainIndex = 0u;
	UINT16 wAcNum = 0u;
	UINT8 chTrainNum = 0u;
	UINT8 chAcIndex = 0u;
	UINT8 chCmdIndex = 0u;
	if (NULL != pDataBuff)
	{
		for (wIndex = 0u; wIndex < AXIS_SECTION_SUM_MAX; wIndex++)
		{
			if (0u != g_acMap[wIndex].chTrainNum)
			{
				wAcNum++;	/* 存在列车的计轴区段需要写入 */
				ShortToChar(wIndex, &pDataBuff[copyIndex]); /* 写入计轴区段ID */
				copyIndex += 2u;
				pDataBuff[copyIndex++] = g_acMap[wIndex].chTrainNum;

				for (chTrainIndex = 0u; chTrainIndex < g_acMap[wIndex].chTrainNum; chTrainIndex++)
				{
					ShortToChar(g_acMap[wIndex].strTrain[chTrainIndex].wTrainId, &pDataBuff[copyIndex]);
					copyIndex += 2u;
					pDataBuff[copyIndex++] = g_acMap[wIndex].strTrain[chTrainIndex].chTrainType;
				}
			}
			else
			{
				;
			}
		}
		ShortToChar(wAcNum, &pDataBuff[curIndex]); /* 写入有车占用的计轴区段数量 */

		pDataBuff[copyIndex++] = g_utTrainSum;
		for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
		{
			ShortToChar(g_utTrain[chTrainIndex].wTrainId, &pDataBuff[copyIndex]);
			copyIndex += 2u;

			LongToChar(g_utTrain[chTrainIndex].dwUtCyc, &pDataBuff[copyIndex]);
			copyIndex += 4u;

			pDataBuff[copyIndex++] = g_utTrain[chTrainIndex].chDir;

			pDataBuff[copyIndex++] = g_utTrain[chTrainIndex].chAcNum;

			for (chAcIndex = 0u; chAcIndex < g_utTrain[chTrainIndex].chAcNum; chAcIndex++)
			{
				ShortToChar(g_utTrain[chTrainIndex].szAcId[chAcIndex], &pDataBuff[copyIndex]);
				copyIndex += 2u;
			}
		}
		
		(void)CommonMemCpy(&pDataBuff[copyIndex], TRAIN_SUM_MAX, g_trainFlag, TRAIN_SUM_MAX);
		copyIndex += TRAIN_SUM_MAX;

		pDataBuff[copyIndex++] = g_initStatus;

		pDataBuff[copyIndex++] = g_cmdNum;

		for (chCmdIndex = 0u; chCmdIndex < g_cmdNum; chCmdIndex++)
		{
			pDataBuff[copyIndex++] = g_cmdStr[chCmdIndex].chCmdType;

			ShortToChar(g_cmdStr[chCmdIndex].wTrainId, &pDataBuff[copyIndex]);
			copyIndex += 2u;

			LongToChar(g_cmdStr[chCmdIndex].dwCmdId, &pDataBuff[copyIndex]);
			copyIndex += 4u;

			ShortToChar(g_cmdStr[chCmdIndex].wTerminalId, &pDataBuff[copyIndex]);
			copyIndex += 2u;

			pDataBuff[copyIndex++] = g_cmdStr[chCmdIndex].chVirCi;

			LongToChar(g_cmdStr[chCmdIndex].dwCmdParam, &pDataBuff[copyIndex]);
			copyIndex += 4u;
		}

		ret = copyIndex;

	}
	return ret;
}

/**
* @brief 设置TOA跟随数据
* @param UINT8 *pDataBuff 跟随数据存储缓冲区
* @param UINT32 curIndex 当前索引
* @return 计算后的索引
*/
UINT32 ToaSetTransferData(OUT UINT8 *pDataBuff, IN UINT32 curIndex)
{
	UINT32 ret = curIndex;
	UINT32 copyIndex = curIndex;
	UINT16 wIndex = 0u;
	UINT8 chAcIndex = 0u;
	UINT16 wTrainId = 0u;
	UINT8 chTrainIndex = 0u;
	UINT8 chTrainNum = 0u;
	UINT16 wAcNum = 0u;
	UINT16 wAcId = 0u;
	UINT8 chCmdIndex = 0u;

	if (NULL != pDataBuff)
	{
		(void)CommonMemSet(g_acMap, (UINT32)(sizeof(AcMapStruct) * AXIS_SECTION_SUM_MAX), 0u, (UINT32)(sizeof(AcMapStruct) * AXIS_SECTION_SUM_MAX));
		(void)CommonMemSet(g_utTrain, (UINT32)(sizeof(UtTrainStruct) * TRAIN_SUM_MAX), 0u, (UINT32)(sizeof(UtTrainStruct) * TRAIN_SUM_MAX));
		(void)CommonMemSet(g_trainFlag, TRAIN_SUM_MAX, FLAG_UNSET, TRAIN_SUM_MAX);
		(void)CommonMemSet(g_cmdStr, (UINT32)(sizeof(ToaCmdStruct) * TOA_CMD_MAX), 0u, (UINT32)(sizeof(ToaCmdStruct) * TOA_CMD_MAX));
		g_cmdNum = 0u;
		g_utTrainSum = 0u;
		wAcNum = ShortFromChar(&pDataBuff[copyIndex]);
		copyIndex += 2u;
		for (wIndex = 0u; wIndex < wAcNum; wIndex++)
		{
			wAcId = ShortFromChar(&pDataBuff[copyIndex]);
			copyIndex += 2u;
			g_acMap[wAcId].chTrainNum = pDataBuff[copyIndex];
			copyIndex++;
			for (chTrainIndex = 0u; chTrainIndex < g_acMap[wAcId].chTrainNum; chTrainIndex++)
			{
				g_acMap[wAcId].strTrain[chTrainIndex].wTrainId = ShortFromChar(&pDataBuff[copyIndex]);
				copyIndex += 2u;
				g_acMap[wAcId].strTrain[chTrainIndex].chTrainType = pDataBuff[copyIndex];
				copyIndex++;
			}
		}

		g_utTrainSum = pDataBuff[copyIndex];
		copyIndex++;

		for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
		{
			g_utTrain[chTrainIndex].wTrainId = ShortFromChar(&pDataBuff[copyIndex]);
			copyIndex += 2u;
			g_utTrain[chTrainIndex].dwUtCyc = LongFromChar(&pDataBuff[copyIndex]);
			copyIndex += 4u;
			g_utTrain[chTrainIndex].chDir = pDataBuff[copyIndex];
			copyIndex++;
			g_utTrain[chTrainIndex].chAcNum = pDataBuff[copyIndex];
			copyIndex++;
			for (chAcIndex = 0u; chAcIndex < g_utTrain[chTrainIndex].chAcNum; chAcIndex++)
			{
				g_utTrain[chTrainIndex].szAcId[chAcIndex] = ShortFromChar(&pDataBuff[copyIndex]);
				copyIndex += 2u;
			}
		}
		
		(void)CommonMemCpy(g_trainFlag, TRAIN_SUM_MAX, &pDataBuff[copyIndex], TRAIN_SUM_MAX);
		copyIndex += TRAIN_SUM_MAX;

		g_initStatus = pDataBuff[copyIndex];
		copyIndex++;

		g_cmdNum = pDataBuff[copyIndex];
		copyIndex++;

		for (chCmdIndex = 0u; chCmdIndex < g_cmdNum; chCmdIndex++)
		{
			g_cmdStr[chCmdIndex].chCmdType = pDataBuff[copyIndex];
			copyIndex++;

			g_cmdStr[chCmdIndex].wTrainId = ShortFromChar(&pDataBuff[copyIndex]);
			copyIndex += 2u;

			g_cmdStr[chCmdIndex].dwCmdId = LongFromChar(&pDataBuff[copyIndex]);
			copyIndex += 4u;

			g_cmdStr[chCmdIndex].wTerminalId = ShortFromChar(&pDataBuff[copyIndex]);
			copyIndex += 2u;

			g_cmdStr[chCmdIndex].chVirCi = pDataBuff[copyIndex];
			copyIndex++;

			g_cmdStr[chCmdIndex].dwCmdParam = LongFromChar(&pDataBuff[copyIndex]);
			copyIndex += 4u;
		}

		ret = copyIndex;
	}
	return ret;
}

/**
* @brief 调试信息打印
* @param 无
* @return 无
*/
static void ToaDebugInfo(void)
{
	UINT16 wAcIndex = 0u;
	UINT8 chTrainIndex = 0u;
	UINT8 chAcIndex = 0u;

	debug_infor_printf((const)"Toa work status:%x\n", g_initStatus);

	for (wAcIndex = 0u; wAcIndex < AXIS_SECTION_SUM_MAX; wAcIndex++)
	{
		if (0u != g_acMap[wAcIndex].chTrainNum)
		{
			debug_infor_printf((const)"Toa Ac Id = %d  ", wAcIndex);
			debug_infor_printf((const)"Ac TrainNum = %d[", g_acMap[wAcIndex].chTrainNum);
			for (chTrainIndex = 0u; chTrainIndex < g_acMap[wAcIndex].chTrainNum; chTrainIndex++)
			{
				debug_infor_printf((const)"%x-%d, ", g_acMap[wAcIndex].strTrain[chTrainIndex].wTrainId, g_acMap[wAcIndex].strTrain[chTrainIndex].chTrainType);
			}
			debug_infor_printf((const)"]\n");
		}
		else
		{
			;
		}
	}

	debug_infor_printf((const)"Lose comm seq:");
	for (chTrainIndex = 0u; chTrainIndex < TRAIN_SUM_MAX; chTrainIndex++)
	{
		if (FLAG_SET == g_trainFlag[chTrainIndex])
		{
			debug_infor_printf((const)"%d, ", chTrainIndex);
		}
	}
	debug_infor_printf((const)"\n");

	for (chTrainIndex = 0u; chTrainIndex < g_utTrainSum; chTrainIndex++)
	{
		debug_infor_printf((const)"Lose comm train id:%x ", g_utTrain[chTrainIndex].wTrainId);
		debug_infor_printf((const)"dir:%x ", g_utTrain[chTrainIndex].chDir);
		debug_infor_printf((const)"cyc:%d ", g_utTrain[chTrainIndex].dwUtCyc);
		debug_infor_printf((const)"ac num:%d[", g_utTrain[chTrainIndex].chAcNum);
		for (chAcIndex = 0u; chAcIndex < g_utTrain[chTrainIndex].chAcNum; chAcIndex++)
		{
			debug_infor_printf((const)"%d,", g_utTrain[chTrainIndex].szAcId[chAcIndex]);
		}
		debug_infor_printf((const)"]\n");
	}
}

/**
* @brief 判断计轴区段是否能够设置
* @param wTrainId 列车ID
* @param wAcId
* @return CI_ERROR:不能设置；CI_SUCCESS:能够设置
* @note：
*/
static UINT8 IsAcFreeToSet(UINT16 wTrainId, UINT16 wAcId)
{
	UINT8 chRtn = CI_ERROR;

	if (AXIS_SECTION_SUM_MAX > wAcId)
	{
		if ((0u == g_acMap[wAcId].chTrainNum)
			|| ((1u == g_acMap[wAcId].chTrainNum) && (TRAIN_SUM_MAX == g_acMap[wAcId].strTrain[0].wTrainId)))
		{
			chRtn = CI_SUCCESS;
		}
		else
		{
			;
		}
	}
	else
	{
		;
	}

	return chRtn;
}