// <summary>ソースコード：倍率調整（ⅹ×α）モデルクラス</summary>
// <author>CommonMP</author>

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

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

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Tool;

// ToDo namespace は　モデル開発者が変更して、ユニークな名称にして下さい
namespace CommonMP.HYMCO.OptionImpl.McAdjustMultiForDevelop   
{
    /// <summary><para>class outline:</para>
    /// <para>倍率調整（ⅹ×α）モデル</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/03/21][新規作成]</para>
    /// </remarks>
    public class McAdjustMultiModel : McStateCalModelBase
    {
        /// <summary> 演算データ（キャスト用） </summary>
        McAdjustMultiCalInfo m_csAdjustMultiInf = null;   // 便利の為、キャスト用に定義しておく

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

        /// <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 override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;

            // 入力端子数のチェック
            if (lInputDataNum == 0)
            {
                // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND,
                     Properties.McAdjustMultiResources.STATEMENT_NO_REC_PORT);
                // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND, "No Receive Port");
                bRtn = false;
            }
            else if (lInputDataNum > 1)
            {
                // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND,
                     Properties.McAdjustMultiResources.STATEMENT_MULTI_REC_PORT);
                // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND, "Too many Receive Ports. (Not support multi-Receive Ports)");
                bRtn = false;
            }

            m_csAdjustMultiInf.m_lInDim1 = 0;

            for (long lP = 0; lP < lInputDataNum; lP++)
            {   // 入力する伝送データ数分繰り返します。
                long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                long lCellDim = csInputCellData[lP].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);

                //受信パターンを格納
                m_csAdjustMultiInf.m_csInPtn = csInputCellData[lP].GetReceivePatternID();

                // 2015.02.17 流量・水位の入力チェックを削除
                if (McAdjustMultiDefine.IN_PATTERN_FLOW_0D.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {   //流量（ポイント時系列情報）
                }
                else if (McAdjustMultiDefine.IN_PATTERN_LEVEL_0D.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {   //水位（ポイント時系列情報）
                }
                else if (McAdjustMultiDefine.IN_PATTERN_FLOW_1D.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {   //流量（１次元時系列情報）
                }
                else if (McAdjustMultiDefine.IN_PATTERN_LEVEL_1D.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {   //水位（１次元時系列情報）
                }
                else

                if (McAdjustMultiDefine.IN_PATTERN_ARBITRARY_0D.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {   //任意入力（ポイント時系列情報）
                }
                else if (McAdjustMultiDefine.IN_PATTERN_ARBITRARY_1D.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {   //任意入力（１次元時系列情報）
                }
                else
                {
                    bRtn = false;
                    // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND
                        , Properties.McAdjustMultiResources.STATEMENT_UNEXPECT_REC_DATA_TYPE_R + csInputCellData[lP].GetUpperElementID().ToString() + ")");
                    // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND
                    //     , "Unexpected receive data type. (Received from " + csInputCellData[lP].GetUpperElementID().ToString() + ")");
                }

                m_csAdjustMultiInf.m_lInDim1 = Math.Max(m_csAdjustMultiInf.m_lInDim1, lD1);
            }


            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 override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;
            for (long lP = 0; lP < lOutputDataNum; lP++)
            {   // 出力する伝送データ数分繰り返します。
                long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                long lCellDim = csOutputCellData[lP].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);

                //// 2015.02.17 任意入出力のエラーチェックを追加
                //HySID csOutPtnID = csOutputCellData[lP].GetSendPatternID();
                //if (McAdjustMultiDefine.OUT_PATTERN_ARBITRARY_0D.Equals(csOutPtnID) == true)
                //{   //ポイント時系列
                //}
                //else if (McAdjustMultiDefine.OUT_PATTERN_ARBITRARY_1D.Equals(csOutPtnID) == true)
                //{   //1次元時系列
                //}
                //else
                //{
                //    // ver1.5 エラートレース日本語対応
                //    csErrorInf.AddCheckErrorData(this.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND,
                //         Properties.McAdjustMultiResources.STATEMENT_UNEXPECT_SEND_DATA_PATTERN + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //    // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                //    //     "Unexpected send data pattern.");
                //    bRtn = false;
                //}


                //  伝送データの種別に応じての処理 
                //                long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                //                long lCellDim = csOutputCellData[lP].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);

                HySObjectKind csCellType = csOutputCellData[lP].GetTranInfoKind();
                if (McTranInfoDefine.SINGLE_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else if (McTranInfoDefine.D1_CELL_SERIAL.Equals(csCellType) == true)
                {
                }
                else
                {
                    // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND,
                         Properties.McAdjustMultiResources.STATEMENT_UNEXPECT_SEND_DATA_TYPE + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                    // csErrorInf.AddCheckErrorData(this.GetID(), McSumDefine.Sum_KIND,
                    //     "Unexpected send data type.");
                    bRtn = false;
                }

                // 2015.02.17 水位・流量の整合性チェックを実施しない
                //if (McAdjustMultiDefine.OUT_PATTERN_FLOW_0D.Equals(csOutputCellData[lP].GetSendPatternID()) == true)
                //{   //流量
                //    if (McAdjustMultiDefine.IN_PATTERN_FLOW_0D.Equals(m_csAdjustMultiInf.m_csInPtn) == false)
                //    {   //受信パターンが流量（ポイント時系列情報）でない
                //        bRtn = false;
                //       // ver1.5 エラートレース日本語対応
                //        csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND ,
                //             Properties.McAdjustMultiResources.STATEMENT_SND_REC_DATA_NO_MATCH + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //       // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND
                //       //     , "send data Pattern and recive data Pattern do not match. (send to " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //    }
                //}
                //else if (McAdjustMultiDefine.OUT_PATTERN_LEVEL_0D.Equals(csOutputCellData[lP].GetSendPatternID()) == true)
                //{   //水位
                //    if (McAdjustMultiDefine.IN_PATTERN_LEVEL_0D.Equals(m_csAdjustMultiInf.m_csInPtn) == false)
                //    {   //受信パターンが水位（ポイント時系列情報）でない
                //        bRtn = false;
                //       // ver1.5 エラートレース日本語対応
                //        csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND , 
                //              Properties.McAdjustMultiResources.STATEMENT_SND_REC_DATA_NO_MATCH  + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //       // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND
                //       //     , "send data Pattern and recive data Pattern do not match. (send to " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //    }
                //}
                //else if (McAdjustMultiDefine.OUT_PATTERN_FLOW_1D.Equals(csOutputCellData[lP].GetSendPatternID()) == true)
                //{   //流量
                //    if (McAdjustMultiDefine.IN_PATTERN_FLOW_1D.Equals(m_csAdjustMultiInf.m_csInPtn) == false)
                //    {   //受信パターンが流量（１次元時系列情報）でない
                //        bRtn = false;
                //       // ver1.5 エラートレース日本語対応
                //        csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND , 
                //             Properties.McAdjustMultiResources.STATEMENT_SND_REC_DATA_NO_MATCH  + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //       // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND
                //       //     , "send data Pattern and recive data Pattern do not match. (send to " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //    }
                //}
                //else if (McAdjustMultiDefine.OUT_PATTERN_LEVEL_1D.Equals(csOutputCellData[lP].GetSendPatternID()) == true)
                //{   //水位
                //    if (McAdjustMultiDefine.IN_PATTERN_LEVEL_1D.Equals(m_csAdjustMultiInf.m_csInPtn) == false)
                //    {   //受信パターンが水位（１次元時系列情報）でない
                //        bRtn = false;
                //       // ver1.5 エラートレース日本語対応
                //        csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND , 
                //             Properties.McAdjustMultiResources.STATEMENT_SND_REC_DATA_NO_MATCH  + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //       // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND
                //       //     , "send data Pattern and recive data Pattern do not match. (send to " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //    }
                //}
                //else
                //{
                //    bRtn = false;
                //   // ver1.5 エラートレース日本語対応
                //    csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND ,
                //         Properties.McAdjustMultiResources.STATEMENT_UNEXPECT_SEND_DATA_PATTERN  + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //   // csErrorInf.AddCheckErrorData(this.m_csElement.GetID(), McAdjustMultiDefine.ADJUST_MULTI_KIND
                //   //     , "Unexpected send data Pattern. (send to " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                //}
                
            }
            return bRtn;
        }


        /// <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 override bool Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = false;
            McInitialInfo csInDt = csInitialData as McInitialInfo;
            if (csInDt != null)
            {
                bRtn = true;
            }

            
            //格納変数初期化
            m_csAdjustMultiInf.m_dOut = new double[m_csAdjustMultiInf.m_lInDim1];

            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>OnlineInitialize(csInitialData)</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 override bool OnlineInitialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            // 
            return true;
        }
        //=======================
        // 演算実行処理関連メソッド
        //=======================

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputCellData)</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 override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            //倍率
            double dRate = m_csAdjustMultiInf.m_dRate;
            
            long lP = 0;
            HySCellData[] csCellData = csInputCellData[lP].GetInterpolatedCellD1();

            for (long lD1 = 0; lD1 < m_csAdjustMultiInf.m_lInDim1; lD1++)
            {
                m_csAdjustMultiInf.m_dOut[lD1] = csInputCellData[lP].Data(csCellData[lD1], 0) * dRate;
            }

            return 0;
        }
        
        /// <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 override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            HySCellData[] csSndCell = null;

            for (long lP = 0; lP < lOutputDataNum; lP++)
            {   // 出力する伝送データ数分繰り返します。
                long lDim1 = 0; long lDim2 = 0; long lDim3 = 0; long lCellDataNum = 0;
                long lCellDim = csOutputCellData[lP].GetDimension(ref lDim1, ref lDim2, ref lDim3, ref lCellDataNum);

                csSndCell = csOutputCellData[lP].PrepareSendCellD1();
                for (long lD1 = 0; lD1 < Math.Min(m_csAdjustMultiInf.m_lInDim1, lDim1); lD1++)
                {
                    csSndCell[lD1].m_dData[0] = m_csAdjustMultiInf.m_dOut[lD1];
                }
            }

            return 0;
        }


        //====================
        // その他必要なメソッド
        //====================

        /// <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 override bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            bool bRtn = false;
            m_csAdjustMultiInf = (McAdjustMultiCalInfo)m_csCalInfo;

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 演算ステップ時刻設定
                this.m_csDltTime = new HySTime(csPrptyInfo.GetStepTime());

                csPrptyInfo.GetInfo("m_dRate", ref m_csAdjustMultiInf.m_dRate);

                bRtn = true;

            }
            return bRtn;
        }
        /// <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 override bool SetOnlineProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            bool bRtn = false;
            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                bRtn = true;

            }
            return bRtn;
        }


    }
    //
}
