//---------------------------------------------------------------------------

#pragma hdrstop

#include "CDSManagerF.h"
#include "CDSCtlrF.h"
#include "CDSIfscF.h"
#include "CDSFormF.h"
#include "CDSImageF.h"
#include "CDSAtmpF.h"
#include "CDSParkF.h"
#include "VmsUtilsF.h"
#include "VMSCommLibF.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

//---------------------------------------------------------------------------
TCDSManager *CDSManager = NULL;
//---------------------------------------------------------------------------

TCDSManager::TCDSManager()
{
    FIsStaticCycle = false;
}
//---------------------------------------------------------------------------
TCDSManager::~TCDSManager()
{
}
//---------------------------------------------------------------------------
int TCDSManager::ClearVmsProvideMode()
{
    int nSelCnt= 0;

    //DWORD dwTick = GetTickCount();
    //JOBSTART;

    FFormDsplDt = Now().FormatString("yyyymmddhhnnss");

    CtlrItr it;
    for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;

        if (pObj->Server.useFlag != use_enable) continue;

        if (!pObj->FProvide) continue;

        pObj->CTRLMODE->MaxDisplayForm = 0;//pObj->VMS_MAX_PHSE_NUM; //0
        pObj->CTRLMODE->Enable         = object_disable;
        pObj->CTRLMODE->SvcDate        = FFormDsplDt;
        pObj->CTRLMODE->SaveFlag       = true;
        pObj->CTRLMODE->pTimer         = Now();
        pObj->CTRLMODE->Result         = false;

        pObj->InitEVehicle();   // 긴급차량우선신호
        pObj->InitSchedule();   //스케줄정보
        pObj->InitIncident();   //돌발정보
        pObj->InitEvent();      //이벤트(공사/행사)정보

        pObj->FExistCngsForm = false;   //정체폼이 없는것으로 초기화

        pObj->pForms->Clear();

        nSelCnt++;
    }

    //JOBEND(dwTick);
    //if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
    //    TIMEDELAY(nSelCnt, dwTick);
    //}
    return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::CheckVmsEVehicleInf(TADOConnection *ADbConn)
{
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

    DWORD dwTick = GetTickCount();
    SELSTART;

    // 하나의 VMS에 긴급차량우선신호 가 2개 이상존재할 경우...
    // 하나의 VMS에 긴급차량우선선호 진행중, 운행완료 상태가 존재하는 경우...
    // 운행중,,,운행중,,,운행중 ===> 운행중이 하나라도 존재하면 최종 상태는 운행중
    //
    sQry = "SELECT COUNT(1) AS EVEHICLE_CNT         \r\n"
           "  FROM PRIO_SGNL_REQ_INFR A             \r\n"
           " INNER JOIN PRIO_SGNL_OPER_IXR B        \r\n"
           "    ON A.SRVC_ID = B.SRVC_ID            \r\n"
           " INNER JOIN TB_VMS_RLTN_IXR C           \r\n"
           "    ON B.IXR_NMBR = C.SGNL_IXR_NMBR     \r\n"
           " WHERE A.END_YN = 'N'                   \r\n";

	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

            int nIdx;
			for( ; !pADO->Eof; pADO->Next())
			{
                nSelCnt = pADO->FieldByName("EVEHICLE_CNT")->AsInteger;
			}
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    if (nSelCnt == 0) {
        // 현재시점에 긴급차량우선신호가 발생하지 않은경우 이전 긴급차량우선신호가 발생했는지 확인
        // ===> 긴급차량우선신호 운영종료 메시지를 전송하여야 함
        // ===> 긴급차량우선신호 운영종료 메시지를 전송한후 일정시간이 지난후 일반스케쥴 메시지 전송
        CtlrItr it;
        for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
        {
            TCDSCtlr *pObj = (TCDSCtlr*)it->second;
            if (pObj->Server.useFlag != use_enable) continue;

            if ((pObj->EVEHICLE->IsOcurr || pObj->EVEHICLE->IsEnd) && COMM_TimeDiff(pObj->EVEHICLE->dtOcurr) <= 60) {
                MINFO(" INF-.DATA: %25.25s: %s, Ocurr(%d), End(%d), TM(%d)", __MYFUNC__,
                    pObj->CTLR_NMBR.c_str(), pObj->EVEHICLE->IsOcurr ? 1 : 0, pObj->EVEHICLE->IsEnd ? 1: 0, COMM_TimeDiff(pObj->EVEHICLE->dtOcurr));
                nSelCnt++;
            }
        }
    }

    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
	return nSelCnt;
}
//---------------------------------------------------------------------------

int TCDSManager::LoadVmsEVehicleInf(TADOConnection *ADbConn, int ACommand)
{
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

    DWORD dwTick = GetTickCount();
    SELSTART;

    CtlrItr it;
    for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;
        pObj->InitEVehicle();   // 긴급차량우선신호
    }

    sQry = "SELECT VMS_CTLR_NMBR AS VMS_CTLR_NMBR, SRVC_ID, COUNT(1) AS IXR_CNT                 \r\n"
           "  FROM (                                                                            \r\n"
           "SELECT A.EMRG_VHCL_ID, A.SRVC_ID, A.END_YN, B.IXR_NMBR, B.IXR_ORD, C.VMS_CTLR_NMBR  \r\n"
           "  FROM PRIO_SGNL_REQ_INFR A                                                         \r\n"
           " INNER JOIN PRIO_SGNL_OPER_IXR B                                                    \r\n"
           "    ON A.SRVC_ID = B.SRVC_ID                                                        \r\n"
           " INNER JOIN TB_VMS_RLTN_IXR C                                                       \r\n"
           "    ON B.IXR_NMBR = C.SGNL_IXR_NMBR                                                 \r\n"
           " WHERE A.END_YN = 'N'                                                               \r\n"
           " )                                                                                  \r\n"
           " GROUP BY VMS_CTLR_NMBR, SRVC_ID                                                    \r\n";

	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

            int nIdx;
			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString VMS_CTLR_NMBR = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;

                TCDSCtlr *pObj = CDSCtlrManager->FLists.Find(VMS_CTLR_NMBR);
                if (!pObj) continue;

                if (ACommand != dbm_check_evehicle_alarm) {
                    // 긴급차량우선신호 체크 메시지가 아닌 경우 모두 다운로드할 수 있도록 플래그 설정
                    // 정주기 인 경우 무조건 다운로드 할 수 있도록(DB 이력 무조건 입력)....
                    pObj->EVEHICLE->IsDownload = false;
                    pObj->EVEHICLE->IsEVechFirst = false;
                }

                if (!pObj->EVEHICLE->IsOcurr) {
                    pObj->EVEHICLE->IsDownload = false;
                    pObj->EVEHICLE->IsEVechFirst = false;
                }
                pObj->EVEHICLE->IsOcurr = true;
                pObj->EVEHICLE->dtOcurr = Now();
                pObj->EVEHICLE->IsEnd   = false;

                AnsiString SRVC_ID = pADO->FieldByName("SRVC_ID")->AsString;
                int IXR_CNT = pADO->FieldByName("IXR_CNT")->AsInteger;

                VMS_EVEHICLE_INFO *pEvt = pObj->EVEHICLE;
                if (pEvt->Count >= VMS_MAX_EVEHICLE)
                {
                    MERROR("VMS EVehicle Occr Count Over: %s, %d", pObj->CTLR_NMBR.c_str(), pEvt->Count);
                    continue;
                }

                pEvt->Unit[pEvt->Count].SRVC_ID = SRVC_ID;
                pEvt->Unit[pEvt->Count].IXR_CNT = IXR_CNT;
                pEvt->Unit[pEvt->Count].SRVC_TM = Now().FormatString("yyyyMMddhhnnss");
                pEvt->Unit[pEvt->Count].END_YN  = "N";
                pEvt->Count++;

                nSelCnt++;
			}
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    /*
    * 모든 VMS에 대해서 긴급차량우선신호 메시지 표출여부를 체크한다.
    */
    nSelCnt = 0;
    for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;
        if (pObj->Server.useFlag != use_enable) continue;

        if (pObj->EVEHICLE->Count > 0) {
            if (pObj->EVEHICLE->IsDownload) {
                // 이미 다운로드 하였음.
                MINFO(" INF-.DATA: %25.25s: EVehicle Ing-Message ..Already Download. %s, Ocurr(%d), End(%d), TM(%d), ACommand(%d)", __MYFUNC__,
                    pObj->CTLR_NMBR.c_str(), pObj->EVEHICLE->IsOcurr ? 1 : 0, pObj->EVEHICLE->IsEnd ? 1: 0, COMM_TimeDiff(pObj->EVEHICLE->dtOcurr), ACommand);
            }
            else {
                if (!pObj->EVEHICLE->IsEVechFirst || (pObj->Server.commState == comm_open)) {
                    // 다운로드 하지 못하였는데 통신상태가 정상인 경우 다운로드 재실행
                    nSelCnt++;
                }

                MINFO(" INF-.DATA: %25.25s: EVehicle Ing-Message ....First Download. %s, Ocurr(%d), End(%d), TM(%d), ACommand(%d)", __MYFUNC__,
                    pObj->CTLR_NMBR.c_str(), pObj->EVEHICLE->IsOcurr ? 1 : 0, pObj->EVEHICLE->IsEnd ? 1: 0, COMM_TimeDiff(pObj->EVEHICLE->dtOcurr),ACommand);
            }
            continue;
        }

        if (pObj->EVEHICLE->Count == 0) {
            if (pObj->EVEHICLE->IsEnd) {
                if (COMM_TimeDiff(pObj->EVEHICLE->dtOcurr) > 60) {
                    // 운영종료 메시지 표출 완료
                    pObj->EVEHICLE->IsOcurr = false;
                    pObj->EVEHICLE->IsEnd = false;
                    nSelCnt++;

                    MINFO(" INF-.DATA: %25.25s: EVehicle End-Message ..END. %s, Ocurr(%d), End(%d), TM(%d), ACommand(%d)", __MYFUNC__,
                        pObj->CTLR_NMBR.c_str(), pObj->EVEHICLE->IsOcurr ? 1 : 0, pObj->EVEHICLE->IsEnd ? 1: 0, COMM_TimeDiff(pObj->EVEHICLE->dtOcurr), ACommand);
                }
            }

            if (pObj->EVEHICLE->IsOcurr) {
                pObj->EVEHICLE->dtOcurr = Now();
                pObj->EVEHICLE->IsOcurr = false;
                pObj->EVEHICLE->IsEnd = true;
                pObj->EVEHICLE->IsDownload = false;
                pObj->EVEHICLE->IsEVechFirst = false;
                nSelCnt++;

                MINFO(" INF-.DATA: %25.25s: EVehicle End-Message START. %s, Ocurr(%d), End(%d), TM(%d), ACommand(%d)", __MYFUNC__,
                    pObj->CTLR_NMBR.c_str(), pObj->EVEHICLE->IsOcurr ? 1 : 0, pObj->EVEHICLE->IsEnd ? 1: 0, COMM_TimeDiff(pObj->EVEHICLE->dtOcurr), ACommand);
            }
        }
    }

    if (0)
    {
        CtlrItr it;
        for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
        {
            TCDSCtlr *pObj = (TCDSCtlr*)it->second;

            if (!pObj->Used) continue;

            MDEBUG(" INF-.DATA: %25.25s: EVehicle Message. %s, %d EA.", __MYFUNC__, pObj->CTLR_NMBR.c_str(), pObj->EVEHICLE->Count);
        }
    }

    MINFO(" INF-.DATA: %25.25s: EVehicle. ACommand(%s), %d EA.", __MYFUNC__, (ACommand == dbm_check_evehicle_alarm) ? "CHECK" : "CYCLE", nSelCnt);

    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
	return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::LoadVmsEventOccrInf(TADOConnection *ADbConn)
{
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

    DWORD dwTick = GetTickCount();
    SELSTART;

    sQry = "SELECT V.VMS_CTLR_NMBR, V.LINK_ID, V.IFSC_ID, V.VMS_IFSC_ID,                \r\n"
           "       V.VMS_IFSC_NM, V.DSPL_STRT_NODE_NM, V.DSPL_END_NODE_NM,              \r\n"
           "       V.DETR_ID, V.DSPL_PRRT, I.INCD_OCRR_ID, I.STRT_LCTN_NM,              \r\n"
           "       V.ROAD_NM, V.SPOT_NM,                                                \r\n"
           "       I.END_LCTN_NM, I.OCRR_LCTN_NM, I.INCD_TITL,                          \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                               \r\n"
           "         FROM TB_CMMN_CD                                                    \r\n"
           "        WHERE CMMN_CD = I.VMS_INCD_TYPE_CD                                  \r\n"
           "          AND CMMN_CLSF_CD = 'VIT') AS VMS_INCD_TYPE_NM,                    \r\n"
           "       I.VMS_INCD_TYPE_CD,                                                  \r\n"
           "       CASE WHEN I.VMS_INCD_TYPE_CD = 'VIT1' THEN                           \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                               \r\n"
           "          FROM TB_CMMN_CD                                                   \r\n"
           "         WHERE CMMN_CD      = I.VMS_INCD_DETL_TYPE_CD                       \r\n"
           "           AND CMMN_CLSF_CD = 'IDT')                                        \r\n"
           "       ELSE                                                                 \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                               \r\n"
           "          FROM TB_CMMN_CD                                                   \r\n"
           "         WHERE CMMN_CD      = I.VMS_INCD_DETL_TYPE_CD                       \r\n"
           "           AND CMMN_CLSF_CD = 'EDT')                                        \r\n"
           "       END AS VMS_INCD_DETL_NM,                                             \r\n"
           "       I.VMS_INCD_DETL_TYPE_CD,                                             \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                               \r\n"
           "          FROM TB_CMMN_CD                                                   \r\n"
           "         WHERE CMMN_CD      = I.CMTR_GRAD_CD                                \r\n"
           "           AND CMMN_CLSF_CD = 'LTCU') AS CMTR_GRAD_NM,                      \r\n"
#if 0
           "       (SELECT CMMN_CD_KOR_NM                                               \r\n"
           "          FROM TB_CMMN_CD                                                   \r\n"
           "         WHERE CMMN_CD      = I.CMTR_GRAD_CD                                \r\n"
           "           AND CMMN_CLSF_CD = 'LTC') AS CMTR_GRAD_NM,                       \r\n"
#endif
#if 0
           "       I.VMS_INCD_RSTR_TYPE_CD,                                             \r\n"
           "       (SELECT CMMN_CD_KOR_NM                                               \r\n"
           "          FROM TB_CMMN_CD                                                   \r\n"
           "         WHERE CMMN_CD      = I.VMS_INCD_RSTR_TYPE_CD                       \r\n"
           "           AND CMMN_CLSF_CD = 'VRT') AS VMS_INCD_RSTR_TYPE_NM,              \r\n"
#endif
           "       I.CMTR_GRAD_CD,                                                      \r\n"
           "       I.INCD_CLSR_LANE,                                                    \r\n"
           "       I.INCD_STRT_DT,                                                      \r\n"
           "       I.INCD_END_PRAR_DT                                                   \r\n"
           "  FROM (SELECT D.VMS_CTLR_NMBR, A.LINK_ID,                                  \r\n"
           "               A.IFSC_ID, B.VMS_IFSC_ID,                                    \r\n"
           "               C.VMS_IFSC_NM,                                               \r\n"
           "               C.DSPL_STRT_NODE_NM,                                         \r\n"
           "               C.DSPL_END_NODE_NM,                                          \r\n"
           "               NVL(C.DETR_ID, 0) AS DETR_ID,                                \r\n"
           "               C.ROAD_NM, C.SPOT_NM,                                        \r\n"
           "               D.DSPL_PRRT                                                  \r\n"
           "          FROM TB_IFSC_RLTN_LINK      A,                                    \r\n"
           "               TB_VMS_IFSC_RLTN_IFSC  B,                                    \r\n"
           "               TB_VMS_IFSC            C,                                    \r\n"
           "               TB_VMS_RLTN_IFSC       D                                     \r\n"
           "         WHERE A.IFSC_ID     = B.IFSC_ID                                    \r\n"
           "           AND B.VMS_IFSC_ID = C.VMS_IFSC_ID                                \r\n"
           "           AND C.VMS_IFSC_ID = D.VMS_IFSC_ID ) V,                           \r\n"
           "       (SELECT A.*, B.INCD_TITL                                             \r\n"
           "          FROM TB_INCD_OCRR_VMS A,                                          \r\n"
           "               TB_INCD_OCRR     B                                           \r\n"
           "         WHERE A.INCD_PRGR_STEP_CD = 'ISS2'                                 \r\n"
           "           AND A.VMS_DSPL_YN       = 'Y'                                    \r\n"
           "           AND A.INCD_OCRR_ID      = B.INCD_OCRR_ID                         \r\n"
           "           AND A.INCD_END_PRAR_DT  > TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS')   \r\n"
           "           AND A.VMS_INCD_TYPE_CD IN ('VIT1', 'VIT2') ) I                   \r\n"
           " WHERE V.LINK_ID = I.LINK_ID                                                \r\n"
           " ORDER BY V.VMS_CTLR_NMBR                                                   \r\n";

	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

            int nIdx;
			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString sVmsNmbr = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;

                TCDSCtlr *pObj = CDSCtlrManager->FLists.Find(sVmsNmbr);
                if (!pObj) continue;

                if (!pObj->FProvide) continue;

                AnsiString VMS_INCD_TYPE_CD = pADO->FieldByName("VMS_INCD_TYPE_CD")->AsString;
                AnsiString INCD_OCRR_ID     = pADO->FieldByName("INCD_OCRR_ID")->AsString;

                VMS_EVENT_INFO *pEvt;
                if (VMS_INCD_TYPE_CD ==  "VIT1")
                {
                    //사고
                    if (pObj->INCIDENT->Count >= VMS_MAX_EVENT)
                    {
                        MERROR("VMS Incident Over: %s, %d", pObj->CTLR_NMBR.c_str(), pObj->INCIDENT->Count);
                        continue;
                    }
                    bool bDup = false;
                    for (int ii = 0; ii < pObj->INCIDENT->Count; ii++)
                    {
                        if (INCD_OCRR_ID == pObj->INCIDENT->Unit[ii].INCD_OCRR_ID)
                        {
                            bDup = true;
                            break;
                        }
                    }
                    if (bDup)
                    {
                        MERROR("VMS Incident dup: %s, %s", pObj->CTLR_NMBR.c_str(), INCD_OCRR_ID.c_str());
                        continue;
                    }
                    nIdx = pObj->INCIDENT->Count;
                    pEvt = pObj->INCIDENT;
                }
                else
                {
                    //공사/행사
                    if (pObj->EVENT->Count >= VMS_MAX_EVENT)
                    {
                        MERROR("VMS Event Over: %s, %d", pObj->CTLR_NMBR.c_str(), pObj->EVENT->Count);
                        continue;
                    }
                    bool bDup = false;
                    for (int ii = 0; ii < pObj->EVENT->Count; ii++)
                    {
                        if (INCD_OCRR_ID == pObj->EVENT->Unit[ii].INCD_OCRR_ID)
                        {
                            bDup = true;
                            break;
                        }
                    }
                    if (bDup)
                    {
                        MERROR("VMS Event dup: %s, %s", pObj->CTLR_NMBR.c_str(), INCD_OCRR_ID.c_str());
                        continue;
                    }
                    nIdx = pObj->EVENT->Count;
                    pEvt = pObj->EVENT;
                }

                pEvt->Unit[nIdx].LINK_ID           = pADO->FieldByName("LINK_ID")->AsString;
                pEvt->Unit[nIdx].IFSC_ID           = pADO->FieldByName("IFSC_ID")->AsString;
                pEvt->Unit[nIdx].VMS_IFSC_ID       = pADO->FieldByName("VMS_IFSC_ID")->AsString;
                pEvt->Unit[nIdx].VMS_IFSC_NM       = pADO->FieldByName("VMS_IFSC_NM")->AsString;
                pEvt->Unit[nIdx].DSPL_STRT_NODE_NM = pADO->FieldByName("DSPL_STRT_NODE_NM")->AsString;
                pEvt->Unit[nIdx].DSPL_END_NODE_NM  = pADO->FieldByName("DSPL_END_NODE_NM")->AsString;
                pEvt->Unit[nIdx].DETR_ID           = pADO->FieldByName("DETR_ID")->AsString.Trim();
                pEvt->Unit[nIdx].DSPL_PRRT         = pADO->FieldByName("DSPL_PRRT")->AsString;
                pEvt->Unit[nIdx].INCD_OCRR_ID      = INCD_OCRR_ID;
                pEvt->Unit[nIdx].STRT_LCTN_NM      = pADO->FieldByName("STRT_LCTN_NM")->AsString;
                pEvt->Unit[nIdx].END_LCTN_NM       = pADO->FieldByName("END_LCTN_NM")->AsString;

                if (pEvt->Unit[nIdx].STRT_LCTN_NM == "")
                {
                    pEvt->Unit[nIdx].STRT_LCTN_NM = pEvt->Unit[nIdx].DSPL_STRT_NODE_NM;
                }
                if (pEvt->Unit[nIdx].END_LCTN_NM == "")
                {
                    pEvt->Unit[nIdx].END_LCTN_NM = pEvt->Unit[nIdx].DSPL_END_NODE_NM;
                }

                pEvt->Unit[nIdx].OCRR_LCTN_NM          = pADO->FieldByName("OCRR_LCTN_NM")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_TYPE_NM      = pADO->FieldByName("VMS_INCD_TYPE_NM")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_TYPE_CD      = pADO->FieldByName("VMS_INCD_TYPE_CD")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_DETL_NM      = pADO->FieldByName("VMS_INCD_DETL_NM")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_DETL_TYPE_CD = pADO->FieldByName("VMS_INCD_DETL_TYPE_CD")->AsString;
                pEvt->Unit[nIdx].CMTR_GRAD_NM          = pADO->FieldByName("CMTR_GRAD_NM")->AsString;
                pEvt->Unit[nIdx].CMTR_GRAD_CD          = pADO->FieldByName("CMTR_GRAD_CD")->AsString;
                pEvt->Unit[nIdx].INCD_CLSR_LANE        = pADO->FieldByName("INCD_CLSR_LANE")->AsString;
                pEvt->Unit[nIdx].INCD_STRT_DT          = pADO->FieldByName("INCD_STRT_DT")->AsString;
                pEvt->Unit[nIdx].INCD_END_PRAR_DT      = pADO->FieldByName("INCD_END_PRAR_DT")->AsString;
                pEvt->Unit[nIdx].ROAD_NM               = pADO->FieldByName("ROAD_NM")->AsString;
                pEvt->Unit[nIdx].SPOT_NM               = pADO->FieldByName("SPOT_NM")->AsString;
#if 0
                pEvt->Unit[nIdx].VMS_INCD_RSTR_TYPE_CD = pADO->FieldByName("VMS_INCD_RSTR_TYPE_CD")->AsString;
                pEvt->Unit[nIdx].VMS_INCD_RSTR_TYPE_NM = pADO->FieldByName("VMS_INCD_RSTR_TYPE_NM")->AsString;
#else
                pEvt->Unit[nIdx].VMS_INCD_RSTR_TYPE_CD = "X";
                pEvt->Unit[nIdx].VMS_INCD_RSTR_TYPE_NM = "주의요망";
#endif
                pEvt->Unit[nIdx].INCD_TITL             = pADO->FieldByName("INCD_TITL")->AsString;

                pEvt->Count++;

                nSelCnt++;
			}
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    if (0)
    {
        CtlrItr it;
        for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
        {
            TCDSCtlr *pObj = (TCDSCtlr*)it->second;

            if (!pObj->Used) continue;

            MDEBUG("VMS Event(I/E): %s, %d/%d EA.", pObj->CTLR_NMBR.c_str(), pObj->INCIDENT->Count, pObj->EVENT->Count);
        }
    }

    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
	return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::LoadVmsScheduleInfo(TADOConnection *ADbConn)
{
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

    DWORD dwTick = GetTickCount();
    SELSTART;

    sQry = "SELECT *                                                                    \r\n"
           "  FROM (                                                                    \r\n"
           "        SELECT B.*, C.VMS_FORM_TYPE_CD,                                     \r\n"
           "               C.VMS_FORM_DSPL_DRCT_CD AS VMS_FORM_SUB_TYPE_CD,             \r\n"
           "               SUBSTR(DECODE(TO_CHAR(SYSDATE, 'D'), '1', B.SCH_WEEK1,       \r\n"
           "                                                    '2', B.SCH_WEEK2,       \r\n"
           "                                                    '3', B.SCH_WEEK3,       \r\n"
           "                                                    '4', B.SCH_WEEK4,       \r\n"
           "                                                    '5', B.SCH_WEEK5,       \r\n"
           "                                                    '6', B.SCH_WEEK6,       \r\n"
           "                                                         B.SCH_WEEK7),      \r\n"
           "                      TO_NUMBER(TO_CHAR(SYSDATE, 'HH24'))+1, 1) AS SCH_YN   \r\n"
           "          FROM TB_VMS_CTLR      A,                                          \r\n"
           "               TB_VMS_DSPL_SCH  B,                                          \r\n"
           "               TB_VMS_FORM      C                                           \r\n"
           "         WHERE A.DEL_YN        = 'N'                                        \r\n"
           "           AND B.USE_YN        = 'Y'                                        \r\n"
           "           AND C.VALID_YN      = 'Y'                                        \r\n"
           "           AND A.VMS_CTLR_NMBR = B.VMS_CTLR_NMBR                            \r\n"
           "           AND A.OPER_MODE     = B.VMS_SCH_TYPE                             \r\n"
           "           AND B.VMS_FORM_ID   = C.VMS_FORM_ID                              \r\n"
           "           AND TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS') BETWEEN                 \r\n"
           "               B.DSPL_STRT_HH AND B.DSPL_END_HH                             \r\n"
           "       )                                                                    \r\n"
           " WHERE SCH_YN = '1'                                                         \r\n"
           " ORDER BY VMS_CTLR_NMBR ASC, PHASE ASC                                      \r\n";

    TCDSForm *pCDSForm;

    //VMS_FORM_DSPL_DRCT_CD
	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

            int        nIdx;
            AnsiString VMS_SCH_TYPE;        //VARCHAR2(5)	N			VMS 스케줄 유형(A:자동,F:고정,B:기본)
            int        VMS_SCH_FORM_TYPE;   //NUMBER(3)	    N			VMS 폼 스케쥴 유형(0:교통,1:돌발,2:공사행사,3:홍보,4:우회,5:정체,6:안전,7:동영상,8:스트리밍영상)
            int        PHASE;               //NUMBER(2)	    N			PHASE
            AnsiString VMS_FORM_ID;         //NUMBER(5)	    Y			VMS FORM ID
            int        DSPL_HH;             //NUMBER(3)	    Y	0		표출 시간
            AnsiString DSPL_STRT_HH;        //VARCHAR2(14)	N			표출시작시간
            AnsiString DSPL_END_HH;         //VARCHAR2(14)	N			표출종료시간
            AnsiString SYMB_LIB_NMBR;       //NUMBER(4)	    Y	0		동영상인 경우 동영상 파일 심벌 아이디
            AnsiString STRM_ADDR;           //VARCHAR2(60)	Y			스트리밍인경우 스트리밍 주소
            bool       bBottomTraffic;
            TCDSIfsc  *pCDSIfsc;
            int        nBottomTrafficCnt;
            int        nFigureTrafficCnt;   //////////////////////// 20200515 추가함
            int        nFigureDisplayTm;    //////////////////////// 20200515 추가함
            String     FIGURE_VMS_IFSC_ID;  //////////////////////// 20200515 추가함
            bool       DSPL_CNGS_YN;

            AnsiString FRST_VMS_IFSC_ID;    //NUMBER(10)	Y			1단 VMS 정보제공구간 ID
            AnsiString SECD_VMS_IFSC_ID;    //NUMBER(10)	Y			2단 VMS 정보제공구간 ID
            AnsiString THIR_VMS_IFSC_ID;    //NUMBER(10)	Y			3단 VMS 정보제공구간 ID
            AnsiString FOUR_VMS_IFSC_ID;    //NUMBER(10)	Y			4단 VMS 정보제공구간 ID
            AnsiString FRST_IMG_IFSC_ID;    //NUMBER(10)	Y			1단 이미지 정보제공구간 ID
            AnsiString SECD_IMG_IFSC_ID;    //NUMBER(10)	Y			2단 이미지 정보제공구간 ID
            AnsiString THIR_IMG_IFSC_ID;    //NUMBER(10)	Y			3단 이미지 정보제공구간 ID
            AnsiString FOUR_IMG_IFSC_ID;    //NUMBER(10)	Y			4단 이미지 정보제공구간 ID

			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString VMS_CTLR_NMBR = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;

                //VMS 스케줄 유형(A:자동,F:고정,B:기본)
                VMS_SCH_TYPE = pADO->FieldByName("VMS_SCH_TYPE")->AsString;

                //VMS 폼 스케쥴 유형(0:교통, 1:돌발,2:공사행사, 3:홍보, 4:우회, 5:정체, 6:안전, 7:동영상, 8:스트리밍영상)
                VMS_SCH_FORM_TYPE = pADO->FieldByName("VMS_SCH_FORM_TYPE")->AsInteger;

                PHASE         = pADO->FieldByName("PHASE")->AsInteger;
                VMS_FORM_ID   = pADO->FieldByName("VMS_FORM_ID")->AsString.Trim();
                DSPL_HH       = pADO->FieldByName("DSPL_HH")->AsInteger;
                DSPL_STRT_HH  = pADO->FieldByName("DSPL_STRT_HH")->AsString.Trim();
                DSPL_END_HH   = pADO->FieldByName("DSPL_END_HH")->AsString.Trim();
                SYMB_LIB_NMBR = pADO->FieldByName("SYMB_LIB_NMBR")->AsString.Trim();
                STRM_ADDR     = pADO->FieldByName("STRM_ADDR")->AsString.Trim();
                DSPL_CNGS_YN  = pADO->FieldByName("DSPL_CNGS_YN")->AsString.Trim() == "Y" ? true : false;

                FRST_VMS_IFSC_ID  = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString.Trim();
                SECD_VMS_IFSC_ID  = pADO->FieldByName("SECD_VMS_IFSC_ID")->AsString.Trim();
                THIR_VMS_IFSC_ID  = pADO->FieldByName("THIR_VMS_IFSC_ID")->AsString.Trim();
                FOUR_VMS_IFSC_ID  = pADO->FieldByName("FOUR_VMS_IFSC_ID")->AsString.Trim();
                FRST_IMG_IFSC_ID  = FRST_VMS_IFSC_ID;//pADO->FieldByName("FRST_IMG_IFSC_ID")->AsString;
                SECD_IMG_IFSC_ID  = SECD_VMS_IFSC_ID;//pADO->FieldByName("SECD_IMG_IFSC_ID")->AsString;
                THIR_IMG_IFSC_ID  = THIR_VMS_IFSC_ID;//pADO->FieldByName("THIR_IMG_IFSC_ID")->AsString;
                FOUR_IMG_IFSC_ID  = FOUR_VMS_IFSC_ID;//pADO->FieldByName("FOUR_IMG_IFSC_ID")->AsString;

                if (VMS_SCH_FORM_TYPE <  eSchTp_traffic ||
                    VMS_SCH_FORM_TYPE >= eSchTp_max)
                {
                    MERROR("LoadVmsScheduleInfo: Unknown Form Type: VmsNmbr(%s), FormId(%s), FormScheduleType(%d)", VMS_CTLR_NMBR.c_str(), VMS_FORM_ID.c_str(), VMS_SCH_FORM_TYPE);
                    continue;
                }

                TCDSCtlr *pObj = CDSCtlrManager->FLists.Find(VMS_CTLR_NMBR);
                if (!pObj)
                {
                    MERROR("LoadVmsScheduleInfo: Not Found VMS: VmsNmbr(%s)", VMS_CTLR_NMBR.c_str());
                    continue;
                }
                if (!pObj->FProvide)
                {
                    //제공하지 않아도 돼는 VMS - mode change로 호출하는 경우임.
                    continue;
                }


                pCDSForm = CDSFormManager->FLists.Find(VMS_FORM_ID);
                if (!pCDSForm)
                {
                    MERROR("LoadVmsScheduleInfo: VMS Schedule Not Found Form: VmsNmbr(%s)-[%s]", VMS_CTLR_NMBR.c_str(), VMS_FORM_ID.c_str());
                    continue;
                }

                if (pObj->SCHEDULE->Count >= VMS_MAX_SCHEDULE)
                {
                    MERROR("LoadVmsScheduleInfo: VMS Schedule Count Over: %s, %d", VMS_CTLR_NMBR.c_str(), pObj->SCHEDULE->Count);
                    continue;
                }

                //TODO: 조회정렬은 기본,고정,자동(돌발,공사,행사,우회,교통,정체폼) 순으로 조회된다.
                //      따라서 각 폼에 대한처리를 수행하면 된다.
                //==> 신규작업에서 폼 표출 우선순위적용함 ==> 조회정렬이 영향이 있는지 확인해야함.
                //eFormTp_traf_1   = 11,  //	소통상황(1단)
                //eFormTp_traf_2   = 12,  //	소통상황(2단)
                //eFormTp_traf_3   = 13,  //	소통상황(3단)
                //eFormTp_traf_4   = 14,  //	소통상황(4단)
                bool isIncidentForm = false;
                if (VMS_SCH_FORM_TYPE == eSchTp_traffic && pCDSForm->VMS_FORM_TYPE_CD == eFormTp_traf_1)
                {
                    //교통정보스케쥴이고 폼의 유형이  소통정보(1단) 인경우....
                    //해당 폼이 돌발이나 이벤트가 등록되어 있다면
                    //폼을 생성하지 않는다.

                    AnsiString FRST_VMS_IFSC_ID = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;

                    if (FRST_VMS_IFSC_ID != "" && FRST_VMS_IFSC_ID != "0")
                    {
                        for (int ii = 0; ii < pObj->SCHEDULE->Count && ii < VMS_MAX_SCHEDULE; ii++)
                        {
                            if (pObj->SCHEDULE->Unit[ii].VMS_SCH_FORM_TYPE == eSchTp_incident ||  //돌발
                                pObj->SCHEDULE->Unit[ii].VMS_SCH_FORM_TYPE == eSchTp_gongsa   ||  //공사/행사
                                pObj->SCHEDULE->Unit[ii].VMS_SCH_FORM_TYPE == eSchTp_deture )     //우회
                            {
                                if (pObj->SCHEDULE->Unit[ii].EVENT)
                                {
                                    if (FRST_VMS_IFSC_ID == pObj->SCHEDULE->Unit[ii].EVENT->VMS_IFSC_ID)
                                    {
                                        //폼을 생성하지 않는다.
                                        // TODO: 상위 순회루틴으로 빠져나가지 않음.
                                        isIncidentForm = true;
                                        break;
                                        //continue;
                                    }
                                }
                            }
                        }
                    }
                }
                if (isIncidentForm) {
                    continue;
                }

                bBottomTraffic     = false;
                nFigureDisplayTm   = DSPL_HH;
                FIGURE_VMS_IFSC_ID = "";
                nFigureTrafficCnt  = 0;   //전체 표출할 하단 소통정보 갯수

                switch(VMS_SCH_FORM_TYPE)
                {
                case eSchTp_traffic:     //교통정보
                    //도형식 소통정보 인 경우 해당 도형의 소통정보가 존재하는지 확인
                    if (pCDSForm->VMS_FORM_TYPE_CD == eFormtp_figure)
                    {
                        bool bTraffic = false;
                        TCDSImage *pBakTrfImg = CDSImageManager->FLists.Find(pCDSForm->TrfBakImgId);
                        if (pBakTrfImg)
                        {
                            FOR_STL(TCDSImageCell*, pCell, pBakTrfImg->FLists)
                            {
                                TCDSIfsc *pTmpIfsc1 = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                if (pTmpIfsc1)
                                {
                                    if (pTmpIfsc1->CMTR_GRAD_CD != "0")
                                    {
                                        FIGURE_VMS_IFSC_ID = pCell->VMS_IFSC_ID;    // 하단에 표출할 정보가 없을 경우 첫번째 제공구간을 표출하기 위함. 20200515 추가함
                                        bTraffic = true;  //소통정보가 하나라도 존재함
                                        break;
                                    }
                                }
                            }
                        }

                        /////////////////////////////////////////////////////// TODO 20200528 ==> 민간정보 연계에서 정보가 수집되지 않는 경우 가 종종 있어서
                        ///////////////////////////////////////////////////////                   도형식 소통정보를 채우지 못한다.
                        ///////////////////////////////////////////////////////                   결측구간이 3구간 이상이면 도형식 소통정보 표출하지 말자
                        if (bTraffic)
                        {
                            int       nMissingCnt = 0;
                            TCDSIfsc *pTmpIfsc1;
                            FOR_STL(TCDSImageCell*, pCell, pBakTrfImg->FLists)
                            {
                                if (pCell->IsDup) continue; //중복 VMS_IFSC_ID 인 경우 skip...

                                pTmpIfsc1 = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                if (pTmpIfsc1)
                                {
                                    if (pTmpIfsc1->CMTR_GRAD_CD == "0")
                                    {
                                        nMissingCnt++;
                                    }
                                }
                            }
                            if (nMissingCnt >= 3)
                            {
                                bTraffic == false;
                                MERROR("LoadVmsScheduleInfo: VMS Figure IFSC Traffic Missing count over: VmsNmbr(%s)-[%s], %d EA Missing", VMS_CTLR_NMBR.c_str(), VMS_FORM_ID.c_str(), nMissingCnt);
                            }
                        }

                        if (bTraffic == false)
                        {
                            //도형식 구간의 모든 소통정보가 생성되지 않았음===> 가공서버가 죽었거나 수집되지 않았음.
                            //표출할 내용이 없음==> skip 해야함
                            MERROR("LoadVmsScheduleInfo: VMS Figure IFSC Traffic Failed: VmsNmbr(%s)-[%s]", VMS_CTLR_NMBR.c_str(), VMS_FORM_ID.c_str());
                            continue;
                        }
                    }

                    //도형식 소통정보 폼일때 하단에 정보제공구간 소통정보를 표출해야 하는 경우
                    if (pCDSForm->VMS_FORM_TYPE_CD == eFormtp_figure && pCDSForm->TrfIfsc)
                    {
                        //도형식 VMS인 경우 하단에 소통정보를 표출하는 경우 다중폼이 생성됨
                        //제공구간소통정보가 정체, 지체인 경우만 하단 소통정보를 표출함
                        //도형식 배경셀에 등록된 구간에 대해서 표출하도록함
                        TCDSImage *pBakTrfImg = CDSImageManager->FLists.Find(pCDSForm->TrfBakImgId);
                        if (pBakTrfImg)
                        {
                            TCDSIfsc *pTmpIfsc1;
                            //정체구간 갯수 확인
                            FOR_STL(TCDSImageCell*, pCell, pBakTrfImg->FLists)
                            {
                                if (pCell->IsDup) continue; //중복 VMS_IFSC_ID 인 경우 skip...

                                pTmpIfsc1 = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                if (pTmpIfsc1)
                                {
                                    if (pTmpIfsc1->CMTR_GRAD_CD == "3")
                                    {
                                        bBottomTraffic = true;  //도형식배경소통정보의 셀내의 구간정보 소통정보가 하나라도 있으면
                                                                //도형식 소통정보를 표출함
                                        nFigureTrafficCnt++;
                                        //break;
                                    }
                                }
                            }
                            //지체(서행)구간 갯수 확인
                            FOR_STL(TCDSImageCell*, pCell, pBakTrfImg->FLists)
                            {
                                if (pCell->IsDup) continue; //중복 VMS_IFSC_ID 인 경우 skip...

                                pTmpIfsc1 = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                if (pTmpIfsc1)
                                {
                                    if (pTmpIfsc1->CMTR_GRAD_CD == "2")
                                    {
                                        bBottomTraffic = true;  //도형식배경소통정보의 셀내의 구간정보 소통정보가 하나라도 있으면
                                                                //도형식 소통정보를 표출함
                                        nFigureTrafficCnt++;
                                        //break;
                                    }
                                }
                            }

                            //////////////////////// 20200515 추가함(S)
                            if (FIGURE_VMS_IFSC_ID != "" && bBottomTraffic == false)
                            {
                                //소통정보는 존재하지만 지체, 정체가 없는 경우 하단 소통정보를 표출못하게 된다.
                                //만일 하단 고정문자가 존재하는 경우 하단 고정문자를 표출하면 되지만
                                //고정문자가 존재하기 않으면 하단에 표출할 정보가 없으므로 첫번째 구간의 정보를 표출하도록 한다.
                                if (pCDSForm->TrfFixed == false)
                                {
                                    bBottomTraffic = true;   //첫번째 소통정보가 표출되도록 함
                                    nFigureTrafficCnt++;
                                }
                            }
                            //////////////////////// 20200515 추가함(E)
                        }
                    }

                    //도형식 소통정보 폼일때 하단에 VMS 축 소통정보를 표출해야 하는 경우
                    if (pCDSForm->VMS_FORM_TYPE_CD == eFormtp_figure && pCDSForm->TrfAxis)
                    {
                        //도형식 VMS인 경우 하단에 소통정보를 표출하는 경우 다중폼이 생성됨
                        //축 소통정보인 경우 모든 축에 대해 소통정보를 표출, 최대 표출설정값이 설정된 경우 설정값만큼만 표출되게 수정(20200515)
                        FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                        {
                            if (!pIfsc->IsUsed) continue;
                            pCDSIfsc = CDSIfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                            if (!pCDSIfsc) continue;

                            if (pCDSIfsc->AXIS_YN != "Y") continue;
                            if (pCDSIfsc->CMTR_GRAD_CD != "0")
                            {
                                if (FIGURE_VMS_IFSC_ID == "")
                                {
                                    FIGURE_VMS_IFSC_ID = pIfsc->VMS_IFSC_ID;    // 하단에 표출할 정보가 없을 경우 첫번째 제공구간을 표출하기 위함. 20200515 추가함
                                }
                                bBottomTraffic = true;
                                nFigureTrafficCnt++;
                                //break;
                            }
                        }
                        //////////////////////// 20200515 추가함(S)
                        if (FIGURE_VMS_IFSC_ID != "" && bBottomTraffic == false)
                        {
                            //소통정보는 존재하지만 지체, 정체가 없는 경우 하단 소통정보를 표출못하게 된다.
                            //만일 하단 고정문자가 존재하는 경우 하단 고정문자를 표출하면 되지만
                            //고정문자가 존재하기 않으면 하단에 표출할 정보가 없으므로 첫번째 구간의 정보를 표출하도록 한다.
                            if (pCDSForm->TrfFixed == false)
                            {
                                bBottomTraffic = true;   //첫번째 소통정보가 표출되도록 함
                                nFigureTrafficCnt++;
                            }
                        }
                        //////////////////////// 20200515 추가함(E)
                    }

                    //////////////////////// 20200515 추가함(S)
                    if (bBottomTraffic && g_AppCfg.BottomTrafficMaxCnt > 0)
                    {
                        //하단소통정보를 일정갯수만 표출하는 경우 표출할 소통정보가 설정값보다 크면 설정값으로 맞춘다.
                        if (nFigureTrafficCnt > g_AppCfg.BottomTrafficMaxCnt)
                        {
                            nFigureTrafficCnt = g_AppCfg.BottomTrafficMaxCnt;
                        }
                        if (g_AppCfg.BottomTrafficCycle > 0)
                        {
                            int nTm = nFigureDisplayTm / nFigureTrafficCnt;
                            if (nTm < g_AppCfg.BottomTrafficCycle)
                            {
                                //표출할 시간이 설정값보다 작으로 설정값으로 표출시각을 설정
                                nFigureDisplayTm = g_AppCfg.BottomTrafficCycle;
                            }
                            else
                            {
                                nFigureDisplayTm = nTm; // 설정값보다 크면 계산된 값을 표출시각으로 설정
                            }
                        }
                    }
                    //////////////////////// 20200515 추가함(E)

                    nBottomTrafficCnt = 0;
                    if (bBottomTraffic)
                    {
                        //도형식 다중 소통정보 표출인 경우
                        //하단소통정보를 표출하는경우 정체, 지체 순으로 표출
                        if (pCDSForm->TrfIfsc)
                        {
                            //정보제공구간 소통정보 순환표출(정체)
                            //도형식 배경셀에 등록된 구간에 대해서 표출하도록함
                            TCDSImage *pBakTrfImg1 = CDSImageManager->FLists.Find(pCDSForm->TrfBakImgId);
                            if (pBakTrfImg1)
                            {
                                FOR_STL(TCDSImageCell*, pCell, pBakTrfImg1->FLists)
                                {
                                    if (pCell->IsDup) continue; //중복 VMS_IFSC_ID 인 경우 skip...

                                    TCDSIfsc *pTmpIfsc1 = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                    if (!pTmpIfsc1) continue;

                                    if (pTmpIfsc1->CMTR_GRAD_CD != "3") continue;

                                    nIdx = pObj->SCHEDULE->Count;
                                    if (nIdx < VMS_MAX_SCHEDULE)
                                    {
                                        nIdx = pObj->SCHEDULE->Count;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                                        pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                        pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pCell->VMS_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = nFigureDisplayTm; //도형식폼이 실제로 표출될 시간
                                        pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pCell->VMS_IFSC_ID;  //하단 제공구간 ID
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                                        pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                                        pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                                        pObj->SCHEDULE->Count++;
                                        nSelCnt++;
                                        nBottomTrafficCnt++;
                                        if (g_AppCfg.BottomTrafficMaxCnt > 0 && nBottomTrafficCnt >= g_AppCfg.BottomTrafficMaxCnt)
                                        {
                                            break;
                                        }
                                    }
                                }
                            }

                            //정보제공구간 소통정보 순환표출(지체)
                            //도형식 배경셀에 등록된 구간에 대해서 표출
                            TCDSImage *pBakTrfImg2 = CDSImageManager->FLists.Find(pCDSForm->TrfBakImgId);
                            if (pBakTrfImg2)
                            {
                                FOR_STL(TCDSImageCell*, pCell, pBakTrfImg2->FLists)
                                {
                                    if (pCell->IsDup) continue; //중복 VMS_IFSC_ID 인 경우 skip...

                                    TCDSIfsc *pTmpIfsc1 = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                    if (!pTmpIfsc1) continue;

                                    if (pTmpIfsc1->CMTR_GRAD_CD != "2") continue;

                                    if (g_AppCfg.BottomTrafficMaxCnt > 0 && nBottomTrafficCnt >= g_AppCfg.BottomTrafficMaxCnt)
                                    {
                                        break;
                                    }
                                    nIdx = pObj->SCHEDULE->Count;
                                    if (nIdx < VMS_MAX_SCHEDULE)
                                    {
                                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                                        nIdx = pObj->SCHEDULE->Count;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                                        pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                        pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pCell->VMS_IFSC_ID;
                                        pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = "";
                                        pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = "";
                                        pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = "";
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = nFigureDisplayTm; //도형식폼이 실제로 표출될 시간
                                        pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pCell->VMS_IFSC_ID;  //하단 제공구간 ID
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                                        pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                                        pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                                        pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                                        pObj->SCHEDULE->Count++;
                                        nSelCnt++;
                                        nBottomTrafficCnt++;
                                    }
                                }
                            }

                            //////////////////////// 20200515 추가함(S)
                            if (nBottomTrafficCnt == 0)
                            {
                                //소통정보가 모두 소통원활이고 하단고정문자표출도 없는 경우 첫번째 정보제공구간의 소통정보를 표출하도록 한다.
                                nIdx = pObj->SCHEDULE->Count;
                                if (nIdx < VMS_MAX_SCHEDULE)
                                {
                                    pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                                    nIdx = pObj->SCHEDULE->Count;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                                    pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FIGURE_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = "";
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = nFigureDisplayTm; //도형식폼이 실제로 표출될 시간
                                    pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = FIGURE_VMS_IFSC_ID;  //하단 제공구간 ID
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                                    pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                                    pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                                    pObj->SCHEDULE->Count++;
                                    nSelCnt++;
                                    nBottomTrafficCnt++;
                                }
                            }
                            //////////////////////// 20200515 추가함(E)
                        }   //도형식배경소통정보 처리 완료

                        if (pCDSForm->TrfAxis)
                        {
                            //축소통정보 순환표출
                            FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                            {
                                if (!pIfsc->IsUsed) continue;
                                pCDSIfsc = CDSIfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                                if (!pCDSIfsc) continue;

                                if (pCDSIfsc->AXIS_YN != "Y") continue;
                                if (pCDSIfsc->CMTR_GRAD_CD == "0") continue;

                                nIdx = pObj->SCHEDULE->Count;
                                if (nIdx < VMS_MAX_SCHEDULE)
                                {
                                    nIdx = pObj->SCHEDULE->Count;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                                    pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = nFigureDisplayTm; //도형식폼이 실제로 표출될 시간
                                    pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pIfsc->VMS_IFSC_ID;  //하단 제공구간 ID
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                                    pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                                    pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                                    pObj->SCHEDULE->Count++;
                                    nSelCnt++;
                                    nBottomTrafficCnt++;
                                    if (g_AppCfg.BottomTrafficMaxCnt > 0 && nBottomTrafficCnt >= g_AppCfg.BottomTrafficMaxCnt)
                                    {
                                        break;
                                    }
                                }
                            }

                            //////////////////////// 20200515 추가함(S)
                            if (nBottomTrafficCnt == 0)
                            {
                                //소통정보가 모두 소통원활이고 하단고정문자표출도 없는 경우 첫번째 VMS축의 소통정보를 표출하도록 한다.
                                nIdx = pObj->SCHEDULE->Count;
                                if (nIdx < VMS_MAX_SCHEDULE)
                                {
                                    nIdx = pObj->SCHEDULE->Count;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                                    pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                                    pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FIGURE_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = FIGURE_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = FIGURE_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FIGURE_VMS_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = nFigureDisplayTm; //도형식폼이 실제로 표출될 시간
                                    pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = FIGURE_VMS_IFSC_ID;  //하단 제공구간 ID
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                                    pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                                    pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                                    pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                                    pObj->SCHEDULE->Count++;
                                    nSelCnt++;
                                    nBottomTrafficCnt++;
                                }
                            }
                            //////////////////////// 20200515 추가함(E)
                        }
                    }
                    else
                    {
                        //도형식 다중표출이 아닌경우(하단소통정보가 없는 경우)
                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case eSchTp_incident:  //돌발
                    //돌발 스케줄인 경우 해당 VMS에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가
                    for (int ii = 0; ii < pObj->INCIDENT->Count; ii++)
                    {
                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->INCIDENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->INCIDENT->Unit[ii];
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case eSchTp_gongsa:  //공사/행사문안
                    //공사/행사 스케줄인 경우 해당 VMS에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가
                    for (int ii = 0; ii < pObj->EVENT->Count; ii++)
                    {
                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->EVENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->EVENT->Unit[ii];
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case eSchTp_hongbo: //홍보
                    nIdx = pObj->SCHEDULE->Count;
                    if (nIdx < VMS_MAX_SCHEDULE)
                    {
                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                        pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                        pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                        pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                        pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                        pObj->SCHEDULE->Count++;
                        nSelCnt++;
                    }
                    break;
                case eSchTp_deture:  //우회도로
                    //돌발발생한 구간중 우회도로 구간이 있는경우
                    for (int ii = 0; ii < pObj->INCIDENT->Count; ii++)
                    {
                        if (pObj->INCIDENT->Unit[ii].DETR_ID == "0") continue;

                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->INCIDENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->INCIDENT->Unit[ii];
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }

                    //공사/행사 발생한 구간중 우회도로 구간이 있는경우
                    for (int ii = 0; ii < pObj->EVENT->Count; ii++)
                    {
                        if (pObj->EVENT->Unit[ii].DETR_ID == "0") continue;

                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pObj->EVENT->Unit[ii].VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].EVENT             = &pObj->EVENT->Unit[ii];
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case eSchTp_congest: //정체상황
                    {
                        //VMS에 설정된 모든 정체구간판정구간에 대하여 정체 판정
                        int nCngsCnt = 0;
                        FOR_STL(TVmsIfsc*, pCngs, pObj->FIfscLists)
                        {
                            if (!pCngs->IsUsed) continue;
                            if (!pCngs->CNGS_CNFM_YN) continue; //정체판정이 아닌경우

                            if (pCngs->CNGST_CNT < g_AppCfg.CngsContCnt) continue; //설정되어 있는 정체판정 횟수보다 작으면 정체아님

                            //정체판정된 정체폼 생성
                            //스케쥴갯수를 초과하지 않으면 폼 스케쥴추가
                            nIdx = pObj->SCHEDULE->Count;
                            if (nIdx < VMS_MAX_SCHEDULE && nCngsCnt <= pObj->FMaxCngsForm)
                            {
                                pObj->FExistCngsForm = true;        // TODO: 해당 제어기에 정체폼이 존재하는지를 플래그 설정
                                                                    // 다른 폼들은 정체폼이 존재할때 표출할지 여부가 결정됨

                                pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                                pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                                pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                                pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                                pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = pCngs->VMS_IFSC_ID;
                                pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = "";
                                pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = "";
                                pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = "";
                                pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = "";
                                pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = "";
                                pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = "";
                                pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = "";
                                pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                                pObj->SCHEDULE->Unit[nIdx].VMS_IFSC_ID       = pCngs->VMS_IFSC_ID;
                                pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                                pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                                pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                                pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                                pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                                pObj->SCHEDULE->Count++;
                                nSelCnt++;
                            }
                        }
                    }
                    break;
                case eSchTp_video:  //동영상
                case eSchTp_stream: //스트리밍영상
                    nIdx = pObj->SCHEDULE->Count;
                    if (nIdx < VMS_MAX_SCHEDULE)
                    {
                        //동영상명칭이나 스트리밍주소가 설정되지 않은 것은 표출하지 않는다.
                        if ( (VMS_SCH_FORM_TYPE == eSchTp_video  && SYMB_LIB_NMBR != "" && SYMB_LIB_NMBR != "200" && STRM_ADDR != "") ||
                             (VMS_SCH_FORM_TYPE == eSchTp_stream && SYMB_LIB_NMBR != "" && SYMB_LIB_NMBR == "300" && STRM_ADDR != "") )
                        {
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case eSchTp_atmp: //9:대기환경
                    {
                        AnsiString ATMP_STTN_NMBR = "";
                        bool isAtmp = false;
                        if (CDSAtmpManager)
                        {
                            FOR_STL(TCDSFormObj*, pTmpObj, pCDSForm->FLists)
                            {
                                if (pTmpObj->VMS_FORM_OBJECT_TYPE_CD >= 401 && pTmpObj->VMS_FORM_OBJECT_TYPE_CD <= 413)
                                {
                                    ATMP_STTN_NMBR = pTmpObj->VMS_IFSC_ID;
                                    TCDSAtmp *pAtmp = CDSAtmpManager->FLists.Find(pTmpObj->VMS_IFSC_ID);
                                    if (pAtmp && pAtmp->SUCCESS)
                                    {
                                        isAtmp = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if (isAtmp == false)
                        {
                            //폼에 속한 대기환경의 모든 정보가 유효하지 않는 경우 폼을 생성하지 않는다.
                            MERROR("LoadVmsScheduleInfo: VMS ATMP Failed: VmsNmbr(%s)-[%s]", VMS_CTLR_NMBR.c_str(), VMS_FORM_ID.c_str());
                            break;
                        }

                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
#if 0
                            AnsiString ATMP_STTN_NMBR = pADO->FieldByName("FRST_VMS_IFSC_ID")->AsString;
                            TCDSAtmp *pAtmpObj = CDSAtmpManager->FLists.Find(ATMP_STTN_NMBR);
                            if (!pAtmpObj) break;
                            if (pAtmpObj->SUCCESS == false)
                            {
                                MERROR("LoadVmsScheduleInfo: VMS ATMP Failed: VmsNmbr(%s)-[%s], %s.%s", VMS_CTLR_NMBR.c_str(), VMS_FORM_ID.c_str(), ATMP_STTN_NMBR.c_str(), pAtmpObj->ATMP_STTN_NM.c_str());
                                break;
                            }
#endif

                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = ATMP_STTN_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case eSchTp_park: //10:주차정보
                    {
                        bool isParkingForm = false;
                        FOR_STL(TCDSFormObj*, pTmpObj, pCDSForm->FLists)
                        {
                            if (pTmpObj->VMS_FORM_OBJECT_TYPE_CD == 101 ||
                                pTmpObj->VMS_FORM_OBJECT_TYPE_CD == 102 ||
                                pTmpObj->VMS_FORM_OBJECT_TYPE_CD == 103 ||
                                pTmpObj->VMS_FORM_OBJECT_TYPE_CD == 104)
                            {
                                TCDSPark *pPark = NULL;
                                if (CDSParkManager) {
                                    pPark = CDSParkManager->FLists.Find(pTmpObj->VMS_IFSC_ID);    //주차장아이디로 주차장정보를 찾음
                                }
                                if (pPark && pPark->SUCCESS)
                                {
                                    isParkingForm = true;
                                    break;
                                }
                            }
                        }
                        if (isParkingForm == false)
                        {
                            //폼에 속한 주차장의 모든 정보가 유효하지 않는 경우 폼을 생성하지 않는다.
                            MERROR("LoadVmsScheduleInfo: VMS PARKING Failed: VmsNmbr(%s)-[%s]", VMS_CTLR_NMBR.c_str(), VMS_FORM_ID.c_str());
                            break;
                        }

                        nIdx = pObj->SCHEDULE->Count;
                        if (nIdx < VMS_MAX_SCHEDULE)
                        {
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                            pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                            pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                            pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = "";
                            pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                            pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                            pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                            pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                            pObj->SCHEDULE->Count++;
                            nSelCnt++;
                        }
                    }
                    break;
                case eSchTp_evehicle:   //11:긴급차량우선신호
                    if (pCDSForm->VMS_FORM_DSPL_DRCT_CD == 0) {
                        pObj->IsEVehIngForm = true; // 긴급차량
                    }
                    else {
                        pObj->IsEVehEndForm = true;
                        DSPL_HH = 60;   // 운영종료 메시지는 기타 메시지와 함께 내려보낸다.
                    }

                    nIdx = pObj->SCHEDULE->Count;
                    if (nIdx < VMS_MAX_SCHEDULE)
                    {
                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_TYPE      = VMS_SCH_TYPE;
                        pObj->SCHEDULE->Unit[nIdx].VMS_SCH_FORM_TYPE = VMS_SCH_FORM_TYPE;
                        pObj->SCHEDULE->Unit[nIdx].PHASE             = PHASE;
                        pObj->SCHEDULE->Unit[nIdx].VMS_FORM_ID       = VMS_FORM_ID;
                        pObj->SCHEDULE->Unit[nIdx].FRST_VMS_IFSC_ID  = FRST_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].SECD_VMS_IFSC_ID  = SECD_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].THIR_VMS_IFSC_ID  = THIR_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].FOUR_VMS_IFSC_ID  = FOUR_VMS_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].FRST_IMG_IFSC_ID  = FRST_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].SECD_IMG_IFSC_ID  = SECD_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].THIR_IMG_IFSC_ID  = THIR_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].FOUR_IMG_IFSC_ID  = FOUR_IMG_IFSC_ID;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_HH           = DSPL_HH;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_STRT_HH      = DSPL_STRT_HH;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_END_HH       = DSPL_END_HH;
                        pObj->SCHEDULE->Unit[nIdx].SYMB_LIB_NMBR     = SYMB_LIB_NMBR;
                        pObj->SCHEDULE->Unit[nIdx].STRM_ADDR         = STRM_ADDR;
                        pObj->SCHEDULE->Unit[nIdx].DSPL_CNGS_YN      = DSPL_CNGS_YN;
                        pObj->SCHEDULE->Count++;
                        nSelCnt++;
                    }
                    break;
                }
			}
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    if (0)
    {
        CtlrItr it;
        for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
        {
            TCDSCtlr *pObj = (TCDSCtlr*)it->second;

            if (!pObj->Used) continue;
            MDEBUG("LoadVmsScheduleInfo: VMS Schedule: %s, %d EA.", pObj->CTLR_NMBR.c_str(), pObj->SCHEDULE->Count);
        }
    }

    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
	return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::LoadVmsOperationMode(TADOConnection *ADbConn)
{
	AnsiString  sQry;
	int         nSelCnt = 0;
	TADOQuery  *pADO = NULL;

    DWORD dwTick = GetTickCount();
    SELSTART;

    sQry = "SELECT A.VMS_CTLR_NMBR, A.OPER_MODE,                    \r\n"
           "       NVL(A.VMS_MAX_PHSE_NUM, 16) AS VMS_MAX_PHSE_NUM  \r\n"
           "  FROM TB_VMS_CTLR A                                    \r\n"
           " WHERE A.DEL_YN = 'N'                                   \r\n";

	try
	{
		pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            SQLText(pADO, sQry, false);
			SQLOpen(pADO);

			for( ; !pADO->Eof; pADO->Next())
			{
                AnsiString VMS_CTLR_NMBR = pADO->FieldByName("VMS_CTLR_NMBR")->AsString;

                TCDSCtlr *pObj = CDSCtlrManager->FLists.Find(VMS_CTLR_NMBR);
                if (!pObj) continue;

                pObj->OPER_MODE = pADO->FieldByName("OPER_MODE")->AsString.Trim();
                int nMaxFormCnt = pADO->FieldByName("VMS_MAX_PHSE_NUM")->AsInteger;

                if (pObj->OPER_MODE != "A" && pObj->OPER_MODE != "F" && pObj->OPER_MODE != "B")
                {
                    pObj->OPER_MODE = "A";
                }

                if (pObj->OPER_MODE == "A")
                    pObj->DSTATE.OprMode = 'A';
                else
                if (pObj->OPER_MODE == "B")
                    pObj->DSTATE.OprMode = 'B';
                else
                    pObj->DSTATE.OprMode = 'F';

                if (pObj->CTRLMODE->Control == pObj->DSTATE.OprMode)
                    pObj->FModeChange = false;
                else
                    pObj->FModeChange = true;

                pObj->CTRLMODE->Control = pObj->DSTATE.OprMode;
                pObj->RSTATE.OprMode    = pObj->CTRLMODE->Control;

                //pObj->VMS_MAX_PHSE_NUM = INT_VMS_MAX_FORM;  //nMaxFormCnt;
                if (pObj->VMS_MAX_PHSE_NUM > INT_VMS_MAX_FORM)
                    pObj->VMS_MAX_PHSE_NUM = INT_VMS_MAX_FORM;

                pObj->CTRLMODE->MaxDisplayForm = pObj->VMS_MAX_PHSE_NUM;
#if 0
                if (pObj->CTRLMODE->MaxDisplayForm > INT_MAX_VMS_FORM)
                    pObj->CTRLMODE->MaxDisplayForm = INT_MAX_VMS_FORM;
#endif
                //VMS별 정체폼갯수를 제한하는 경우 여기에서 처리하도록 하자
                pObj->FMaxCngsForm = VMS_MAX_CNGS_FORM;  //현재는 디폴트, 즉 모든정보 생성

                nSelCnt++;
			}
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
		SQLFree(pADO);
	}

    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
	return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::InitVmsDsplPrst(TADOConnection *ADbConn)
{
	int         nSelCnt = 0;
	AnsiString  sQry;
	TADOQuery  *pADO = NULL;

    DWORD dwTick = GetTickCount();
    INSSTART;

    sQry = "INSERT INTO TB_VMS_DSPL_PRST(VMS_CTLR_NMBR, PHASE, DSPL_DT, DNLD_YN)                            \r\n"
           "SELECT VMS_CTLR_NMBR, PHASE, DSPL_DT, DNLD_YN                                                   \r\n"
           "  FROM (SELECT A.VMS_CTLR_NMBR, B.ORD AS PHASE, '19700101000000' AS DSPL_DT, 'N' AS DNLD_YN     \r\n"
           "          FROM TB_VMS_CTLR A,                                                                   \r\n"
           "               (SELECT LEVEL AS ORD FROM DUAL CONNECT BY LEVEL < 11) B                          \r\n"
           "       ) X                                                                                      \r\n"
           " WHERE (VMS_CTLR_NMBR, PHASE) NOT IN (SELECT VMS_CTLR_NMBR, PHASE FROM TB_VMS_DSPL_PRST)        \r\n"
           " ORDER BY VMS_CTLR_NMBR, PHASE                                                                  \r\n";

	try
	{
        pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            SQLText(pADO, sQry, false);
            nSelCnt = SQLExec(pADO);
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
		}
		catch(Exception &e)
		{
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        SQLFree(pADO);
	}

    INSEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
    return nSelCnt;
}
//---------------------------------------------------------------------------

int TCDSManager::UpdateVmsProvideResult(TADOConnection *ADbConn, void *ACtlrObj)
{
	int         nSelCnt = 0;
	AnsiString  sQry;
	TADOQuery  *pADO = NULL;
    int         nFormCnt = 0;

    TCDSCtlr* AObj = (TCDSCtlr*)ACtlrObj;
    if (!AObj) return VERR_MEMORY_ALLOC;

    DWORD dwTick = GetTickCount();
    UPDSTART;

    sQry = "UPDATE TB_VMS_DSPL_PRST      "
           "   SET DSPL_DT       = :p03, "
           "       DNLD_YN       = :p04  "
           " WHERE VMS_CTLR_NMBR = :p01  "
           "   AND PHASE        <= :p02  ";

    int    VMS_CTLR_NMBR;
    int    PHASE;
    String DSPL_DT;
    String DNLD_YN;

	try
	{
        nFormCnt = AObj->pForms->Count();

        if (nFormCnt == 0) return VERR_NONE;

        if (nFormCnt > MAX_VMS_SCENARIO_FORM) {
            MINFO(" INF-ERROR: %25.25s: %s, Form Count Over: %d/%d EA.", __MYFUNC__, AObj->CTLR_NMBR.c_str(), nFormCnt, MAX_VMS_SCENARIO_FORM);
            nFormCnt = MAX_VMS_SCENARIO_FORM;
        }

        pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

        VMS_CTLR_NMBR = AObj->CTLR_NMBR.ToIntDef(0);
        PHASE         = nFormCnt;
        DSPL_DT       = AObj->CTRLMODE->SvcDate;
        DNLD_YN       = AObj->CTRLMODE->Result ? "Y" : "N";

        if (DNLD_YN == "Y" && (AObj->EVEHICLE->IsOcurr || AObj->EVEHICLE->IsEnd)) {
            AObj->EVEHICLE->IsDownload = true;
            AObj->EVEHICLE->dtDownload = Now();
        }

		try
		{
            SQLText(pADO, sQry, false);

            SQLBind(pADO, "p01", VMS_CTLR_NMBR);
            SQLBind(pADO, "p02", PHASE);
            SQLBind(pADO, "p03", DSPL_DT);
            SQLBind(pADO, "p04", DNLD_YN);

            nSelCnt = SQLExec(pADO);
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
		}
		catch(Exception &e)
		{
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}

        UPDEND(nSelCnt, dwTick);
        if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
            TIMEDELAY(nSelCnt, dwTick);
        }

        if (AObj->DSPL_DT == DSPL_DT)
        {
            MWARN(" INF-.DATA: %25.25s: %s, %d EA [%s], Already HS Insert.[%s][%d]", __MYFUNC__,
                AObj->CTLR_NMBR.c_str(), nFormCnt, AnsiString(DNLD_YN).c_str(), AnsiString(AObj->DSPL_DT).c_str(), AObj->PHASE);
            return nSelCnt;
        }

        if (AObj->EVEHICLE->IsOcurr || AObj->EVEHICLE->IsEnd) {
            AObj->EVEHICLE->IsEVechFirst = true;
        }

        int nInsCnt = 0;
        dwTick = GetTickCount();
        INSSTART;
        // 이력 저장--제공시각이 동일한게 이력으로 저장될수 있기때문에 트랜잭션을 다시시작한다.
        // 이전 VMS인 경우 임...
    sQry = "INSERT INTO TB_VMS_DSPL_HS                               \r\n"
           "       (DSPL_DT, VMS_CTLR_NMBR, PHASE,                   \r\n"
           "        VMS_SCH_TYPE, VMS_SCH_FORM_TYPE,                 \r\n"
           "        VMS_FORM_ID, DSPL_HH,                            \r\n"
           "        VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,             \r\n"
           "        VMS_FORM_DSPL_DRCT_CD, VMS_FORM_DSPL_MTHD_CD,    \r\n"
           "        DNLD_YN)                                         \r\n"
           " SELECT DSPL_DT, VMS_CTLR_NMBR, PHASE,                   \r\n"
           "        VMS_SCH_TYPE, VMS_SCH_FORM_TYPE,                 \r\n"
           "        VMS_FORM_ID, DSPL_HH,                            \r\n"
           "        VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,             \r\n"
           "        VMS_FORM_DSPL_DRCT_CD, VMS_FORM_DSPL_MTHD_CD,    \r\n"
           "        DNLD_YN                                          \r\n"
           "   FROM TB_VMS_DSPL_PRST                                 \r\n"
           "  WHERE VMS_CTLR_NMBR = :p01                             \r\n"
           "    AND DSPL_DT       = :p02                             \r\n"
           "    AND PHASE        <= :p03                             \r\n";

		try
		{
            SQLText(pADO, sQry, false);

            SQLBind(pADO, "p01", VMS_CTLR_NMBR);
            SQLBind(pADO, "p02", DSPL_DT);
            SQLBind(pADO, "p03", PHASE);

            nInsCnt = SQLExec(pADO);
            nSelCnt += nInsCnt;

            AObj->DSPL_DT = DSPL_DT;
            AObj->PHASE   = nFormCnt;

		    AObj->CTRLMODE->SaveFlag = true;
			AObj->CTRLMODE->pTimer = Now();

            MINFO(" INF-.DATA: %25.25s: %s, %d EA [%s], HS Insert.[%s][%d]", __MYFUNC__,
                AObj->CTLR_NMBR.c_str(), nFormCnt, AnsiString(DNLD_YN).c_str(), AnsiString(AObj->DSPL_DT).c_str(), AObj->PHASE);

            INSEND(nInsCnt, dwTick);
            if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
                TIMEDELAY(nInsCnt, dwTick);
            }
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
		}
		catch(Exception &e)
		{
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        SQLFree(pADO);
	}

    //MINFO(" INF-.DATA: %25.25s: %s, %d EA [%s]", __MYFUNC__ , AObj->CTLR_NMBR.c_str(), nFormCnt, AnsiString(DNLD_YN).c_str());
    return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::SaveVmsProvideForm(TADOConnection *ADbConn, void *ACtlrObj)
{
// VMS 제공정보 객체 코드
typedef enum en_vms_object_type
{
	vms_obj_none,       /* 0:정보없음 */
	vms_obj_text,       /* 1:문자열 */
	vms_obj_bitmap,     /* 2:Bitmap ID */
	vms_obj_draw,       /* 3:Draw */
} EN_VMS_OBJECT_TYPE;

	AnsiString  sQry;
	AnsiString  uQry;
	TADOQuery  *pADO = NULL;
    int         nSelCnt = 0;

    TCDSCtlr* AObj = (TCDSCtlr*)ACtlrObj;
    if (!AObj) return VERR_MEMORY_ALLOC;

    int nFormCnt = AObj->pForms->Count();
    if (nFormCnt == 0) return VERR_NONE;

    if (nFormCnt > MAX_VMS_SCENARIO_FORM) {
        MINFO(" INF-ERROR: %25.25s: %s, Form Count Over: %d/%d EA.", __MYFUNC__, AObj->CTLR_NMBR.c_str(), nFormCnt, MAX_VMS_SCENARIO_FORM);
        nFormCnt = MAX_VMS_SCENARIO_FORM;
    }

    DWORD dwTick = GetTickCount();
    UPDSTART;

    MINFO(" INF-START: %25.25s: %s, %d EA.", __MYFUNC__, AObj->CTLR_NMBR.c_str(), nFormCnt);

if (g_AppCfg.UpdateMode == 0) {
    sQry = "UPDATE TB_VMS_DSPL_PRST                 "
           "   SET DSPL_DT               = :p03,    "
           "       VMS_SCH_TYPE          = :p04,    "
           "       VMS_SCH_FORM_TYPE     = :p05,    "
           "       VMS_FORM_ID           = :p06,    "
           "       DSPL_HH               = :p07,    "
           "       VMS_DSPL_MSG_DATA     = :p08,    "
           "       VMS_DSPL_MSG_TXT      = :p09,    "
           "       VMS_FORM_DSPL_DRCT_CD = :p10,    "
           "       VMS_FORM_DSPL_MTHD_CD = :p11,    "
           "       VMS_DSPL_MSG_IMAG     = :p12,    "
           "       DNLD_YN               = :p13     "
           " WHERE VMS_CTLR_NMBR = :p01             "
           "   AND PHASE         = :p02             ";
}
else {
    sQry = "MERGE INTO TB_VMS_DSPL_PRST L                                  \r\n"
           "USING (SELECT :p01 AS VMS_CTLR_NMBR,                           \r\n"
           "              :p02 AS PHASE,                                   \r\n"
           "              :p03 AS DSPL_DT,                                 \r\n"
           "              :p04 AS VMS_SCH_TYPE,                            \r\n"
           "              :p05 AS VMS_SCH_FORM_TYPE,                       \r\n"
           "              :p06 AS VMS_FORM_ID,                             \r\n"
           "              :p07 AS DSPL_HH,                                 \r\n"
           "              :p08 AS VMS_DSPL_MSG_DATA,                       \r\n"
           "              :p09 AS VMS_DSPL_MSG_TXT,                        \r\n"
           "              :p10 AS VMS_FORM_DSPL_DRCT_CD,                   \r\n"
           "              :p11 AS VMS_FORM_DSPL_MTHD_CD,                   \r\n"
           "              :p12 AS VMS_DSPL_MSG_IMAG,                       \r\n"
           "              :p13 AS DNLD_YN                                  \r\n"
           "         FROM DUAL) M                                          \r\n"
           " ON (L.VMS_CTLR_NMBR = M.VMS_CTLR_NMBR AND L.PHASE = M.PHASE)  \r\n"
           "WHEN MATCHED THEN                                              \r\n"
           "UPDATE SET L.DSPL_DT               = M.DSPL_DT,                \r\n"
           "           L.VMS_SCH_TYPE          = M.VMS_SCH_TYPE,           \r\n"
           "           L.VMS_SCH_FORM_TYPE     = M.VMS_SCH_FORM_TYPE,      \r\n"
           "           L.VMS_FORM_ID           = M.VMS_FORM_ID,            \r\n"
           "           L.DSPL_HH               = M.DSPL_HH,                \r\n"
           "           L.VMS_DSPL_MSG_DATA     = M.VMS_DSPL_MSG_DATA,      \r\n"
           "           L.VMS_DSPL_MSG_TXT      = M.VMS_DSPL_MSG_TXT,       \r\n"
           "           L.VMS_FORM_DSPL_DRCT_CD = M.VMS_FORM_DSPL_DRCT_CD,  \r\n"
           "           L.VMS_FORM_DSPL_MTHD_CD = M.VMS_FORM_DSPL_MTHD_CD,  \r\n"
           "           L.VMS_DSPL_MSG_IMAG     = M.VMS_DSPL_MSG_IMAG,      \r\n"
           "           L.DNLD_YN               = M.DNLD_YN                 \r\n"
           "WHEN NOT MATCHED THEN                                          \r\n"
           "INSERT (VMS_CTLR_NMBR, PHASE, DSPL_DT,                         \r\n"
           "        VMS_SCH_TYPE, VMS_SCH_FORM_TYPE,                       \r\n"
           "        VMS_FORM_ID, DSPL_HH,                                  \r\n"
           "        VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,                   \r\n"
           "        VMS_FORM_DSPL_DRCT_CD, VMS_FORM_DSPL_MTHD_CD,          \r\n"
           "        VMS_DSPL_MSG_IMAG, DNLD_YN)                            \r\n"
           "VALUES (M.VMS_CTLR_NMBR, M.PHASE, M.DSPL_DT,                   \r\n"
           "        M.VMS_SCH_TYPE, M.VMS_SCH_FORM_TYPE,                   \r\n"
           "        M.VMS_FORM_ID, M.DSPL_HH,                              \r\n"
           "        M.VMS_DSPL_MSG_DATA, M.VMS_DSPL_MSG_TXT,               \r\n"
           "        M.VMS_FORM_DSPL_DRCT_CD, M.VMS_FORM_DSPL_MTHD_CD,      \r\n"
           "        M.VMS_DSPL_MSG_IMAG, M.DNLD_YN)                        \r\n";
}

	try
	{
        pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            AObj->pForms->Lock();

            SQLText(pADO, sQry, false);

            for (int ii = 0; ii < nFormCnt; ii++)
            {
				TVmsForm *pForm = AObj->pForms->GetItem(ii);

                int    VMS_CTLR_NMBR         = AObj->CTLR_NMBR.ToIntDef(0);
                int    PHASE                 = ii+1;
                String DSPL_DT               = AObj->CTRLMODE->SvcDate;
                int    VMS_SCH_TYPE          = pForm->VMS_SCH_TYPE.ToIntDef(0);
                int    VMS_SCH_FORM_TYPE     = pForm->VMS_SCH_FORM_TYPE;
                int    VMS_FORM_ID           = pForm->VMS_FORM_ID.ToIntDef(0);
                int    DSPL_HH               = pForm->DSPL_HH;
                String VMS_DSPL_MSG_DATA     = "";
                String VMS_DSPL_MSG_TXT      = "";
                int    VMS_FORM_DSPL_DRCT_CD = pForm->VMS_FORM_DSPL_DRCT_CD.ToIntDef(0);
                int    VMS_FORM_DSPL_MTHD_CD = pForm->VMS_FORM_DSPL_MTHD_CD.ToIntDef(0);
                String DNLD_YN               = pForm->SvcRes ? "Y" : "N";

                AnsiString sTmp  = "";
                AnsiString sCont = "";

                int nObjCnt, nObjType;
                try
                {
                    //폼종류/표출시간/배경색상
                    sCont.printf("%02X%02X%02X|", pForm->VMS_FORM_TYPE_CD, pForm->DSPL_HH, pForm->VMS_FORM_COLR_CD);
                    VMS_DSPL_MSG_DATA += sCont;

                    nObjCnt = pForm->Count();

                    for (int jj = 0; jj < nObjCnt; jj++)
                    {
                        TVmsFormObj *pFormObj = pForm->GetItem(jj);

                        if (pFormObj->ImageId  == "") pFormObj->ImageId  = "1"; //이력저장용
                        if (pFormObj->TextData == "") pFormObj->TextData = " "; //이력저장용

                        switch(pFormObj->ObjectType)
                        {
                        case   1: //심볼
                        case   2: //이미지
                        case 167: //@우회소통정보이미지
                        case 200: //동영상
                        case 300: //스티리밍영상
                        case 406: //@통합대기등급 이미지
                        case 407: //@미세먼지등급 이미지
                        case 408: //@초미세먼지등급 이미지
                        case 413: //@오존등급이미지
                            nObjType = vms_obj_bitmap;
                            sTmp.printf("%02X%04X%04X%02X%04X%04X%s|",
                                pFormObj->IsBlinking,
                                pFormObj->PosX,
                                pFormObj->PosY,
                                pFormObj->BkColor,
                                pFormObj->Width,
                                pFormObj->Height,
                                pFormObj->ImageId.c_str());

                            sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                            VMS_DSPL_MSG_DATA += sCont;
                            break;
                        case  3: //소통정보배경이미지
                        case 17: //1단,소통정보이미지1
                        case 27: //2단,소통정보이미지2
                        case 37: //3단,소통정보이미지3
                        case 47: //4단,소통정보이미지4
                            {
                                nObjType = vms_obj_draw;
                                sTmp.printf("%02X%04X%04X%02X%04X%04X%s+",
                                    pFormObj->IsBlinking,
                                    pFormObj->PosX,
                                    pFormObj->PosY,
                                    pFormObj->BkColor,
                                    pFormObj->Width,
                                    pFormObj->Height,
                                    pFormObj->ImageId.c_str());

                                sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                                VMS_DSPL_MSG_DATA += sCont;

                                AnsiString sVertex = "";
                                TCDSImage *pSymbol = CDSImageManager->FLists.Find(pFormObj->ImageId);
                                if (pSymbol)
                                {
                                    sTmp = "";
                                    int nCnt = 0;

                                    FOR_STL(TCDSImageCell*, pCell, pSymbol->FLists)
                                    {
                                        TCDSIfsc *pIfsc = NULL;
                                        if (pFormObj->ObjectType == 3)
                                            pIfsc = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                        else
                                            pIfsc = CDSIfscManager->FLists.Find(pFormObj->IFSC_ID);

                                        if (pIfsc)
                                        {
                                            sVertex.sprintf("%03d%03d%d", pCell->POSX, pCell->POSY, pIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                            sTmp += sVertex;
                                            nCnt++;
                                        }
                                    }
                                    sCont.printf("%02X%s|", nCnt, sTmp.c_str());
                                    VMS_DSPL_MSG_DATA += sCont;
                                }
                                else
                                {
                                    VMS_DSPL_MSG_DATA += "X|";
                                }
                            }
                            break;
                        default://기타 문자열
                            VMS_DSPL_MSG_TXT += pFormObj->TextData;
                            VMS_DSPL_MSG_TXT += " ";

                            nObjType = vms_obj_text;
                            sTmp.printf("%02X%04X%04X%02X%02X%02X%02X%02X%02X%s|",
                                pFormObj->IsBlinking,
                                pFormObj->PosX,
                                pFormObj->PosY,
                                pFormObj->BkColor,
                                pFormObj->TextFontSize,
                                pFormObj->TextFontColor,
                                pFormObj->TextFontName,
                                pFormObj->TextFontBold,
                                pFormObj->TextData.Length(),
                                pFormObj->TextData);

                            sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                            VMS_DSPL_MSG_DATA += sCont;
                            break;
                        }
                    }

                    /*
                    *  웹접근성에서 홍보이미지도 alt 로 내용을 지원해야 하기때문에
                    *  폼의 설명이 우선적으로 설정되도록 프로그램 수정(20210615)
                    */
                    if (VMS_DSPL_MSG_TXT == "")
                    {
                        TCDSForm *pCDSForm = CDSFormManager->FLists.Find(pForm->VMS_FORM_ID);
                        if (pCDSForm)
                        {
                            if (pCDSForm->VMS_FORM_EXPL.Length() > pCDSForm->VMS_FORM_NM.Length())
                            {
                                VMS_DSPL_MSG_TXT = pCDSForm->VMS_FORM_EXPL;
                            }
                            else
                            {
                                VMS_DSPL_MSG_TXT = pCDSForm->VMS_FORM_NM;
                            }
                        }
                    }

                    if (VMS_DSPL_MSG_DATA.Length() > 1500) VMS_DSPL_MSG_DATA = VMS_DSPL_MSG_DATA.SubString(1, 1499);
                    if (VMS_DSPL_MSG_TXT.Length()  > 400) VMS_DSPL_MSG_TXT  = VMS_DSPL_MSG_TXT.SubString(1, 399);

                    SQLBind(pADO, "p01", VMS_CTLR_NMBR);
                    SQLBind(pADO, "p02", PHASE);
                    SQLBind(pADO, "p03", DSPL_DT);
                    SQLBind(pADO, "p04", VMS_SCH_TYPE);
                    SQLBind(pADO, "p05", VMS_SCH_FORM_TYPE);
                    SQLBind(pADO, "p06", VMS_FORM_ID);
                    SQLBind(pADO, "p07", DSPL_HH);
                    SQLBind(pADO, "p08", VMS_DSPL_MSG_DATA);
                    SQLBind(pADO, "p09", VMS_DSPL_MSG_TXT);
                    SQLBind(pADO, "p10", VMS_FORM_DSPL_DRCT_CD);
                    SQLBind(pADO, "p11", VMS_FORM_DSPL_MTHD_CD);
                    pADO->Parameters->ParamByName("p12")->LoadFromStream(pForm->pStream, ftBlob);
                    SQLBind(pADO, "p13", DNLD_YN);
                    SQLExec(pADO);

                    nSelCnt++;
                }
                __finally
                {
                }
            }
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
		}
		catch(Exception &e)
		{
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        AObj->pForms->UnLock();

        SQLFree(pADO);
	}

    MINFO(" INF-..END: %25.25s: %s, %d EA. Elapsed: %u ms.", __MYFUNC__, AObj->CTLR_NMBR.c_str(), nSelCnt, JOBTIME(dwTick));
    UPDEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
    return nSelCnt;
}
//---------------------------------------------------------------------------
#if 0
int TCDSManager::SaveVmsProvideForm(TADOConnection *ADbConn, void *ACtlrObj)
{
// VMS 제공정보 객체 코드
typedef enum en_vms_object_type
{
	vms_obj_none,       /* 0:정보없음 */
	vms_obj_text,       /* 1:문자열 */
	vms_obj_bitmap,     /* 2:Bitmap ID */
	vms_obj_draw,       /* 3:Draw */
} EN_VMS_OBJECT_TYPE;

#define D_UPDATE

	AnsiString  sQry;
	AnsiString  uQry;
	TADOQuery  *pSADO = NULL;
	TADOQuery  *pUADO = NULL;
    int         nSelCnt = 0;

    DWORD dwTick = GetTickCount();
    UPDSTART;

    TCDSCtlr* AObj = (TCDSCtlr*)ACtlrObj;
    if (!AObj) return VERR_MEMORY_ALLOC;

    int nFormCnt = AObj->pForms->Count();
    if (nFormCnt == 0) return VERR_NONE;

    if (nFormCnt > MAX_VMS_SCENARIO_FORM) {
        MINFO(" INF-ERROR: %25.25s: %s, Form Count Over: %d/%d EA.", __MYFUNC__, AObj->CTLR_NMBR.c_str(), nFormCnt, MAX_VMS_SCENARIO_FORM);
        nFormCnt = MAX_VMS_SCENARIO_FORM;
    }

    sQry = "MERGE INTO TB_VMS_DSPL_PRST L                                  \r\n"
           "USING (SELECT :p01 AS VMS_CTLR_NMBR,                           \r\n"
           "              :p02 AS PHASE,                                   \r\n"
           "              :p03 AS DSPL_DT,                                 \r\n"
           "              :p04 AS VMS_SCH_TYPE,                            \r\n"
           "              :p05 AS VMS_SCH_FORM_TYPE,                       \r\n"
           "              :p06 AS VMS_FORM_ID,                             \r\n"
           "              :p07 AS DSPL_HH,                                 \r\n"
           "              :p08 AS VMS_DSPL_MSG_DATA,                       \r\n"
           "              :p09 AS VMS_DSPL_MSG_TXT,                        \r\n"
           "              :p10 AS VMS_FORM_DSPL_DRCT_CD,                   \r\n"
           "              :p11 AS VMS_FORM_DSPL_MTHD_CD,                   \r\n"
#ifndef D_UPDATE
           "              :p13 AS VMS_DSPL_MSG_IMAG,                       \r\n"
#endif
           "              :p12 AS DNLD_YN                                  \r\n"
           "         FROM DUAL) M                                          \r\n"
           " ON (L.VMS_CTLR_NMBR = M.VMS_CTLR_NMBR AND L.PHASE = M.PHASE)  \r\n"
           "WHEN MATCHED THEN                                              \r\n"
           "UPDATE SET L.DSPL_DT               = M.DSPL_DT,                \r\n"
           "           L.VMS_SCH_TYPE          = M.VMS_SCH_TYPE,           \r\n"
           "           L.VMS_SCH_FORM_TYPE     = M.VMS_SCH_FORM_TYPE,      \r\n"
           "           L.VMS_FORM_ID           = M.VMS_FORM_ID,            \r\n"
           "           L.DSPL_HH               = M.DSPL_HH,                \r\n"
           "           L.VMS_DSPL_MSG_DATA     = M.VMS_DSPL_MSG_DATA,      \r\n"
           "           L.VMS_DSPL_MSG_TXT      = M.VMS_DSPL_MSG_TXT,       \r\n"
           "           L.VMS_FORM_DSPL_DRCT_CD = M.VMS_FORM_DSPL_DRCT_CD,  \r\n"
           "           L.VMS_FORM_DSPL_MTHD_CD = M.VMS_FORM_DSPL_MTHD_CD,  \r\n"
#ifndef D_UPDATE
           "           L.VMS_DSPL_MSG_IMAG     = M.VMS_DSPL_MSG_IMAG,      \r\n"
#endif
           "           L.DNLD_YN               = M.DNLD_YN                 \r\n"
           "WHEN NOT MATCHED THEN                                          \r\n"
           "INSERT (VMS_CTLR_NMBR, PHASE, DSPL_DT,                         \r\n"
           "        VMS_SCH_TYPE, VMS_SCH_FORM_TYPE,                       \r\n"
           "        VMS_FORM_ID, DSPL_HH,                                  \r\n"
           "        VMS_DSPL_MSG_DATA, VMS_DSPL_MSG_TXT,                   \r\n"
           "        VMS_FORM_DSPL_DRCT_CD, VMS_FORM_DSPL_MTHD_CD,          \r\n"
#ifndef D_UPDATE
           "        VMS_DSPL_MSG_IMAG, DNLD_YN)                            \r\n"
#else
           "        DNLD_YN)                                               \r\n"
#endif
           "VALUES (M.VMS_CTLR_NMBR, M.PHASE, M.DSPL_DT,                   \r\n"
           "        M.VMS_SCH_TYPE, M.VMS_SCH_FORM_TYPE,                   \r\n"
           "        M.VMS_FORM_ID, M.DSPL_HH,                              \r\n"
           "        M.VMS_DSPL_MSG_DATA, M.VMS_DSPL_MSG_TXT,               \r\n"
           "        M.VMS_FORM_DSPL_DRCT_CD, M.VMS_FORM_DSPL_MTHD_CD,      \r\n"
#ifndef D_UPDATE
           "        M.VMS_DSPL_MSG_IMAG, M.DNLD_YN)                        \r\n";
#else
           "        M.DNLD_YN)                                             \r\n";
#endif

#ifdef D_UPDATE
    uQry = "UPDATE TB_VMS_DSPL_PRST         \r\n"
           "   SET VMS_DSPL_MSG_IMAG = :p03 \r\n"
           " WHERE VMS_CTLR_NMBR = :p01     \r\n"
           "   AND PHASE         = :p02     \r\n";
#endif

	try
	{
        pSADO = new TADOQuery(NULL);
        pSADO->Connection = ADbConn;

#ifdef D_UPDATE
        pUADO = new TADOQuery(NULL);
        pUADO->Connection = ADbConn;
#endif

		try
		{
            AObj->pForms->Lock();

            SQLText(pSADO, sQry, false);
#ifdef D_UPDATE
            SQLText(pUADO, uQry, false);
#endif

            //ADbConn->BeginTrans();

            for (int ii = 0; ii < nFormCnt; ii++)
            {
				TVmsForm *pForm = AObj->pForms->GetItem(ii);

                String VMS_CTLR_NMBR         = AObj->CTLR_NMBR;
                String PHASE                 = String(ii+1);
                String DSPL_DT               = AObj->CTRLMODE->SvcDate;
                String VMS_SCH_TYPE          = pForm->VMS_SCH_TYPE;
                String VMS_SCH_FORM_TYPE     = pForm->VMS_SCH_FORM_TYPE;
                String VMS_FORM_ID           = pForm->VMS_FORM_ID;
                String DSPL_HH               = String(pForm->DSPL_HH);
                String VMS_DSPL_MSG_DATA     = "";
                String VMS_DSPL_MSG_TXT      = "";
                String VMS_FORM_DSPL_DRCT_CD = pForm->VMS_FORM_DSPL_DRCT_CD;
                String VMS_FORM_DSPL_MTHD_CD = pForm->VMS_FORM_DSPL_MTHD_CD;
                String DNLD_YN               = pForm->SvcRes ? "Y" : "N";

                AnsiString sTmp  = "";
                AnsiString sCont = "";

                int nObjCnt, nObjType;
                try
                {
                    //폼종류/표출시간/배경색상
                    sCont.printf("%02X%02X%02X|", pForm->VMS_FORM_TYPE_CD, pForm->DSPL_HH, pForm->VMS_FORM_COLR_CD);
                    VMS_DSPL_MSG_DATA += sCont;

                    nObjCnt = pForm->Count();

                    for (int jj = 0; jj < nObjCnt; jj++)
                    {
                        TVmsFormObj *pFormObj = pForm->GetItem(jj);

                        if (pFormObj->ImageId  == "") pFormObj->ImageId  = "1"; //이력저장용
                        if (pFormObj->TextData == "") pFormObj->TextData = " "; //이력저장용

                        switch(pFormObj->ObjectType)
                        {
                        case   1: //심볼
                        case   2: //이미지
                        case 167: //@우회소통정보이미지
                        case 200: //동영상
                        case 300: //스티리밍영상
                        case 406: //@통합대기등급 이미지
                        case 407: //@미세먼지등급 이미지
                        case 408: //@초미세먼지등급 이미지
                        case 413: //@오존등급이미지
                            nObjType = vms_obj_bitmap;
                            sTmp.printf("%02X%04X%04X%02X%04X%04X%s|",
                                pFormObj->IsBlinking,
                                pFormObj->PosX,
                                pFormObj->PosY,
                                pFormObj->BkColor,
                                pFormObj->Width,
                                pFormObj->Height,
                                pFormObj->ImageId.c_str());

                            sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                            VMS_DSPL_MSG_DATA += sCont;
                            break;
                        case  3: //소통정보배경이미지
                        case 17: //1단,소통정보이미지1
                        case 27: //2단,소통정보이미지2
                        case 37: //3단,소통정보이미지3
                        case 47: //4단,소통정보이미지4
                            {
                                nObjType = vms_obj_draw;
                                sTmp.printf("%02X%04X%04X%02X%04X%04X%s+",
                                    pFormObj->IsBlinking,
                                    pFormObj->PosX,
                                    pFormObj->PosY,
                                    pFormObj->BkColor,
                                    pFormObj->Width,
                                    pFormObj->Height,
                                    pFormObj->ImageId.c_str());

                                sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                                VMS_DSPL_MSG_DATA += sCont;

                                AnsiString sVertex = "";
                                TCDSImage *pSymbol = CDSImageManager->FLists.Find(pFormObj->ImageId);
                                if (pSymbol)
                                {
                                    sTmp = "";
                                    int nCnt = 0;

                                    FOR_STL(TCDSImageCell*, pCell, pSymbol->FLists)
                                    {
                                        TCDSIfsc *pIfsc = NULL;
                                        if (pFormObj->ObjectType == 3)
                                            pIfsc = CDSIfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                        else
                                            pIfsc = CDSIfscManager->FLists.Find(pFormObj->IFSC_ID);

                                        if (pIfsc)
                                        {
                                            sVertex.sprintf("%03d%03d%d", pCell->POSX, pCell->POSY, pIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                            sTmp += sVertex;
                                            nCnt++;
                                        }
                                    }
                                    sCont.printf("%02X%s|", nCnt, sTmp.c_str());
                                    VMS_DSPL_MSG_DATA += sCont;
                                }
                                else
                                {
                                    VMS_DSPL_MSG_DATA += "X|";
                                }
                            }
                            break;
                        default://기타 문자열
                            VMS_DSPL_MSG_TXT += pFormObj->TextData;
                            VMS_DSPL_MSG_TXT += " ";

                            nObjType = vms_obj_text;
                            sTmp.printf("%02X%04X%04X%02X%02X%02X%02X%02X%02X%s|",
                                pFormObj->IsBlinking,
                                pFormObj->PosX,
                                pFormObj->PosY,
                                pFormObj->BkColor,
                                pFormObj->TextFontSize,
                                pFormObj->TextFontColor,
                                pFormObj->TextFontName,
                                pFormObj->TextFontBold,
                                pFormObj->TextData.Length(),
                                pFormObj->TextData);

                            sCont.printf("%02X%02X%s", nObjType, sTmp.Length(), sTmp.c_str());
                            VMS_DSPL_MSG_DATA += sCont;
                            break;
                        }
                    }

                    /*
                    *  웹접근성에서 홍보이미지도 alt 로 내용을 지원해야 하기때문에
                    *  폼의 설명이 우선적으로 설정되도록 프로그램 수정(20210615)
                    */
                    if (VMS_DSPL_MSG_TXT == "")
                    {
                        TCDSForm *pCDSForm = CDSFormManager->FLists.Find(pForm->VMS_FORM_ID);
                        if (pCDSForm)
                        {
                            if (pCDSForm->VMS_FORM_EXPL.Length() > pCDSForm->VMS_FORM_NM.Length())
                            {
                                VMS_DSPL_MSG_TXT = pCDSForm->VMS_FORM_EXPL;
                            }
                            else
                            {
                                VMS_DSPL_MSG_TXT = pCDSForm->VMS_FORM_NM;
                            }
                        }
                    }

                    if (VMS_DSPL_MSG_DATA.Length() > 1500) VMS_DSPL_MSG_DATA = VMS_DSPL_MSG_DATA.SubString(1, 1499);
                    if (VMS_DSPL_MSG_TXT.Length()  > 400) VMS_DSPL_MSG_TXT  = VMS_DSPL_MSG_TXT.SubString(1, 399);

                    SQLBind(pSADO, "p01", VMS_CTLR_NMBR);
                    SQLBind(pSADO, "p02", PHASE);
                    SQLBind(pSADO, "p03", DSPL_DT);
                    SQLBind(pSADO, "p04", VMS_SCH_TYPE);
                    SQLBind(pSADO, "p05", VMS_SCH_FORM_TYPE);
                    SQLBind(pSADO, "p06", VMS_FORM_ID);
                    SQLBind(pSADO, "p07", DSPL_HH);
                    SQLBind(pSADO, "p08", VMS_DSPL_MSG_DATA);
                    SQLBind(pSADO, "p09", VMS_DSPL_MSG_TXT);
                    SQLBind(pSADO, "p10", VMS_FORM_DSPL_DRCT_CD);
                    SQLBind(pSADO, "p11", VMS_FORM_DSPL_MTHD_CD);
                    SQLBind(pSADO, "p12", DNLD_YN);
#ifndef D_UPDATE
                    pSADO->Parameters->ParamByName("p13")->LoadFromStream(pForm->pStream, ftBlob);
#endif
                    SQLExec(pSADO);

#ifdef D_UPDATE
                    try
                    {
                        SQLBind(pUADO, "p01", VMS_CTLR_NMBR);
                        SQLBind(pUADO, "p02", PHASE);
                        pUADO->Parameters->ParamByName("p03")->LoadFromStream(pForm->pStream, ftBlob);
                        SQLExec(pUADO);

                        //MINFO("[%s] FormImage Size: %d", AObj->VmsNo.c_str(), pForm->pStream->Size);
                        //pForm->pBitmap->SaveToFile(g_sFtpFormDir + AObj->VmsId + "\\" + PHASE + ".bmp");
                        //pImage->Picture->SaveToFile(g_sFtpFormDir + AObj->VmsId + "\\" + PHASE + ".bmp");
                    }
                    catch(Exception &e)
                    {
                    }
#endif

                    nSelCnt++;
                }
                __finally
                {
                }
            }
            //ADbConn->CommitTrans();
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            //if (ADbConn->InTransaction) {
            //    ADbConn->RollbackTrans();
            //}
            return -1;
		}
		catch(Exception &e)
		{
            DBERROR(String(e.ClassName()), e.Message, sQry);
            //if (ADbConn->InTransaction) {
            //    ADbConn->RollbackTrans();
            //}
            return -1;
		}
	}
	__finally
	{
        AObj->pForms->UnLock();

        SQLFree(pSADO);
#ifdef D_UPDATE
        SQLFree(pUADO);
#endif
	}

    MINFO(" INF-.DATA: %25.25s: %s, %d EA.", __MYFUNC__, AObj->CTLR_NMBR.c_str(), nSelCnt);
    UPDEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
    return nSelCnt;
}
//---------------------------------------------------------------------------
#endif

int TCDSManager::LoadVmsOnOffTime(TADOConnection *ADbConn)
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;

    DWORD dwTick = GetTickCount();
    SELSTART;

    sQry = "SELECT A.VMS_CTLR_NMBR, \r\n"
           "       A.PANL_ON_TIME,  \r\n"
           "       A.PANL_OFF_TIME  \r\n"
           "  FROM TB_VMS_CTLR A    \r\n"
           " WHERE A.DEL_YN = 'N'   \r\n";

    BYTE OnOff, OldOnOff;
    int nOnTime, nOffTime, nCurrTime;
    nCurrTime = Now().FormatString("hhnn").ToIntDef(0);
    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
            pADO->Connection = ADbConn;

			SQLText(pADO, sQry, true);

			SQLOpen(pADO);
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VMS_CTLR_NMBR = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();

				TCDSCtlr *pObj = CDSCtlrManager->FLists.Find(VMS_CTLR_NMBR);
                if (!pObj) continue;

                pObj->PANL_ON_TIME       = pADO->FieldByName("PANL_ON_TIME")->AsString.Trim();      //	N	VARCHAR2(4)	Y	'0400'		전광판 ON TIME
                pObj->PANL_OFF_TIME      = pADO->FieldByName("PANL_OFF_TIME")->AsString.Trim();     //	N	VARCHAR2(4)	Y	'0200'		전광판 OFF TIME
                if (pObj->PANL_ON_TIME  == "9999" || pObj->PANL_ON_TIME.Length()  != 4) pObj->PANL_ON_TIME  = "0000";
                if (pObj->PANL_OFF_TIME == "9999" || pObj->PANL_OFF_TIME.Length() != 4) pObj->PANL_OFF_TIME = "0000";

                pObj->MODULE.PowerOnTime  = Now().FormatString("yyyymmdd") + pObj->PANL_ON_TIME;
                pObj->MODULE.PowerOffTime = Now().FormatString("yyyymmdd") + pObj->PANL_OFF_TIME;
                pObj->MODULE.Retry        = VMS_MAX_RETRY_COUNT;

                OldOnOff = pObj->MODULE.OnOff;

                OnOff    = vms_req_board_power_on;
                nOnTime  = pObj->PANL_ON_TIME.ToIntDef(0);
                nOffTime = pObj->PANL_OFF_TIME.ToIntDef(0);
                if (nOnTime != nOffTime)
                {
                    if (nOnTime > nOffTime)
                    {
                        // 0100(off), 0500(on)
                        if (nCurrTime >= nOffTime && nCurrTime < nOnTime)
                        {
                            OnOff = vms_req_board_power_off;
                        }
                    }
                    else
                    if (nOffTime > nOnTime)
                    {
                        // 2300(off), 0500(on)
                        if (nCurrTime >= nOffTime || nCurrTime < nOnTime)
                        {
                            OnOff = vms_req_board_power_off;
                        }
                    }
                }
                if (OldOnOff != OnOff)
                {
                    if (pObj->FSession && pObj->FSession->State == eSS_Connected)
                    {
                        pObj->MODULE.IsOnOff = true;
                        pObj->MODULE.OnOff = OnOff;

                        IPC_JOB_MESSAGE *pMsg = g_jobBuff.GetBuff();
                        pMsg->Type    = eVmsStatusControl;
                        pMsg->ObjPtr  = (DWORD)pObj->FSession;
                        pMsg->Buff[0] = 0x01;
                        pMsg->Buff[1] = OnOff;
                        pMsg->Len     = 2;
                        g_jobQ.PushBlocking((DWORD)pMsg);
                    }
                }
#if 0
                if (pObj->FSession && pObj->FSession->State == eSS_Connected && pObj->MODULE.OnOff != pObj->PANL_PWER_MODE)
                {
                    pObj->MODULE.IsOnOff = true;
                }
#endif

                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
        }
    }
    __finally
    {
        SQLFree(pADO);
    }

//    MINFO("DCOM <<< Check VMS Job Schedule: OnOffTime, %d EA"., nSelCnt);
    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
    return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::LoadVmsDownLoadJob(TADOConnection *ADbConn)
{
    String     sQry;
    TADOQuery *pADO = NULL;
    int        nSelCnt = 0;
    int        nDnIdx;
    VMS_DOWNLOAD_INFO *pInfo;

    DWORD dwTick = GetTickCount();
    SELSTART;

    sQry = "SELECT A.VMS_CTLR_NMBR, A.RGST_DT,                               \r\n"
           "       A.FILETYPE, A.FILEID                                      \r\n"
           "  FROM TB_VMS_DOWNLOAD A                                         \r\n"
           " WHERE A.SENDSTARTDATE <= TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS')   \r\n"
           "   AND A.SENDRESULT = 0                                          \r\n"
           " ORDER BY A.VMS_CTLR_NMBR, A.RGST_DT DESC, A.FILETYPE, A.FILEID  \r\n";


    CtlrItr it;
    for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;
        pObj->InitDownLoadInfo();
    }

    try
    {
        try
        {
            pADO = new TADOQuery(NULL);
            pADO->Connection = ADbConn;

			SQLText(pADO, sQry, true);

			SQLOpen(pADO);
            for( ; !pADO->Eof; pADO->Next())
            {
                AnsiString VMS_CTLR_NMBR     = pADO->FieldByName("VMS_CTLR_NMBR")->AsString.Trim();
				TCDSCtlr *pObj = CDSCtlrManager->FLists.Find(VMS_CTLR_NMBR);
                if (!pObj) continue;

                if (pObj->DOWNLOAD->Count < VMS_MAX_DOWNLOAD)
                {
                    pInfo = pObj->DOWNLOAD;

                    nDnIdx = pInfo->Count++;
                    pInfo->Unit[nDnIdx].RegDate     = pADO->FieldByName("RGST_DT")->AsString;
                    pInfo->Unit[nDnIdx].FileType    = pADO->FieldByName("FILETYPE")->AsString;
                    pInfo->Unit[nDnIdx].FileId      = pADO->FieldByName("FILEID")->AsString;
                    pInfo->Unit[nDnIdx].SendEndDate = Now().FormatString("yyyymmddhhnnss");
                    pInfo->Unit[nDnIdx].SendStep    = send_wait;
                    pInfo->Unit[nDnIdx].SendResult  = vms_download_fail;
                }
                nSelCnt++;
            }
        }
        catch(EDatabaseError &E)
        {
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
        }
        catch(Exception &e)
        {
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
        }
    }
    __finally
    {
        SQLFree(pADO);
    }

    for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;
        if (pObj->DOWNLOAD->Count > 0)
        {
            pObj->DOWNLOAD->Enable   = vms_download_enable;
            pObj->DOWNLOAD->SaveFlag = true;
        }
    }

//    MINFO("DCOM <<< Check VMS Job Schedule: DownloadJob, %d EA.", nSelCnt);
    SELEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
    return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::SaveVmsDownLoadJob(TADOConnection *ADbConn, void *ACtlrObj)
{
	int         nSelCnt = 0;
	AnsiString  sQry;
	TADOQuery  *pADO = NULL;

    TCDSCtlr* AObj = (TCDSCtlr*)ACtlrObj;
    if (!AObj) return VERR_MEMORY_ALLOC;

    DWORD dwTick = GetTickCount();
    UPDSTART;

    MINFO(" INF-START: %25.25s: %s", __MYFUNC__, AObj->CTLR_NMBR.c_str());

    sQry = "UPDATE TB_VMS_DOWNLOAD        "
           "   SET SENDENDDATE   = :p05,  "
           "       SENDSTEP	     = :p06,  "
           "       SENDRESULT    = :p07   "
           " WHERE RGST_DT       = :p01   "
           "   AND VMS_CTLR_NMBR = :p02   "
           "   AND FILETYPE      = :p03   "
           "   AND FILEID        = :p04   ";
	try
	{
        pADO = new TADOQuery(NULL);
        pADO->Connection = ADbConn;

		try
		{
            SQLText(pADO, sQry, false);

            for (int ii = 0; ii < AObj->DOWNLOAD->Count && ii < VMS_MAX_DOWNLOAD; ii++)
            {
                SQLBind(pADO, "p01", AObj->DOWNLOAD->Unit[ii].RegDate);
                SQLBind(pADO, "p02", AObj->CTLR_NMBR);
                SQLBind(pADO, "p03", AObj->DOWNLOAD->Unit[ii].FileType);
                SQLBind(pADO, "p04", AObj->DOWNLOAD->Unit[ii].FileId);
                SQLBind(pADO, "p05", AObj->DOWNLOAD->Unit[ii].SendEndDate);
                SQLBind(pADO, "p06", AObj->DOWNLOAD->Unit[ii].SendStep);
                SQLBind(pADO, "p07", AObj->DOWNLOAD->Unit[ii].SendResult);

                nSelCnt = SQLExec(pADO);
            }
            //pADO->Connection->CommitTrans();
		}
		catch(EDatabaseError &E)
		{
            DBERROR(String(E.ClassName()), E.Message, sQry);
            return -1;
		}
		catch(Exception &e)
		{
            DBERROR(String(e.ClassName()), e.Message, sQry);
            return -1;
		}
	}
	__finally
	{
        SQLFree(pADO);
	}

    MINFO(" INF-..END: %25.25s: %s, %d EA.", __MYFUNC__, AObj->CTLR_NMBR.c_str(), nSelCnt);
    UPDEND(nSelCnt, dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSelCnt, dwTick);
    }
    return nSelCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::SaveVmsDownloadForm(TADOConnection *ADbConn)
{
    int nSaveVmsCnt = 0;
    int nSaveFormCnt = 0;

    DWORD dwTick = GetTickCount();
    JOBSTART;

    //생성한 폼을 데이터베이스에 저장한다.
    CtlrItr it;
    for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;

        if (pObj->Server.useFlag != use_enable) continue;
        if (!pObj->FProvide) continue;

        //PostMessage((HWND)g_AppCfg.lMainWinHandle, WM_PANEL_REFRESH, 2, (LPARAM)clYellow);

        nSaveFormCnt += SaveVmsProvideForm(ADbConn, (void*)pObj);

        //PostMessage((HWND)g_AppCfg.lMainWinHandle, WM_PANEL_REFRESH, 2, (LPARAM)clLime);

        nSaveVmsCnt++;
    }

    //생성한 폼을 제어기에 전송할 수 있도록 플래그를 설정한다.
    for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
    {
        TCDSCtlr *pObj = (TCDSCtlr*)it->second;

        if (pObj->Server.useFlag != use_enable) continue;
        if (!pObj->FProvide) continue;

        if (pObj->pForms->Count() > 0)
        {
            pObj->CTRLMODE->Enable   = object_enable;
            pObj->CTRLMODE->SaveFlag = true;
            pObj->CTRLMODE->Result   = false;
        }
    }

    JOBEND(dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nSaveVmsCnt, dwTick);
    }
	return nSaveVmsCnt;
}
//---------------------------------------------------------------------------
int TCDSManager::SendVmsDownloadForm()
{
    INT_VMS_FORM_SAVE_REQ Req;
    memset((char*)&Req, 0x00, sizeof(Req));
    memcpy(Req.Date, FFormDsplDt.c_str(), INT_VMS_MAX_DATETIME);
    return CComm_VmsFormSaveNotify(&Req);
}
//---------------------------------------------------------------------------
int TCDSManager::MakeVmsScenarioForm(TADOConnection *ADbConn, int ACommand)
{
	int nResult = VERR_NONE;

    DWORD dwTick = GetTickCount();
    JOBSTART;

	CDSManager->ClearVmsProvideMode();

    if (LOAD_DB)
    {
        if (CDSFontManager)  CDSFontManager->LoadFontNameInfo(ADbConn);
        if (CDSImageManager) CDSImageManager->LoadVmsSymbolInfo(ADbConn);
        if (CDSFormManager)  CDSFormManager->LoadVmsFormInfo(ADbConn);
        if (CDSIfscManager)  CDSIfscManager->LoadVmsIfscInfo(ADbConn);
        if (CDSAtmpManager)  CDSAtmpManager->LoadAtmpInfo(ADbConn);
    }

    //대기환경정보를 읽어온다
    if (CDSAtmpManager)
    {
        nResult = CDSAtmpManager->LoadAtmpRtPnstInfo(ADbConn);
        if (nResult < 0)
        {
            MERROR("LoadAtmpRtPnstInfo: error: %d", nResult);
        }
    }

    //주차정보를 읽어온다
    if (CDSParkManager)
    {
        nResult = CDSParkManager->LoadFromDb(ADbConn);
        if (nResult < 0)
        {
            MERROR("CDSParkManager->LoadFromDb: error: %d", nResult);
        }
    }

    if (ACommand != dbm_dnld_form_eveh) {
        // 긴급차량우선신호 이벤트가 아닌경우(즉, 주기 메시지 생성)
        nResult = CDSManager->LoadVmsEVehicleInf(ADbConn, ACommand);
        if (nResult < 0)
        {
            MERROR("LoadVmsEVehicleInf: error: %d", nResult);
        }
    }

    //돌발/공사/행사가 발생한 정보를 VMS에 맵핑한다.
    nResult = CDSManager->LoadVmsEventOccrInf(ADbConn);
    if (nResult < 0)
    {
        MERROR("LoadVmsEventOccrInf: error: %d", nResult);
    }

    // VMS구간 소통정보를 모두 읽어오자..(데이터가 많을 경우 해당되는 정보만 읽어오도록 수정
    nResult = CDSIfscManager->LoadVmsIfscTrafficInfo(ADbConn);
    if (nResult < 0)
    {
        MERROR("LoadVmsIfscTrafficInfo: error: %d", nResult);
    }

    //정체폼을 위한 정체정보 판정
    //스케쥴정보를 읽기전에 VMS별 정체판정조건에 따라 정체정보를 판정한다.
    if (CDSManager->FIsStaticCycle)
    {
        try
        {
            CtlrItr it;
            for(it=CDSCtlrManager->FLists.FObjects.begin(); it != CDSCtlrManager->FLists.FObjects.end(); ++it)
            {
                TCDSCtlr *pObj = (TCDSCtlr*)it->second;

                FOR_STL(TVmsIfsc*, pIfsc, pObj->FIfscLists)
                {
                    if (!pIfsc->IsUsed) continue;
                    if (!pIfsc->CNGS_CNFM_YN) continue; //정체판정이 아닌경우

                    TCDSIfsc *pTrfIfsc = CDSIfscManager->FLists.Find(pIfsc->VMS_IFSC_ID);
                    if (!pTrfIfsc)
                    {
                        pIfsc->CNGST_CNT = 0;
                        continue;
                    }
                    if (pTrfIfsc->SPED <= pIfsc->CNGS_CNFM_SPED)
                    {
                        //현재속도값이 정체판정속도 이하이면 정체판정 횟수를 증가
                        if (pIfsc->CNGST_CNT == 0)
                        {
                            pIfsc->dtCngst = Now();
                        }
                        pIfsc->CNGST_CNT++;
                    }
                    else
                    {
                        //정체판정속도보다 크면 정체횟수를 초기화
                        pIfsc->CNGST_CNT = 0;
                    }
                }
            }
        }
        catch(Exception &e)
        {
        }
    }

    //VMS의 스케줄정보를 조회한다.
    nResult = LoadVmsScheduleInfo(ADbConn);
    if (nResult < 0)
    {
        MERROR("LoadVmsScheduleInfo: error: %d", nResult);
    }

    CDSManager->FIsStaticCycle = false;  //정주기 정보제공주기 플래그 설정

    JOBEND(dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nResult, dwTick);
    }
    return nResult;
}
//---------------------------------------------------------------------------
int TCDSManager::DownloadVmsForm(TADOConnection *ADbConn, int ACommand)
{
	int nResult = 0;

    DWORD dwTick = GetTickCount();
    JOBSTART;

    if (ACommand == dbm_dnld_form_cycle || ACommand == dbm_dnld_form_init)
    {
        //정주기 다운로드 이면 모든 VMS에 메시지다운로드 플래그 활성화 시킴
        //모드변경에 의한 다운로드인경우에는 내부통신을 수신한 곳에서 플래그를 활성화 시켰음.
        //1. 현재 운영모드를 다시 한번 읽음
        if (LoadVmsOperationMode(ADbConn) < 0)
        {
            return -1;
        }

        //모든 VMS에 메시지다운로드 플래그 활성화 시킴
        CDSCtlrManager->InitProvide(NULL);
    }

    nResult = MakeVmsScenarioForm(ADbConn, ACommand);

    JOBEND(dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nResult, dwTick);
    }
	return nResult;
}
//---------------------------------------------------------------------------
int TCDSManager::SaveProvideResult(TADOConnection *ADbConn, void *AData)
{
	int          ii;
    TCDSCtlr    *pObj;
    int          nJobCnt = 0;
    int          nResult;
	VMS_PROVIDE_RESULE *pSave;

    DWORD dwTick = GetTickCount();
    JOBSTART;

    pSave = (VMS_PROVIDE_RESULE*)AData;
    if (!pSave)
    {
        MERROR("SaveProvideResult: Data NULL");
        return -1;
    }

    switch(pSave->Type)
    {
    case provide_form:
        {
            INT_VMS_FORM_DOWNLOAD_REQ VmsSave;

            memset(&VmsSave, 0x00, sizeof(VmsSave));
            VmsSave.Count = 0;

            MINFO(" INF-.DATA: %25.25s: Save Count: %d EA.", __MYFUNC__, pSave->Count);
            for (ii = 0; ii < pSave->Count && ii < MAX_VMS_PROVIDE_RESULT; ii++)
            {
                pObj = (TCDSCtlr*)pSave->pObj[ii];
                if (!pObj) continue;
                if ((nResult = UpdateVmsProvideResult(ADbConn, (void*)pObj)) < 0)
                {
                    MERROR("ProvideSave: UpdateVmsProvideResult failed: %d", nResult);
                }
                else
                {
                    nJobCnt++;

                    memcpy(VmsSave.Unit[VmsSave.Count].VmsId, pObj->CTLR_NMBR.c_str(),         INT_VMS_MAX_ID);
                    memcpy(VmsSave.Unit[VmsSave.Count].Date,  pObj->CTRLMODE->SvcDate.c_str(), INT_VMS_MAX_DATETIME);
                    VmsSave.Unit[VmsSave.Count].Result = pObj->CTRLMODE->Result ? vms_download_succ : vms_download_fail;
                    VmsSave.Count++;

                    if (VmsSave.Count >= INT_VMS_MAX_FORM_DOWNLOAD)
                    {
                        CComm_VmsFormDownLoadNotify(&VmsSave);
                        VmsSave.Count = 0;
                    }
                }
            }
            if (VmsSave.Count > 0)
            {
                CComm_VmsFormDownLoadNotify(&VmsSave);
            }
        }
        break;
    case provide_download:
        for (ii = 0; ii < pSave->Count && ii < MAX_VMS_PROVIDE_RESULT; ii++)
        {
            pObj = (TCDSCtlr*)pSave->pObj[ii];
            if (!pObj) continue;

            nJobCnt++;
            if ((nResult = SaveVmsDownLoadJob(ADbConn, (void*)pObj)) < 0)
            {
                MERROR("SaveProvideResult: SaveVmsDownLoadJob failed: %d", nResult);
            }
        }
        break;
    }

    JOBEND(dwTick);
    if (JOBTIME(dwTick) > g_AppCfg.JobTimeout) {
        TIMEDELAY(nJobCnt, dwTick);
    }
	return nJobCnt;
}
//---------------------------------------------------------------------------
