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

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;
using CommonMP.HYMCO.OptionImple.GAModelSampleLIB.GACtlTools;

namespace CommonMP.HYMCO.OptionImple.GAModelSampleLIB
{
    /// <summary><para>class outline:</para>
    /// <para>遺伝子情報を保持する染色体の実装</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.3][2010/10/01][新規作成]</para>
    /// </remarks>
    [Serializable]
    public class GAChromosomeSample : GAChromosomeIF, HySDataRoot, HySVersionManagement
    {
        /// <summary> KinematicWave河道計算処理演算要素数</summary>
        public long m_lBoxNum = 15;
        
        /// <summary>
        /// 遺伝情報：各KinematicWave河道計算処理で使用する粗度（KinematicWave河道計算処理演算要素数の配列）
        /// この情報が進化により　最適化される
        /// </summary>
        public double[] m_dRough = null;

        /// <summary>KinematicWave河道計算処理内のセル分割数 </summary>
        public long m_lCelDivNumber = 5;

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>GAChromosomeSample csGhromosome = new GAChromosomeSample( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>GAChromosomeSample 生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public GAChromosomeSample()
        {
            SetNowVersion();   //バージョン情報設定
        }
        
    
        /// <summary><para>method outline:</para>
        /// <para>KinematicWave河道計算処理内のセル分割数設定</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　SetCelDivNumber(lCelDivNum)</para>
        /// </example>
        /// <param name="lCelDivNum">モデル内のセル数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>KinematicWave河道計算処理内のセル分割数＝モデル固有の遺伝情報</para>
        /// </remarks>
        public virtual void SetCelDivNumber( long lCelDivNum)
        {
            m_lCelDivNumber = lCelDivNum;
        }

        /// <summary><para>method outline:</para>
        /// <para>KinematicWave河道計算処理演算要素数設定</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　SetBoxNum(lBxNum)</para>
        /// </example>
        /// <param name="lBxNum">KinematicWave河道計算処理演算要素数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>KinematicWave河道計算処理演算要素数＝モデル固有の遺伝情報</para>
        /// </remarks>
        public virtual void SetBoxNum( long lBxNum )
        {
            m_lBoxNum = lBxNum;
            m_dRough = new double[m_lBoxNum];
            for (long lLp = 0; lLp < m_lBoxNum; lLp++)
            {
                m_dRough[lLp] = 0.03+ 0.01*(1.0-2.0*GARoulette.m_csRnd.NextDouble());
            }
        }

        // 発生
        /// <summary><para>method outline:</para>
        /// <para>演算モデル固体クラス発生</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para> GACreatureIF csCreature = Genesis() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>演算モデル固体クラス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>自遺伝子内容から演算モデル固体を発生させる</para>
        /// </remarks>
        public virtual GACreatureIF Genesis()
        {
            GAKinematicWaveEvolutionModel csRtnObj = new GAKinematicWaveEvolutionModel();
            csRtnObj.SetCalInfo(new GAKinematicWaveEvolutionModelCalInfo());
            // 自遺伝子情報から、生成したオブジェクトのパラメーター等を設定する
            csRtnObj.GeneDecipher(this);

            return csRtnObj;
        }
       
        // 複製
        /// <summary><para>method outline:</para>
        /// <para>遺伝子情報複製</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para> GAChromosomeIF csChromosome = Copy() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>伝子情報を保持する染色体クラス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual GAChromosomeIF Copy()
        {
            GAChromosomeSample csRtnObj = new GAChromosomeSample();
            csRtnObj.DataCopy(this);
            return csRtnObj;
        }

        /// <summary><para>method outline:</para>
        /// <para>引数で与えられた情報を自分にコピーを行う</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para> DataCopy(OrgData) </para>
        /// </example>
        /// <param name="OrgData">コピー元情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual void DataCopy(GAChromosomeSample OrgData)
        {
            this.m_lBoxNum = OrgData.m_lBoxNum;
            this.m_dRough = new double[m_lBoxNum];
            for (long lLp = 0; lLp < m_lBoxNum; lLp++)
            {
                this.m_dRough[lLp] = OrgData.m_dRough[lLp];
            }
            this.m_lCelDivNumber = OrgData.m_lCelDivNumber;
        }

        // 突然変異
        /// <summary><para>method outline:</para>
        /// <para>遺伝子への突然変異発生</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = Mutation(dRatio)</para>
        /// </example>
        /// <param name="dRatio">変異率（０～１）</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool Mutation(double dRatio)
        {
            if (GARoulette.m_csRnd.NextDouble() < dRatio)
            {
                long lPos = (long)((double)m_lBoxNum * GARoulette.m_csRnd.NextDouble());
                if (lPos < 0) { lPos = 0; }
                if (lPos >= m_lBoxNum) { lPos = m_lBoxNum - 1; }
                m_dRough[lPos] += 0.01*(0.5 - GARoulette.m_csRnd.NextDouble());
                if (m_dRough[lPos] < 0.01) { m_dRough[lPos] = 0.01; }
                if (m_dRough[lPos] > 0.08) { m_dRough[lPos] = 0.08; }
            }
            return true;
        }

        // 交鎖
        /// <summary><para>method outline:</para>
        /// <para>遺伝子間の交鎖発生</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = CrossOver(csOther,dRatio)</para>
        /// </example>
        /// <param name="csOther">交鎖する相手方遺伝子</param>
        /// <param name="dRatio">交鎖発生率率（０～１）</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool CrossOver(ref GAChromosomeIF csOther, double dRatio)
        {
            if (GARoulette.m_csRnd.NextDouble() < dRatio)
            {
                GAChromosomeSample csOtherChr = csOther as GAChromosomeSample;
                long lPos = (long)((double)(m_lBoxNum-2) * GARoulette.m_csRnd.NextDouble())+1;
                if (lPos < 0) { lPos = 1; }
                if (lPos >= m_lBoxNum) { lPos = m_lBoxNum - 2; }
                double[] dRough = new double[m_lBoxNum];
                for (long lLp = lPos; lLp < m_lBoxNum; lLp++)
                {
                    dRough[lLp] = this.m_dRough[lLp];
                    this.m_dRough[lLp] = csOtherChr.m_dRough[lLp];
                    csOtherChr.m_dRough[lLp] = dRough[lLp];
                }
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>遺伝子情報のファイル書き出し</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>long lRtn = FileOut(csFileNameWithPath)</para>
        /// </example>
        /// <param name="csFileNameWithPath">ファイル名称</param>
        /// <returns>0 :正常 , -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long FileOut(String csFileNameWithPath)
        {
            long lRtn = 0;
            HySFile csFile = new HySFile(csFileNameWithPath);
            lRtn = csFile.Open(HySFile.OPEN_MODE.CREATE_NEW, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.NOT_MK_DIR);
            if (lRtn == 0)
            {
                if (csFile.DataWrite(this) == false)
                {
                    lRtn = -1;
                }
                csFile.Close();
            }
            return lRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>遺伝子情報のファイル読み込み</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>long lRtn = FileIn(csFileNameWithPath)</para>
        /// </example>
        /// <param name="csFileNameWithPath">ファイル名称</param>
        /// <returns>0 :正常 , -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long FileIn(String csFileNameWithPath)
        {
            long lRtn = 0;
            HySFile csFile = new HySFile(csFileNameWithPath);
            lRtn = csFile.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR);
            if (lRtn == 0)
            {
                GAChromosomeSample csRdDt = csFile.DataRead() as GAChromosomeSample;
                if (csRdDt != null)
                {
                    this.DataCopy(csRdDt);
                }
                else
                {
                    lRtn = -1;
                }
                csFile.Close();
            }
            return lRtn;
        }

        // ================================================
        //   バージョンアップ時の下位互換性を保つ為の処理
        // ================================================
        /// <summary>保存バージョン情報</summary>
        private string m_sDecodedVersion;
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sDecodedVersion = GetDecodedVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 保存バージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>メンバー変数に設定されているバージョン情報を返す</para>
        /// </remarks>
        public string GetDecodedVersion()
        {
            return m_sDecodedVersion;
        }
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sVersion = GetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 現在のバージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public string GetNowVersion()
        {
            return "1.00";
        }
        /// <summary><para>method outline:</para>
        /// <para>バージョン情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>現在のバージョン情報をメンバー変数に設定する</para>
        /// </remarks>
        public void SetNowVersion()
        {
            m_sDecodedVersion = GetNowVersion();
        }
        /// <summary><para>method outline:</para>
        /// <para>復元後の整合性確保処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> PostDeserialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>シリアライズされた旧バージョン情報を復元する際、過去の整合性をとる時に使用する
        /// バージョンによって変数等追加がない場合には、実装の必要がない
        /// </para>
        /// </remarks>
        public virtual void PostDeserialize()
        {
            if (GetDecodedVersion() != GetNowVersion())
            {
                //旧バージョンから順にバージョンを上げて行く
                switch (GetDecodedVersion())
                {
                    case "1.00":
                        break;
                }
                SetNowVersion();
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>逆シリアル化時追加処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> IDeserializationCallback.OnDeserialization(csObj)</para>
        /// </example>
        /// <param name="csObj">ダミー</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>予約処理</para>
        /// </remarks>
        void IDeserializationCallback.OnDeserialization(Object csObj)
        {
            PostDeserialize();
        }
    }
}
