using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


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

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

using CommonMP.HYMCO.CoreOptionl.HymcoExpansionModel;

using CommonMP.HYMCO._SYSTEM_;

namespace CommonMP.HYMCO.Ocean.McOceanBaseModel
{
    /// <summary><para>class outline:</para>
    /// <para>海洋モデルモデル経済基底クラス（経済側のモデルは本クラスを派生して作成する）</para>
    /// </summary>
    /// <remarks>
    /// <para>history:</para>
    /// <para>
    /// [2021/12/31][メソッド追加]
    /// </para>
    /// <para>remarks:</para>
    /// <para> 補間処理付き </para>
    /// </remarks>
    public abstract class MzCashflowModelElement : McInterCnnctModel
    {
        /// <summary> 演算データ（キャスト用） </summary>
        protected  MzCashflowModelElementCalInfo m_csOcCashInf = null; // 便利の為、キャスト用に定義しておく

        //-----------------------------------------
        // CO2排出： McOceanBaseDefine.CO2_EMISSION
        protected McPatternRdvSndTranInfoPair m_csRcvCO2DmyCnnct = new McPatternRdvSndTranInfoPair();
        protected McPatternRdvSndTranInfoPair m_csSndCO2EmissionCnnct = new McPatternRdvSndTranInfoPair();

        //-----------------------------------------
        // 売買：売り手
        protected McPatternRdvSndTranInfoPair m_csRcvECBuyCnnct = new McPatternRdvSndTranInfoPair();
        // 売買：買い手
        protected McPatternRdvSndTranInfoPair m_csSndECSellCnnct = new McPatternRdvSndTranInfoPair();

        //-----------------------------------------
        // 製品売買：購入者
        protected McPatternRdvSndTranInfoPair m_csRcvProductBuyCnnct = new McPatternRdvSndTranInfoPair();
        // 製品売買：生産者
        protected McPatternRdvSndTranInfoPair m_csSndProductSellCnnct = new McPatternRdvSndTranInfoPair();

        //-----------------------------------------
        // キャッシュ：請求者
        protected McPatternRdvSndTranInfoPair m_csRcvECCashINCnnct = new McPatternRdvSndTranInfoPair();
        // キャッシュ：支払者
        protected McPatternRdvSndTranInfoPair m_csSndECCashOUTCnnct = new McPatternRdvSndTranInfoPair();

        //----------------------------------------
        // ディバッグ用送信データ
        protected McPatternRdvSndTranInfoPair m_csDebugSendCnnct = new McPatternRdvSndTranInfoPair();


        protected bool m_ActionFlg = false;

        /// <summary> 生産への直接寄与率：例えば調査データは＝１、海上警備行動は、直接生産を生み出さないので＝０ </summary>
        protected double[] m_ContributionRatioForProduct = 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 CheckReceiveDataConnection(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;
            // 使用しやすいようにキャストしておく
            m_csOcCashInf = m_csCalInfo as MzCashflowModelElementCalInfo;

            //-------------------------
            // 売買(買い手：売り手)
            (m_csRcvECBuyCnnct, m_csSndECSellCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.DEALING);

            //-------------------------
            // キャッシュ(請求者：支払者)
            (m_csRcvECCashINCnnct, m_csSndECCashOUTCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.CHASH);
            m_ContributionRatioForProduct = new double[m_csSndECCashOUTCnnct.m_RcvInfNum];

            //-------------------------
            // 製品売買(購買者：生産者)
            (m_csRcvProductBuyCnnct, m_csSndProductSellCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.PRODUCT);


            //------------------------
            // CO2排出
            (m_csRcvCO2DmyCnnct, m_csSndCO2EmissionCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.CO2_EMISSION);

            //-------------------------
            // ディバッグ用送信データ
            m_csDebugSendCnnct = this.PrepareSndPattern(MzOceanBaseDefine.DEBUG_OUT);

            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 CheckSendDataConnection(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;

            return bRtn;
        }


        /// <summary>
        /// 指定パターン送受信情報
        /// </summary>
        protected virtual (McPatternRdvSndTranInfoPair, McPatternRdvSndTranInfoPair) PrepareRcvSndPattern(HySID csPatternID)
        {
            McPatternRdvSndTranInfoPair csRcvRtn = new McPatternRdvSndTranInfoPair();
            McPatternRdvSndTranInfoPair csSndRtn = new McPatternRdvSndTranInfoPair();
            List<McReceiveCellDataIF> csRcvIFListD = new List<McReceiveCellDataIF>();
            List<McSendCellDataIF> csSndIFListD = new List<McSendCellDataIF>();
            List<McReceiveCellDataIF> csRcvIFListU = new List<McReceiveCellDataIF>();
            List<McSendCellDataIF> csSndIFListU = new List<McSendCellDataIF>();

            csRcvRtn.m_PatternID = csPatternID;
            csSndRtn.m_PatternID = csPatternID;
            for (int i = 0; i < m_csMutualConnectionPatternList.Count; i++)
            {
                if (csPatternID.Equals(m_csMutualConnectionPatternList[i].m_PatternID) == true)
                {
                    for (int kk = 0; kk < m_csMutualConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        var SDP = m_csMutualConnectionPatternList[i].m_RcvSndPairList[kk];
                        if (SDP.Item4 == McSndRcvTypeKbn.Rcv)
                        {
                            csRcvIFListD.Add(SDP.Item1);
                            csSndIFListD.Add(SDP.Item2);
                        }
                        else if (SDP.Item4 == McSndRcvTypeKbn.Snd)
                        {
                            csRcvIFListU.Add(SDP.Item1);
                            csSndIFListU.Add(SDP.Item2);
                        }
                    }
                    csRcvRtn.m_RcvInfNum = csRcvIFListD.Count;
                    csRcvRtn.m_csRcvInfArry = csRcvIFListD.ToArray();
                    csRcvRtn.m_dRcvRatioData = new double[csRcvRtn.m_RcvInfNum][];
                    csRcvRtn.m_csSndInfArry = csSndIFListD.ToArray();
                    csRcvRtn.m_dSendRatioData = new double[csRcvRtn.m_RcvInfNum][];

                    csSndRtn.m_RcvInfNum = csRcvIFListU.Count;
                    csSndRtn.m_csRcvInfArry = csRcvIFListU.ToArray();
                    csSndRtn.m_dRcvRatioData = new double[csSndRtn.m_RcvInfNum][];
                    csSndRtn.m_csSndInfArry = csSndIFListU.ToArray();
                    csSndRtn.m_dSendRatioData = new double[csSndRtn.m_RcvInfNum][];

                    for (int z = 0; z < csRcvRtn.m_RcvInfNum; z++)
                    {
                        csRcvRtn.m_dRcvRatioData[z] = new double[1];
                        csRcvRtn.m_dSendRatioData[z] = new double[1];
                        csRcvRtn.m_dRcvRatioData[z][0] = 0.0;
                        csRcvRtn.m_dSendRatioData[z][0] = 1.0;
                    }
                    for (int z = 0; z < csSndRtn.m_RcvInfNum; z++)
                    {
                        csSndRtn.m_dRcvRatioData[z] = new double[1];
                        csSndRtn.m_dSendRatioData[z] = new double[1];
                        csSndRtn.m_dRcvRatioData[z][0] = 0.0;
                        csSndRtn.m_dSendRatioData[z][0] = 1.0;
                    }

                    break;
                }
            }
            return (csRcvRtn, csSndRtn);
        }

        /// <summary>
        /// 指定送信パターン情報生成
        /// </summary>
        /// <param name="csPatternID"></param>
        /// <returns></returns>
        protected virtual McPatternRdvSndTranInfoPair PrepareSndPattern(HySID csPatternID)
        {
            McPatternRdvSndTranInfoPair csSndRtn = new McPatternRdvSndTranInfoPair();
            List<McSendCellDataIF> csSndIFListD = new List<McSendCellDataIF>();

            csSndRtn.m_PatternID = csPatternID;

            for (int i = 0; i < m_csSendOnlyConnectionPatternList.Count; i++)
            {
                if (csPatternID.Equals(m_csSendOnlyConnectionPatternList[i].m_PatternID) == true)
                {
                    for (int kk = 0; kk < m_csSendOnlyConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        var SDP = m_csSendOnlyConnectionPatternList[i].m_RcvSndPairList[kk];
                        if (SDP.Item4 == McSndRcvTypeKbn.OnlySnd)
                        {
                            csSndIFListD.Add(SDP.Item2);
                        }
                    }

                    csSndRtn.m_RcvInfNum = csSndIFListD.Count;
                    csSndRtn.m_csRcvInfArry = null;
                    csSndRtn.m_dRcvRatioData = new double[csSndIFListD.Count][];
                    csSndRtn.m_csSndInfArry = csSndIFListD.ToArray();
                    csSndRtn.m_dSendRatioData = new double[csSndRtn.m_RcvInfNum][];

                    for (int z = 0; z < csSndRtn.m_RcvInfNum; z++)
                    {
                        csSndRtn.m_dRcvRatioData[z] = new double[1];
                        csSndRtn.m_dSendRatioData[z] = new double[1];
                        csSndRtn.m_dRcvRatioData[z][0] = 0.0;
                        csSndRtn.m_dSendRatioData[z][0] = 1.0;

                    }
                    break;
                }
            }
            return csSndRtn;
        }

        /// <summary>
        /// 指定受信パターン情報生成
        /// </summary>
        /// <param name="csPatternID"></param>
        /// <returns></returns>
        protected virtual McPatternRdvSndTranInfoPair PrepareRcvPattern(HySID csPatternID)
        {
            McPatternRdvSndTranInfoPair csRcvRtn = new McPatternRdvSndTranInfoPair();
            List<McReceiveCellDataIF> csRcvIFListD = new List<McReceiveCellDataIF>();

            csRcvRtn.m_PatternID = csPatternID;
            for (int i = 0; i < m_csRcvOnlyConnectionPatternList.Count; i++)
            {
                if (csPatternID.Equals(m_csRcvOnlyConnectionPatternList[i].m_PatternID) == true)
                {
                    for (int kk = 0; kk < m_csRcvOnlyConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        var SDP = m_csRcvOnlyConnectionPatternList[i].m_RcvSndPairList[kk];
                        if (SDP.Item4 == McSndRcvTypeKbn.OnlyRcv)
                        {
                            csRcvIFListD.Add(SDP.Item1);
                        }
                    }
                    csRcvRtn.m_RcvInfNum = csRcvIFListD.Count;
                    csRcvRtn.m_csRcvInfArry = csRcvIFListD.ToArray();
                    csRcvRtn.m_dRcvRatioData = new double[csRcvRtn.m_RcvInfNum][];
                    csRcvRtn.m_csSndInfArry = null;
                    csRcvRtn.m_dSendRatioData = new double[csRcvRtn.m_RcvInfNum][];

                    for (int z = 0; z < csRcvRtn.m_RcvInfNum; z++)
                    {
                        csRcvRtn.m_dRcvRatioData[z] = new double[1];
                        csRcvRtn.m_dSendRatioData[z] = new double[1];
                        csRcvRtn.m_dRcvRatioData[z][0] = 0.0;
                        csRcvRtn.m_dSendRatioData[z][0] = 1.0;
                    }
                    break;
                }
            }
            return csRcvRtn;
        }

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

        /// <summary>
        /// 受信
        /// </summary>
        protected override void ReceiveData()
        {
            {
                BuyerReceive();
                SellerReceive();

                ProductBuyerReceive();
                ProductSellerReceive();

                OutcomeReceive();
                ExpenseReceive();
            }
            // 人間行為によって消費するO2：受信
            ReceiveO2Consumption();
            return;
        }

        /// <summary>
        /// 送信例
        /// </summary>
        protected override void SendData()
        {
            if (m_ActionFlg == true)
            {
                BuyerSend();
                SellerSend();
                
                ProductBuyerSend();
                ProductSellerSend();

                CostingSend();
                OutcomeSend();

                //m_csOcCashInf.m_Claimed = 0;
                //m_csOcCashInf.m_EstimatedCost = 0;
            }
            // 人間行為によって排出するCO2：送信
            SendCO2Emission();
            
            //SendDEBUG();
            m_ActionFlg = false;
            return;
        }

        /// <summary>
        /// 人間行為によって消費するO2：受信
        /// </summary>
        protected virtual void ReceiveO2Consumption()
        {
            //------------------------
            //  O2を受け取る               
            for (int i = 0; i < m_csSndCO2EmissionCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csSndCO2EmissionCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    // O2
                    m_csOcCashInf.m_HmnRcvO2 += csCell[0].m_dData[0];
                }
            }

        }
  
        /// <summary>
        /// 人間行為によって排出するCO2：送信
        /// </summary>
        protected virtual void SendCO2Emission()
        {
            HySCellData[] csSndDt = null;

    
            for (int i = 0; i < m_csSndCO2EmissionCnnct.m_RcvInfNum; i++)
            {
                csSndDt = m_csSndCO2EmissionCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }

                csSndDt[0].m_dData[0] = m_csOcCashInf.m_HmnCO2Emission;
                csSndDt[0].m_dData[1] = m_csOcCashInf.m_HmnReqO2;
            }
        }

        //------------McOceanBaseDefine.DEALING--------------
        /// <summary>
        /// 品物受け取り：買い手
        /// </summary>
        protected virtual void BuyerReceive()
        {
            double dSum = 0;
            for (int i = 0; i < m_csRcvECBuyCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvECBuyCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if (csCell[0].m_dData[0] < 0) { csCell[0].m_dData[0] = 0; }
                    dSum += csCell[0].m_dData[0] + 1E-16;
                    // 支払いの為、納入量を覚えておく
                    m_csRcvECBuyCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1E-16;

                    if (csCell[0].m_dData[1] < 0) { csCell[0].m_dData[1] = 0; }
                    if (csCell[0].m_dData[2] < 0) { csCell[0].m_dData[2] = 0; }
                    m_csOcCashInf.ProductBuyerReceive(csCell[0].m_dData[0], csCell[0].m_dData[1], csCell[0].m_dData[2]);
                }
            }
            // 分配係数設定
            for (int i = 0; i < m_csRcvECBuyCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csRcvECBuyCnnct.m_dSendRatioData[i][0] = m_csRcvECBuyCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// 代金支払い：買い手
        /// </summary>
        protected virtual void BuyerSend()
        {
            for (int i = 0; i < m_csRcvECBuyCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csRcvECBuyCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_csOcCashInf.m_dDealingChash * m_csRcvECBuyCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[0] < 0) { csSndDt[0].m_dData[0] = 0; }
                csSndDt[0].m_dData[1] = m_csOcCashInf.m_dNextDealingChash * m_csRcvECBuyCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[1] < 0) { csSndDt[0].m_dData[1] = 0; }
            }
        }
        /// <summary>
        /// 代金受け取り：売り手
        /// </summary>
        protected virtual void SellerReceive()
        {
            double dSum = 0;
            for (int i = 0; i < m_csSndECSellCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csSndECSellCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if (csCell[0].m_dData[0] < 0) { csCell[0].m_dData[0] = 0; }
                    // 発注額
                    dSum += csCell[0].m_dData[1] + 1E-16;
                    m_csSndECSellCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[1] + 1E-16;
                    // 現在支払われた納入金ではなく、次回購入予定である事に注意

                    //// 収入
                    //m_csOcCashInf.m_dNowDealingChash += csCell[0].m_dData[0];
                    //// 発注額
                    //m_csOcCashInf.m_dNextDealingChash += csCell[0].m_dData[1];
                    if (csCell[0].m_dData[1] < 0) { csCell[0].m_dData[1] = 0; }
                    m_csOcCashInf.ProductSellerReceive(csCell[0].m_dData[0], csCell[0].m_dData[1]);
                }
            }
            // 分配係数設定（現在支払われた納入金ではなく、次回購入予定である事に注意）
            for (int i = 0; i < m_csSndECSellCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csSndECSellCnnct.m_dSendRatioData[i][0] = m_csSndECSellCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// 品物納入：売り手
        /// </summary>
        protected virtual void SellerSend()
        {
            // 予め通知された購入額に応じて納入
            for (int i = 0; i < m_csSndECSellCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csSndECSellCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_csOcCashInf.m_dProduct * m_csSndECSellCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[0] < 0) { csSndDt[0].m_dData[0] = 0; }
                csSndDt[0].m_dData[1] = m_csOcCashInf.m_dPrductUnitCost;
                if (csSndDt[0].m_dData[1] < 0) { csSndDt[0].m_dData[1] = 0; }
                csSndDt[0].m_dData[2] = m_csOcCashInf.m_dFeedCapability;
                if (csSndDt[0].m_dData[2] < 0) { csSndDt[0].m_dData[2] = 0; }
            }
        }

        //----------- McOceanBaseDefine.PRODUCT----------------
        /// <summary>
        /// 製品受け取り：買い手
        /// </summary>
        protected virtual void ProductBuyerReceive()
        {
            double dSum = 0;
            for (int i = 0; i < m_csRcvProductBuyCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvProductBuyCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if (csCell[0].m_dData[0] < 0) { csCell[0].m_dData[0] = 0; }
                    dSum += csCell[0].m_dData[0] + 1E-16;
                    // 支払いの為、納入量を覚えておく
                    m_csRcvProductBuyCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1E-16;

                    //m_csOcCashInf.m_Materials += csCell[0].m_dData[0];
                    //m_csOcCashInf.m_dNowUnitCost = csCell[0].m_dData[1];
                    if (csCell[0].m_dData[1] < 0) { csCell[0].m_dData[1] = 0; }
                    //m_csOcCashInf.m_dFeedCapability = csCell[0].m_dData[2];
                    if (csCell[0].m_dData[2] < 0) { csCell[0].m_dData[2] = 0; }
                    m_csOcCashInf.ProductBuyerReceive(csCell[0].m_dData[0], csCell[0].m_dData[1], csCell[0].m_dData[2]);
                }
            }
            // 分配係数設定
            for (int i = 0; i < m_csRcvProductBuyCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csRcvProductBuyCnnct.m_dSendRatioData[i][0] = m_csRcvProductBuyCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// 製品代金支払い：買い手
        /// </summary>
        protected virtual void ProductBuyerSend()
        {
            for (int i = 0; i < m_csRcvProductBuyCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csRcvProductBuyCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_csOcCashInf.m_dDealingChash * m_csRcvProductBuyCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[0] < 0) { csSndDt[0].m_dData[0] = 0; }
                csSndDt[0].m_dData[1] = m_csOcCashInf.m_dNextDealingChash * m_csRcvProductBuyCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[1] < 0) { csSndDt[0].m_dData[1] = 0; }
            }
        }
        /// <summary>
        /// 製品代金受け取り：生産者
        /// </summary>
        protected virtual void ProductSellerReceive()
        {
            double dSum = 0;
            for (int i = 0; i < m_csSndProductSellCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csSndProductSellCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if(csCell[0].m_dData[1] < 0) { csCell[0].m_dData[1] = 0; }
                    // 発注額
                    dSum += csCell[0].m_dData[1] + 1E-16;
                    m_csSndProductSellCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[1] + 1E-16;
                    // 現在支払われた納入金ではなく、次回購入予定である事に注意

                    //// 収入
                    //m_csOcCashInf.m_dNowDealingChash += csCell[0].m_dData[0];
                    //// 発注額
                    //m_csOcCashInf.m_dNextDealingChash+ = csCell[0].m_dData[1];
                    if (csCell[0].m_dData[1] < 0) { csCell[0].m_dData[1] = 0; }
                    m_csOcCashInf.ProductSellerReceive(csCell[0].m_dData[0], csCell[0].m_dData[1]);
                }
            }
            // 分配係数設定（現在支払われた納入金ではなく、次回購入予定である事に注意）
            for (int i = 0; i < m_csSndProductSellCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csSndProductSellCnnct.m_dSendRatioData[i][0] = m_csSndProductSellCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// 製品納入：生産者
        /// </summary>
        protected virtual void ProductSellerSend()
        {
            // 予め通知された購入額に応じて納入
            for (int i = 0; i < m_csSndProductSellCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csSndProductSellCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                csSndDt[0].m_dData[0] = m_csOcCashInf.m_dProduct * m_csSndProductSellCnnct.m_dSendRatioData[i][0];
                if(csSndDt[0].m_dData[0] < 0) { csSndDt[0].m_dData[0] = 0; }
                csSndDt[0].m_dData[1] = m_csOcCashInf.m_dPrductUnitCost;
                if (csSndDt[0].m_dData[1] < 0) { csSndDt[0].m_dData[1] = 0; }
                csSndDt[0].m_dData[2] = m_csOcCashInf.m_dFeedCapability;
                if (csSndDt[0].m_dData[2] < 0) { csSndDt[0].m_dData[2] = 0; }
                csSndDt[0].m_dData[3] = 0;
                csSndDt[0].m_dData[4] = 0;
            }
        }

        //---------McOceanBaseDefine.CHASH-----------------
        /// <summary>
        /// 成果受け取り：支払者
        /// </summary>
        protected virtual void OutcomeReceive()
        {
            m_csOcCashInf.m_EstimatedCost = 0.0;
            double dSum = 0;
            for (int i = 0; i < m_csSndECCashOUTCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csSndECCashOUTCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if(csCell[0].m_dData[0] < 0) { csCell[0].m_dData[0] = 0; }
                    // 請求額
                    // 現在支払われた納入金ではなく、請求額である事に注意
                    dSum += csCell[0].m_dData[0] + 1E-16;
                    m_csSndECCashOUTCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1E-16;

                    // 請求額
                    //m_csOcCashInf.m_Claimed += csCell[0].m_dData[0];
                    // 次回の見積もり
                    if (csCell[0].m_dData[1] < 0) { csCell[0].m_dData[1] = 0; }
                    //m_csOcCashInf.m_EstimatedCost = csCell[0].m_dData[1];
                    //m_csOcCashInf.m_NonMaterial_Val += csCell[0].m_dData[0] * csCell[0].m_dData[2];

                    m_ContributionRatioForProduct[i] = csCell[0].m_dData[2];
                    m_csOcCashInf.BuyerReceiveOutcom(csCell[0].m_dData[0], csCell[0].m_dData[1], csCell[0].m_dData[2]);
                }
            }
            // 分配係数設定（請求額である事に注意）
            for (int i = 0; i < m_csSndECCashOUTCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csSndECCashOUTCnnct.m_dSendRatioData[i][0] = m_csSndECCashOUTCnnct.m_dRcvRatioData[i][0] / dSum;
            } 
        }
        /// <summary>
        /// 出費、支出：支払者
        /// </summary>
        protected virtual void CostingSend()
        {
           // 予め通知された購入額に応じて納入
            for (int i = 0; i < m_csSndECCashOUTCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csSndECCashOUTCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                // 次回発注
                csSndDt[0].m_dData[0] = m_csOcCashInf.m_OrdersPlaced * m_csSndECCashOUTCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[0] < 0) { csSndDt[0].m_dData[0] = 0; }
                // 支払い
                csSndDt[0].m_dData[1] = m_csOcCashInf.m_Payment * m_csSndECCashOUTCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[1] < 0) { csSndDt[0].m_dData[1] = 0; }
            }
        }

        /// <summary>
        /// 経費受け取り：受取人
        /// </summary>
        protected virtual void ExpenseReceive()
        {
            double dSum = 0;
            for (int i = 0; i < m_csRcvECCashINCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvECCashINCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    if(csCell[0].m_dData[0] < 0) { csCell[0].m_dData[0] = 0; }
                    // 受注
                    dSum += csCell[0].m_dData[0] + 1E-16;
                    // 要求の為、発注額を覚えておく
                    m_csRcvECCashINCnnct.m_dRcvRatioData[i][0] = csCell[0].m_dData[0] + 1E-16;

                    //m_csOcCashInf.m_OrdersPlaced += csCell[0].m_dData[0];
                    // 収入
                    if (csCell[0].m_dData[1] < 0) { csCell[0].m_dData[1] = 0; }
                    //m_csOcCashInf.m_Payment = csCell[0].m_dData[1];
                    //m_csOcCashInf.m_Income += csCell[0].m_dData[1];
                    //m_csOcCashInf.m_dNowUnitPlace = csCell[0].m_dData[1];
                    m_csOcCashInf.SellerReceivePayment(csCell[0].m_dData[0], csCell[0].m_dData[1]);
                }
            }
            //  分配係数設定（受注額である事に注意）
            for (int i = 0; i < m_csRcvECCashINCnnct.m_RcvInfNum; i++)
            {
                // 分配比計算
                m_csRcvECCashINCnnct.m_dSendRatioData[i][0] = m_csRcvECCashINCnnct.m_dRcvRatioData[i][0] / dSum;
            }
        }
        /// <summary>
        /// 成果送付：受取人
        /// </summary>   
        protected virtual void OutcomeSend()
        {
            for (int i = 0; i < m_csRcvECCashINCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csSndDt = m_csRcvECCashINCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                // 請求額
                csSndDt[0].m_dData[0] = m_csOcCashInf.m_Claimed * m_csRcvECCashINCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[0] < 0) { csSndDt[0].m_dData[0] = 0.0; }
                // 次回見積もり
                csSndDt[0].m_dData[1] = m_csOcCashInf.m_EstimatedCost * m_csRcvECCashINCnnct.m_dSendRatioData[i][0];
                if (csSndDt[0].m_dData[1] < 0) { csSndDt[0].m_dData[1] = 0.0; }
                // 作業価値係数
                csSndDt[0].m_dData[2] = m_csOcCashInf.m_ContributionRatioForProduct;
            }
        }

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

        protected virtual void SendDEBUG()
        {
            for (int i = 0; i < m_csDebugSendCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csDebugSendCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if(csCell == null) { continue; }
                csCell[0].m_dData[0] = m_csOcCashInf.m_Chash;
                csCell[0].m_dData[1] = m_csOcCashInf.m_NonMaterial_Val;
                csCell[0].m_dData[2] = m_csOcCashInf.m_OrdersPlaced;
                csCell[0].m_dData[3] = m_csOcCashInf.m_Payment;
                csCell[0].m_dData[4] = m_csOcCashInf.m_Claimed;
                csCell[0].m_dData[5] = m_csOcCashInf.m_EstimatedCost;
            }
        }

        /// <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)
        {
            McInitialInfo csInDt = csInitialData as McInitialInfo;
            if (csInDt != null)
            {   // 初期化情報有り
                double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);
  
                m_csOcCashInf.Clear();

                m_csOcCashInf.m_WorkTime = m_csOcCashInf.m_HmnActTimeSpan - m_csDltTime.TotalSec() +1;

                csInDt.GetInfo("m_Facility", ref m_csOcCashInf.m_Facility);
                csInDt.GetInfo("m_DepreciationRate", ref m_csOcCashInf.m_DepreciationRate);
                csInDt.GetInfo("m_CapitalStock", ref m_csOcCashInf.m_CapitalStock);
                csInDt.GetInfo("m_Chash", ref m_csOcCashInf.m_Chash);
                csInDt.GetInfo("m_Debt", ref m_csOcCashInf.m_CapitalStock);
                csInDt.GetInfo("m_DebtInterestRate", ref m_csOcCashInf.m_Chash);
                csInDt.GetInfo("m_Credit", ref m_csOcCashInf.m_CapitalStock);
                csInDt.GetInfo("m_CreditInterestRate", ref m_csOcCashInf.m_Chash);
                csInDt.GetInfo("m_dNextDealingChash", ref m_csOcCashInf.m_dNextDealingChash);
                csInDt.GetInfo("m_dNowUnitCost", ref m_csOcCashInf.m_dPrductUnitCost);
                csInDt.GetInfo("m_OrdersPlaced", ref m_csOcCashInf.m_OrdersPlaced);
                csInDt.GetInfo("m_EstimatedCost", ref m_csOcCashInf.m_EstimatedCost);

                //// CO2排出
                //m_csOcCashInf.m_HmnCO2Emission = m_csOcCashInf.m_HmnCO2EmissionDay * dT;
                //m_csOcCashInf.m_HmnReqO2 = (32.0 / 44.0) * m_csOcCashInf.m_HmnCO2EmissionDay * dT;
            }
            m_ActionFlg = false;
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>初期値の送信</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = SendInitData()</para>
        /// </example>
        /// <param name="lOnlySendDataNum">出力だけの情報数</param>
        /// <param name="csOnlySelDataCellData">出力だけの情報配列</param>
        /// <param name="lRcvSndDataNum">相互接続報数</param>
        /// <param name="csReceiveCellData">相互接続入力側情報配列</param>
        /// <param name="csSelDataCellData">相互接続出力側情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>派生クラス側で必ずオーバライドする必要がある</para>
        /// </remarks>
        protected override bool SendInitData(
                        long lOnlySendDataNum, ref McSendOnlyTranInfo[] csOnlySelDataCellData,
                        long lRcvSndDataNum, ref McRdvSndTranInfoPair[] csRcvSndCelDataCellData
                    )
        {
            m_ActionFlg = true;
            SendData();
            return true;
        }

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

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputDataList)</para>
        /// </example>
        /// <param name="lOnlyReceveDataNum">入力だけの情報数</param>
        /// <param name="csOnlyReceiveCellData">入力だけの情報配列</param>
        /// <param name="lOnlySendDataNum">出力だけの情報数</param>
        /// <param name="csOnlySelDataCellData">出力だけの情報配列</param>
        /// <param name="lRcvSndDataNum">相互接続報数</param>
        /// <param name="csReceiveCellData">相互接続入力側情報配列</param>
        /// <param name="csSelDataCellData">相互接続出力側情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>派生クラス側で必ずオーバライドする必要がある</para>
        /// </remarks>
        protected override long Calculate(
            long lOnlyReceveDataNum, ref McReceiveOnlyTranInfo[] csOnlyReceiveCellData,
            long lOnlySendDataNum, ref McSendOnlyTranInfo[] csOnlySelDataCellData,
            long lRcvSndDataNum, ref McRdvSndTranInfoPair[] csRcvSndCelDataCellData
            )
        {
            m_ActionFlg = false;
            // 活動周期で行動を行う
            m_csOcCashInf.m_WorkTime += m_csDltTime.TotalSec();
            if (m_csOcCashInf.m_WorkTime >= m_csOcCashInf.m_HmnActTimeSpan)
            {
                m_ActionFlg = true;
                m_csOcCashInf.m_WorkTime -= m_csOcCashInf.m_HmnActTimeSpan;
      
                // 人間行為
                HumanAction();
            }

            //double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);
            //// CO2排出 既に計算済みのため、変動がない場合には、再計算しない。
            //m_csOcCashInf.m_HmnCO2Emission = m_csOcCashInf.m_HmnCO2EmissionDay * dT;
            //m_csOcCashInf.m_HmnReqO2 = (32.0 / 44.0) * m_csOcCashInf.m_HmnCO2EmissionDay * dT;
            m_csOcCashInf.m_HmnRcvO2 -= m_csOcCashInf.m_HmnReqO2;
            return 0;
        }

        /// <summary>
        /// 人間の行為
        /// </summary>
        /// <returns></returns>
        protected abstract long HumanAction();


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

            /// <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 = base.SetProperty(csCellMdlPropertyInfo);

            // 使用しやすいようにキャストしておく
            m_csOcCashInf = (MzCashflowModelElementCalInfo)m_csCalInfo;
           // 14400
            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 演算ステップ時刻設定
                this.m_csDltTime = new HySTime(csPrptyInfo.GetStepTime());


                // 行動または納入の間隔
                SetHumanActionSpanTime(ref csPrptyInfo);
                // 活動によるCO2排出量
                SetHumanActionCO2Emission(ref csPrptyInfo);
                // 生産への直接寄与率
                csPrptyInfo.GetInfo("m_ContributionRatioForProduct", ref m_csOcCashInf.m_ContributionRatioForProduct);

            }

            return true;
        }

        /// <summary>
        /// 行動または納入の間隔
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        protected virtual void SetHumanActionSpanTime( ref McCellModelPropertyInfo csPrptyInfo)
        {
            double dDay = 0.0;
            csPrptyInfo.GetInfo("m_HmnActTimeSpan", ref dDay);
            m_csOcCashInf.m_HmnActTimeSpan = dDay * 24 * 3600;
        }
        /// <summary>
        /// CO2排出量
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        protected virtual void SetHumanActionCO2Emission(ref McCellModelPropertyInfo csPrptyInfo)
        {
            double dT = m_csDltTime.GetTime() / (3600.0 * 24.0);
            double dDD = 0.0;
            csPrptyInfo.GetInfo("m_HmnCO2EmissionDay", ref dDD);
            m_csOcCashInf.m_HmnCO2EmissionDay = dDD * 1E3; // * dT;

            // CO2排出
            m_csOcCashInf.m_HmnCO2Emission = m_csOcCashInf.m_HmnCO2EmissionDay * dT;
            m_csOcCashInf.m_HmnReqO2 = (32.0 / 44.0) * m_csOcCashInf.m_HmnCO2EmissionDay * dT;

        }
    }
}
