// <summary>ソースコード：ＨＹＭＣＯ演算モデルクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.Interface.Controller;


namespace CommonMP.HYMCO.Interface.Model
{
    /// <summary><para>class outline:</para>
    /// <para>基本演算モデル基底クラス（通常　演算処理は本クラスを派生して作成する）</para>
    /// </summary>
    /// <remarks>
    /// <para>history:</para>
    /// <para>
    /// [CommonMP][ver 1.3.0][2012/12/01][メソッド追加]
    /// [CommonMP][ver 1.4.0][2013/12/10][メソッド追加]
    /// </para>
    /// <para>remarks:</para>
    /// <para> 補間処理付き </para>
    /// </remarks>
    public abstract class McBasicCalculateModelBase : McCalculateModelBase
    {
        /// <summary>セル型入力伝送情報 </summary>
        protected McReceiveCellDataIF[] m_InputCellData = null;
        /// <summary>セル型出力伝送情報 </summary>
        protected McSendCellDataIF[] m_OutputCellData = null;
        /// <summary>演算モデルに対するプロパティ情報設定済判断用フラグ　<para>true:設定済、=false:未設定</para></summary>
        protected bool m_bSetPropertyFlg = false;

        //=========================
        // 演算実行前処理関連メソッド
        //=========================

        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csInputDataList, ref csErrorInf)</para>
        /// </example>
        /// <param name="csInputDataList">入力情報リスト</param>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        public override bool ReceiveConnectionCheck(ref HySDataLinkedList csInputDataList, ref McStructErrorInfo csErrorInf)
        {
            bool bRtn = true;
            bool bChildChekOK = true;
            // 入力情報の配列化
            m_lInputDataNum = csInputDataList.GetCount();
            m_csInputData = new McTranInfo[m_lInputDataNum];
            m_InputCellData = new McReceiveCellDataIF[m_lInputDataNum];


            McTranInfoIFCellType csCellTrnInfo=null;
            csInputDataList.SetCursorFirst();
            for (long lP = 0; lP < m_lInputDataNum; lP++)
            {   // 入力データ数分

                m_csInputData[lP] = csInputDataList.GetCursorData() as McTranInfo;
                if (m_csInputData[lP] == null)
                {
                    bRtn = false;
                    bChildChekOK = false;
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                         Properties.HymcoIFResources.STATEMENT_INPUTDATA_PROPE_NG_R + m_csInputData[lP].GetUpperElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                   //      "Input data property setting is wrong . (Check Connection data property.) (Received from " + m_csInputData[lP].GetUpperElementID().ToString() + ")");
                }
                
                csCellTrnInfo = m_csInputData[lP] as McTranInfoIFCellType;
                if (csCellTrnInfo != null)
                {   // セル型データならば
                    m_InputCellData[lP] = csCellTrnInfo.GetReceiveCellData();
                    if(  m_InputCellData[lP] == null )
                    {
                        bRtn = false;
                        bChildChekOK = false;
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                                 Properties.HymcoIFResources.STATEMENT_WRONG_RECEIVEDATA + m_csInputData[lP].GetConnectionID().ToString() + ")");
                       // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                       //          "Wrong receive data setting.(Received:Connection ID =" + m_csInputData[lP].GetConnectionID().ToString() + ")");
                    }
                    else if (m_InputCellData[lP].GetReceiveTranInfoPattern() == null)
                    {
                        // 受信伝送情報パターン未設定の場合
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                                        Properties.HymcoIFResources.STATEMENT_RECEIVDATA_NO_SET_PROPE );
                       // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                       //                 "ReceiveData Property is not set.");
                        bChildChekOK = false;
                        bRtn = false;
                        // エラーが発生しても最後まで行わせる
                    }
                }
                else
                {
                    bRtn = false;
                    bChildChekOK = false;
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                             Properties.HymcoIFResources.STATEMENT_INPUTDATA_NO_CELLTYPE + m_csInputData[lP].GetUpperElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                   //          "Input data is not CellType.(Received from " + m_csInputData[lP].GetUpperElementID().ToString() + ")");
                }

                csInputDataList.MoveCursorNext();
            }
            if (bChildChekOK == true && m_bSetPropertyFlg == true)
            {
                // プロパティ情報未設定の場合は、子クラスのチェックは行わない
                if (this.ReceiveConnectionCheck(ref csErrorInf, m_lInputDataNum, m_InputCellData) != true)
                {
                    bRtn = false;
                }
            }

            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected abstract bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData);
        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf)
        { 
            // Do Nothing
            return true;
        }


        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csOutputDataList, ref csErrorInf)</para>
        /// </example>
        /// <param name="csOutputDataList">出力情報リスト</param>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        public override bool SendConnectionCheck(ref HySDataLinkedList csOutputDataList, ref McStructErrorInfo csErrorInf)
        {
            bool bRtn = true;
            bool bChildChekOK = true;
            // 出力情報の配列化
            m_lOutputDataNum = csOutputDataList.GetCount();
            m_csOutputData = new McTranInfo[m_lOutputDataNum];
            m_OutputCellData = new McSendCellDataIF[m_lOutputDataNum];

            csOutputDataList.SetCursorFirst();
            for (long lP = 0; lP < m_lOutputDataNum; lP++)
            {   // 出力データ数分
                m_csOutputData[lP] = csOutputDataList.GetCursorData() as McTranInfo;
                McTranInfoIFCellType csCellInfo = m_csOutputData[lP]  as McTranInfoIFCellType;
                if (csCellInfo != null)
                {
                    m_OutputCellData[lP] = csCellInfo.GetSendCellData();
                }
                else
                {
                    m_OutputCellData[lP] = null;
                }
                csOutputDataList.MoveCursorNext();
            }

            if (m_lOutputDataNum != m_OutputCellData.Length)
            {
                bRtn = false;
                bChildChekOK = false;
               // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                         Properties.HymcoIFResources.STATEMENT_OUTPUTDATA_NO_SET_PROPE );
               // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
               //          "Output data property is not set or bad setting parameter.");
            }
            else
            {
                McTranInfoIFCellType csCellTrnInfo = null;
                // 送信するセル型情報にデータを設定する
                for (long lP = 0; lP < m_lOutputDataNum; lP++)
                {   // 出力データ数分
                    csCellTrnInfo = m_csOutputData[lP] as McTranInfoIFCellType;
                    if (csCellTrnInfo != null)
                    {
                        if (m_OutputCellData[lP] != null)
                        {
                            csCellTrnInfo.SetCellIDMngData(m_OutputCellData[lP].GetCellIDMngData());
                            // セル対応データを設定する
                            if (m_OutputCellData[lP].GetTranInfoPattern() != null)
                            {
                                m_OutputCellData[lP].SetTranInfo(m_csOutputData[lP]);
                                //m_csOutputData[lP]
                                if( m_OutputCellData[lP].SendConnectionCheck(ref csErrorInf, (HySID)this.GetID(), McModelLibraryDefine.ELEMENT_CALC) != true )
                                {
                                    bRtn = false;
                                }
                                // エラーが発生しても最後まで行わせる
                            }
                            else
                            {
                               // ver1.5 エラートレース日本語対応
                                csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                                         Properties.HymcoIFResources.STATEMENT_SENDDATA_NO_SET_PROPE );
                               // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                               //          "SendData Property is not set.");
                                bChildChekOK = false;
                                bRtn = false;
                                // エラーが発生しても最後まで行わせる
                            }

                        }
                        else
                        {
                            bRtn = false;
                            bChildChekOK = false;
                           // ver1.5 エラートレース日本語対応
                            csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                                 Properties.HymcoIFResources.STATEMENT_DIMENSION_NO_MATCH + m_csOutputData[lP].GetLowerElementID().ToString() + ")");
                           // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                           //      "Output property is not set  or  output data dimension is not match or is not CellType. (Check Connection data property.)  (Send to " + m_csOutputData[lP].GetLowerElementID().ToString() + ")");
                        }

                    }
                    else
                    {
                        bRtn = false;
                        bChildChekOK = false;
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                                 Properties.HymcoIFResources.STATEMENT_OUTPUTDATA_NO_CELLTYPE + m_csOutputData[lP].GetLowerElementID().ToString() + ")");
                       // csErrorInf.AddCheckErrorData(this.GetID(), McModelLibraryDefine.ELEMENT_CALC,
                       //          "Output data is not CellType.(Send to " + m_csOutputData[lP].GetLowerElementID().ToString() + ")");
                    }
                }
            }
            if (bChildChekOK == true && m_bSetPropertyFlg == true)
            {
                // プロパティ情報未設定の場合は、子クラスのチェックは行わない
                if (this.SendConnectionCheck(ref csErrorInf, m_lOutputDataNum, m_OutputCellData) != true)
                {
                    bRtn = false;
                }
            }

            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected abstract bool SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData);
        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf)
        {
            // Do Nothing.
            return true;
        }

        //=======================
        // 演算実行処理関連メソッド
        //=======================

        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(ref csInitialData, ref csInputDataList, ref csOutputDataList)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="csInputDataList">前段接続要素からの伝送情報リスト</param>
        /// <param name="csOutputDataList">前段接続要素への伝送情報リスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Initialize(ref McPropertyInfoRoot csInitialData, ref HySDataLinkedList csInputDataList, ref HySDataLinkedList csOutputDataList)
        {
            // 内挿処理に現在時刻を設定
            for (long lP = 0; lP < m_lInputDataNum; lP++)
            {   // 入力データ数分
                if (m_InputCellData[lP] != null)
                {
                    m_InputCellData[lP].SetCurrentTime(this.m_csSimTime);
                }
            }
            return this.Initialize(ref csInitialData, m_lInputDataNum, ref m_InputCellData);
            /*
            // 各伝送データに現在時刻を指定して伝送するレコード情報を作成する
            for (long lLp = 0; lLp < m_lOutputDataNum; lLp++)
            {
                if (m_OutputCellData[lLp] != null)
                {
                    m_OutputCellData[lLp].SetCurrentTime(this.m_csSimTime);
                }
            }
            
            this.Initialize(ref csInitialData, m_lInputDataNum, ref m_InputCellData);
            
            // モデルがセットした伝送情報を　実際に伝送データとして流す
            for (long lLp = 0; lLp < m_lOutputDataNum; lLp++)
            {
                if (m_OutputCellData[lLp] != null)
                {
                    m_OutputCellData[lLp].SendData();
                }
            }
            */
        }
        /*
        /// <summary><para>method outline:</para>
        /// <para>接続線のみ初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>InputConnectionInitialize(ref csInitialData, ref csInputDataList)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="csInputDataList">前段接続要素からの伝送情報リスト</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>Initialize()はモデル内部まで初期化するが、本メソッドはモデルに接続されている接続線情報を初期化する</para>
        /// </remarks>
        public override bool InputConnectionInitialize(ref McPropertyInfoRoot csInitialData, ref HySDataLinkedList csInputDataList)
        {
            // 内挿処理に現在時刻を設定
            for (long lP = 0; lP < m_lInputDataNum; lP++)
            {   // 入力データ数分
                if (m_InputCellData[lP] != null)
                {
                    m_InputCellData[lP].SetCurrentTime(this.m_csSimTime);
                }
            }
            return true;
        }
        */

        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract bool Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData);
        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool Initialize(ref McPropertyInfoRoot csInitialData)
        {
            // Do Nothing
            return true;
        }
        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のモデルを初期化</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(ref csInitialData, ref csInputDataList, ref csOutputDataList)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="csInputDataList">前段接続要素からの伝送情報リスト</param>
        /// <param name="csOutputDataList">前段接続要素への伝送情報リスト</param>
        /// <returns>bool</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中に 初期値情報を変更した場合にコールされる(将来拡張用)</para>
        /// </remarks>
        public override bool OnlineInitialize(ref McPropertyInfoRoot csInitialData, ref HySDataLinkedList csInputDataList, ref HySDataLinkedList csOutputDataList)
        {
            // 内挿処理に現在時刻を設定
            for (long lP = 0; lP < m_lInputDataNum; lP++)
            {   // 入力データ数分
                if (m_InputCellData[lP] != null)
                {
                    m_InputCellData[lP].SetCurrentTime(this.m_csSimTime);
                }
            }
            return this.OnlineInitialize(ref csInitialData, m_lInputDataNum, ref m_InputCellData);
        }
        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のモデルを初期化</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>OnlineInitialize(ref csInitialData, lInputDataNum, ref csInputCellData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>bool</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中に 初期値情報を変更した場合にコールされる(将来拡張用)</para>
        /// </remarks>
        protected virtual bool OnlineInitialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            //return this.Initialize(ref csInitialData, lInputDataNum, ref csInputCellData); <-- これを行ってはいけない（初期化したくないモデルもいる）
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル演算可能判別</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = Calculable()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>=true:計算可 =false:計算不可</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Calculable()
        {
            bool bRtn = true;
            if (m_eDtFusionTiming == CommonMP.HYMCO.Interface.McDefine.DataFusionTiming.ASYNCHRONOUS)
            {   // 非同期ならば
                // 上流の全ての要素が必要時刻まで計算されていなければ計算を開始しない
                // 即ち　IsConverged=true で返す。（計算が行われない為、シミュレーション時刻も進行しない）
                for (long lP = 0; lP < m_lInputDataNum; lP++)
                {   // 入力データ数分
                    if (m_csSimTime.After(m_InputCellData[lP].GetLastTime()) == true)
                    {
                        bRtn = false;
                        break;
                    }
                }
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>モデル演算における収束判別</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = IsConverged( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>=true:収束完了 =false:未収束</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool IsConverged()
        {
            bool bRtn = false;
            if (m_csSimTime.Before(m_csTgtTime) != true)
            {   // 計算時刻が、目標時刻を超えたならば
                bRtn = true;
            }
            if (bRtn == false)
            {   // 先の条件で収束していないとき
                if (m_eDtFusionTiming == CommonMP.HYMCO.Interface.McDefine.DataFusionTiming.ASYNCHRONOUS)
                {   // 非同期ならば
                    // 上流の全ての要素が必要時刻まで計算されていなければ計算を開始しない
                    // 即ち　IsConverged=true で返す。（計算が行われない為、シミュレーション時刻も進行しない）
                    for (long lP = 0; lP < m_lInputDataNum; lP++)
                    {   // 入力データ数分
                        if (m_csSimTime.After(m_InputCellData[lP].GetLastTime()) == true)
                        {
                            bRtn = true;
                        }
                    }
                }
            }
            return bRtn;
        }

        ///// <summary><para>method outline:</para>
        ///// <para>演算実行中断中のモデルを初期化</para>
        ///// </summary>
        ///// <example><para>usage:</para>
        ///// <para>Initialize(ref csInitialData, ref csInputDataList, ref csOutputDataList)</para>
        ///// </example>
        ///// <param name="csInitialData">初期化設定情報</param>
        ///// <param name="csInputDataList">前段接続要素からの伝送情報リスト</param>
        ///// <param name="csOutputDataList">前段接続要素への伝送情報リスト</param>
        ///// <returns>無し</returns>
        ///// <exception cref="">無し</exception>
        ///// <remarks><para>remarks:</para>
        ///// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する</para>
        ///// </remarks>
        //public override void OnlineInitialize(ref McPropertyInfoRoot csInitialData, ref HySDataLinkedList csInputDataList, ref HySDataLinkedList csOutputDataList)
        //{
        //    // 必要ならば　派生側でオーバライドさせて処理を追加する
        //}
        
        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputDataList)</para>
        /// </example>
        /// <param name="csInputDataList">演算に必要な入力情報リスト</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override long Calculate(ref HySDataLinkedList csInputDataList)
        {
            // 内挿処理に現在時刻を設定
            for (long lP = 0; lP < m_lInputDataNum; lP++)
            {   // 入力データ数分
                if (m_InputCellData[lP] != null)
                {
                    m_InputCellData[lP].SetCurrentTime(this.m_csSimTime);
                }
            }
            return this.Calculate(m_lInputDataNum, ref m_InputCellData);
        }
        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref InputCellData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData);
        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Calculate()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long Calculate()
        {   
            // Do Nothing
            return 0;
        }
        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion(ref csOutputDataList)</para>
        /// </example>
        /// <param name="csOutputDataList">演算結果を公開する出力情報リスト</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override long DataFusion(ref HySDataLinkedList csOutputDataList)
        {
            long lRtn = 0;
            // 各伝送データに現在時刻を指定して伝送するレコード情報を作成する
            for (long lLp = 0; lLp < m_lOutputDataNum; lLp++)
            {
                if (m_OutputCellData[lLp] != null)
                {
                    m_OutputCellData[lLp].SetCurrentTime(this.m_csSimTime);
                }
            }
            try
            {
                // モデル側で計算した結果を設定する
                lRtn = DataFusion(m_lOutputDataNum, ref m_OutputCellData);
            }
            catch (Exception ex)
            {
                // ログ出力
               // ver1.5 エラートレース日本語対応
                HySLog.LogOut(HySLog.ONLINE, "McCmnElement::DataFusion", 
                    Properties.HymcoIFResources.STATEMENT_CATCH_EXCEPTION +"(" + Properties.HymcoIFResources.STATEMENT_IN_CLASS +")"
                    + this.ToString() + ".DataFusion() :: " + ex.Message );
                // HySLog.LogOut(HySLog.ONLINE, "McCmnElement::DataFusion", "Exception Catch in Class " + this.ToString() + ".DataFusion() :: " + ex.Message); //ex.StackTrace);
                //McLog.DebugOut(this.GetSimulationTime(), GetID(), McLog.SYSTEM, "Exception Catch", " in " + this.ToString() + ".DataFusion() :: " + ex.Message);

                McStructErrorInfo csErrorInfo = HySCommonInfoHash.GetCorrespondData(McDefine.CALCULATION_ERROR_INF, this.m_csElement.GetOwnerProjectID()) as McStructErrorInfo;
                if (csErrorInfo != null)
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInfo.AddSimuErrorData(this.GetID(), McModelLibraryDefine.ELEMENT,
                            Properties.HymcoIFResources.STATEMENT_CATCH_EXCEPTION + this.ToString() + ".DataFusion() :: " + ex.Message);
                   // csErrorInfo.AddSimuErrorData(this.GetID(), McModelLibraryDefine.ELEMENT,
                   //         "Exception Catch in " + this.ToString() + ".DataFusion() :: " + ex.Message);
                }
                lRtn = -1;
            }

            // モデルがセットした伝送情報を　実際に伝送データとして流す
            for (long lLp = 0; lLp < m_lOutputDataNum; lLp++)
            {
                if (m_OutputCellData[lLp] != null)
                {
                    m_OutputCellData[lLp].SendData();
                }
            }
            return lRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion( lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected abstract long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData );     
        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>DataFusion( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long DataFusion()
        {
            // Do Nothing
            return 0;
        }


        // Ver1.3 
        /// <summary><para>method outline:</para>
        /// <para>収束計算に必要な初期出力を強制的に行わせる</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = InitialDataFusionForConvergentCalculation(dErrorVal)</para>
        /// </example>
        /// <param name="dErrorVal">出力の目安を示す値</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override long InitialDataFusionForConvergentCalculation(double dErrorVal)
        {  
            // 各伝送データに現在時刻を指定して伝送するレコード情報を作成する
            for (long lLp = 0; lLp < m_lOutputDataNum; lLp++)
            {
                if (m_OutputCellData[lLp] != null)
                {
                    m_OutputCellData[lLp].SetCurrentTime(this.m_csSimTime);
                }
            }
            return InitialDataFusionForConvergentCalculation(dErrorVal, m_lOutputDataNum, ref m_OutputCellData);
        }
        /// <summary><para>method outline:</para>
        /// <para>収束計算に必要な初期出力を強制的に行わせる</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = InitialDataFusionForConvergentCalculation(dErrorVal, lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="dErrorVal">出力の目安を示す値</param>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual long InitialDataFusionForConvergentCalculation(double dErrorVal, long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            return 0;
        }
        //================
        // 各種設定メソッド
        //================

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csPropertyInfo)</para>
        /// </example>
        /// <param name="csPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McPropertyInfoRoot csPropertyInfo)
        {
            bool bRtn = false;
            // 親クラスでは共通の設定を行う
            McCellModelPropertyIF csCellModelInfo = csPropertyInfo as McCellModelPropertyIF;
            if (csCellModelInfo != null)
            {
                // 出力側の設定
                //if (csCellModelInfo.GetOutputConnectionNumber() != m_lOutputDataNum)
                if (csCellModelInfo.IsAllSendCellDataSet() == false)
                {   // 未設定項目があれば、プロパティが設定されていない可能性がある

                    //csCellModelInfo.MakeRecommendCellData( ); //m_lOutputDataNum, m_csOutputData);
                    // リコメンド設定を行う
                    // 此処では、m_lOutputDataNum, m_csOutputDataは未設定の為、引数で与えれも無意味
                }
                else
                {
                    // セル型データ出力ツールを設定する
                    m_OutputCellData = csCellModelInfo.CreateSendCellData();
                    if (csCellModelInfo.GetStepTime() > 0.0D)
                    {
                        this.SetDeltaTime(new HySTime(csCellModelInfo.GetStepTime()));
                    }
                    bRtn= this.SetProperty(csCellModelInfo);
                    m_bSetPropertyFlg = true;
                }
            }
            return bRtn;
        }

        //★★★★★★★★★★★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(プロパティ情報設定時のメッセージスロー)
        //★★★★★★★★★★★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>モデル構築時にプロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csPropertyInfo, ref csErrorInfo)</para>
        /// </example>
        /// <param name="csPropertyInfo">プロパティ情報</param>
        /// <param name="csErrorInfo">エラー情報</param>
        /// <returns>true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McPropertyInfoRoot csPropertyInfo, ref McStructErrorInfo csErrorInfo)
        {
            bool bRtn = false;
            // 親クラスでは共通の設定を行う
            McCellModelPropertyIF csCellModelInfo = csPropertyInfo as McCellModelPropertyIF;
            if (csCellModelInfo != null)
            {
                // 出力側の設定
                //if (csCellModelInfo.GetOutputConnectionNumber() != m_lOutputDataNum)
                if (csCellModelInfo.IsAllSendCellDataSet() == false)
                {   // 未設定項目があれば、プロパティが設定されていない可能性がある

                    //csCellModelInfo.MakeRecommendCellData( ); //m_lOutputDataNum, m_csOutputData);
                    // リコメンド設定を行う
                    // 此処では、m_lOutputDataNum, m_csOutputDataは未設定の為、引数で与えれも無意味
                }
                else
                {
                    // セル型データ出力ツールを設定する
                    m_OutputCellData = csCellModelInfo.CreateSendCellData();
                    if (csCellModelInfo.GetStepTime() > 0.0D)
                    {
                        this.SetDeltaTime(new HySTime(csCellModelInfo.GetStepTime()));
                    }
                    bRtn = this.SetProperty(csCellModelInfo, ref csErrorInfo);
                    if (bRtn == true)
                    {// 個別要素の設定が正常の場合、フラグを変える必要あり
                        m_bSetPropertyFlg = true;
                    }
                }
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">セル型プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public abstract bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo);
        //★★★★★★★★★★★★★★★★★★★★★★★★★★★
        // Ver1.4で追加(プロパティ情報設定時のメッセージスロー)
        //★★★★★★★★★★★★★★★★★★★★★★★★★★★
        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csCellMdlPropertyInfo, ref csErrorInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">セル型プロパティ情報</param>
        /// <param name="csErrorInfo">エラー情報</param>
        /// <returns>true:正常、false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo, ref McStructErrorInfo csErrorInfo)
        {
            bool bRtn = false;
            bRtn = this.SetProperty(csCellMdlPropertyInfo);
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のプロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetOnlineProperty(csPropertyInfo)</para>
        /// </example>
        /// <param name="csPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する(将来拡張用)</para>
        /// </remarks>
        public override bool SetOnlineProperty(McPropertyInfoRoot csPropertyInfo)
        {
            McCellModelPropertyIF csCellModelInfo = csPropertyInfo as McCellModelPropertyIF;
            if (csCellModelInfo != null)
            {
                return this.SetOnlineProperty(csCellModelInfo);
            }
            else
            {
                return true;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>演算実行中断中のプロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetOnlineProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する(将来拡張用)</para>
        /// </remarks>
        public virtual bool SetOnlineProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            // return this.SetProperty(csCellMdlPropertyInfo); <-- これを行ってはならない。（デフォルトで、変更したくない場合もある）
            //  本メソッドを通るモデルは　自らが、オーバーライドして実装しておく必要がある。
            return true;
        }
    }
}
