using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
//using System.Reflection;
#if DEBUG
	using System.IO;
#endif

using SystemCommon;


namespace 顧客分析君
{
    public partial class _301計算 : Form
    {
        ////////////////////////////////////////////////////////////////////////
        // メンバ変数
        ////////////////////////////////////////////////////////////////////////
        #region メンバ変数

		//public enum enm計算条件Tab : int
		//{
		//    FM分析,
		//    RFM分析,
		//    顧客動向表
		//}
		private static class 計算条件Tab
		{
			public const string cstrFM分析 = "FM分析";
			public const string cstrRFM分析 = "RFM分析";
			public const string cstr顧客動向表 = "顧客動向表";
		}

        #endregion

        ////////////////////////////////////////////////////////////////////////
        // 公開 共通メソッド 
        ////////////////////////////////////////////////////////////////////////
        #region 公開 共通メソッド

        public _301計算()
        {
            InitializeComponent();

            Set表示項目();
        }

        #endregion


        ////////////////////////////////////////////////////////////////////////
        // 非公開 共通メソッド
        ////////////////////////////////////////////////////////////////////////
        #region 非公開 共通メソッド

        private bool IsValidateSUB(TextBox txtbx, string strInputName, string strTabName)
        {
            //必須入力欄
            if (txtbx.Text == "")
            {
                string errmsg = string.Format(Properties.Resources.MSG_W_AタブのBが入力されていません
					, strTabName, strInputName);
                MessageBox.Show(errmsg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtbx.Focus();
                return false;
            }

            long res;
            if (long.TryParse(txtbx.Text, out res) == false)
            {
                string errmsg = string.Format(Properties.Resources.MSG_W_AタブのBに_半角数値以外が入力されています
					, strTabName, strInputName);
                MessageBox.Show(errmsg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtbx.Focus();
                return false;
            }

            return true;
        }

        //　値範囲の整合性チェック
        private bool IsValidateSub値範囲の整合性(string strTab名, TextBox txtbFrom, TextBox txtbTo)
        {
            if (long.Parse(txtbFrom.Text) >= long.Parse(txtbTo.Text)) // 例：F5がF4と同じか、下回っていたらエラー
            {
                string strErrMsg = string.Format(Properties.Resources.MSG_W_AタブのBが_Cの値を超えていません, strTab名
                    , txtbTo.Name.Substring(3, 2), txtbFrom.Name.Substring(3, 2));
                MessageBox.Show(strErrMsg, Properties.Resources.MSG_TTL_入力エラー
					, MessageBoxButtons.OK, MessageBoxIcon.Warning);

                return false;
            }

            return true;
        }

        private bool IsValidateSub値範囲の整合性_計算対象期間(string strTab名, DateTime dtFrom, DateTime dtTo)
        {
            if (dtFrom > dtTo)
            {
                string strErrMsg = string.Format(Properties.Resources.MSG_W_Aタブの計算対象期間_終了日が_計算対象期間_開始日の値を超えていません
					, strTab名);
                MessageBox.Show(strErrMsg, Properties.Resources.MSG_TTL_入力エラー
					, MessageBoxButtons.OK, MessageBoxIcon.Warning);

                return false;
            }

            return true;
        }

        //入力値検証
        private bool IsValidate()
        {
#if 顧客分析君ZERO
#else
            //必須入力チェック
            if (IsValidateSUB(txtF3_FM, 計算条件Tab.cstrFM分析, txtF3_FM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtF2_FM, 計算条件Tab.cstrFM分析, txtF2_FM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtM3_FM, 計算条件Tab.cstrFM分析, txtM3_FM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtM2_FM, 計算条件Tab.cstrFM分析, txtM2_FM.Name.Substring(3, 2)) == false)
                return false;
#endif
            if (IsValidateSUB(txtR5_RFM, 計算条件Tab.cstrRFM分析, txtR5_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtR4_RFM, 計算条件Tab.cstrRFM分析, txtR4_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtR3_RFM, 計算条件Tab.cstrRFM分析, txtR3_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtR2_RFM, 計算条件Tab.cstrRFM分析, txtR2_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtF5_RFM, 計算条件Tab.cstrRFM分析, txtF5_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtF4_RFM, 計算条件Tab.cstrRFM分析, txtF4_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtF3_RFM, 計算条件Tab.cstrRFM分析, txtF3_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtF2_RFM, 計算条件Tab.cstrRFM分析, txtF2_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtM5_RFM, 計算条件Tab.cstrRFM分析, txtM5_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtM4_RFM, 計算条件Tab.cstrRFM分析, txtM4_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtM3_RFM, 計算条件Tab.cstrRFM分析, txtM3_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (IsValidateSUB(txtM2_RFM, 計算条件Tab.cstrRFM分析, txtM2_RFM.Name.Substring(3, 2)) == false)
                return false;

#if 顧客分析君ZERO
#else
            if (chkRFMの入力値を使う.Checked == false)
            {
                //if (IsValidateSUB(txtR5_動向表) == false) return false;
                //if (IsValidateSUB(txtR4_動向表) == false) return false;
                //if (IsValidateSUB(txtR3_動向表) == false) return false;
                //if (IsValidateSUB(txtR2_動向表) == false) return false;
                if (IsValidateSUB(txtF5_顧客動向表, 計算条件Tab.cstr顧客動向表, txtF5_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (IsValidateSUB(txtF4_顧客動向表, 計算条件Tab.cstr顧客動向表, txtF4_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (IsValidateSUB(txtF3_顧客動向表, 計算条件Tab.cstr顧客動向表, txtF3_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (IsValidateSUB(txtF2_顧客動向表, 計算条件Tab.cstr顧客動向表, txtF2_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (IsValidateSUB(txtM5_顧客動向表, 計算条件Tab.cstr顧客動向表, txtM5_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (IsValidateSUB(txtM4_顧客動向表, 計算条件Tab.cstr顧客動向表, txtM4_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (IsValidateSUB(txtM3_顧客動向表, 計算条件Tab.cstr顧客動向表, txtM3_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (IsValidateSUB(txtM2_顧客動向表, 計算条件Tab.cstr顧客動向表, txtM2_顧客動向表.Name.Substring(3, 2)) == false) 
                    return false;
            }

            //値チェック
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtF3_FM.Text, 計算条件Tab.cstrFM分析 + "」タブの「" + txtF3_FM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtF2_FM.Text, 計算条件Tab.cstrFM分析 + "」タブの「" + txtF2_FM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtM3_FM.Text, 計算条件Tab.cstrFM分析 + "」タブの「" + txtM3_FM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtM2_FM.Text, 計算条件Tab.cstrFM分析 + "」タブの「" + txtM2_FM.Name.Substring(3, 2)) == false)
                return false;
#endif
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtR5_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtR5_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtR4_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtR4_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtR3_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtR3_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtR2_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtR2_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtF5_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtF5_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtF4_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtF4_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtF3_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtF3_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtF2_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtF2_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtM5_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtM5_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtM4_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtM4_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtM3_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtM3_RFM.Name.Substring(3, 2)) == false)
                return false;
            if (C11ValidateOnForm.IsValidate符号無し数値型(txtM2_RFM.Text, 計算条件Tab.cstrRFM分析 + "」タブの「" + txtM2_RFM.Name.Substring(3, 2)) == false)
                return false;

#if 顧客分析君ZERO
#else
            if (chkRFMの入力値を使う.Checked == false)
            {
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtF5_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtF5_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtF4_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtF4_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtF3_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtF3_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtF2_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtF2_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtM5_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtM5_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtM4_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtM4_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtM3_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtM3_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
                if (C11ValidateOnForm.IsValidate符号無し数値型(txtM2_顧客動向表.Text, 計算条件Tab.cstr顧客動向表 + "」タブの「" + txtM2_顧客動向表.Name.Substring(3, 2)) == false)
                    return false;
            }

            //値範囲のチェック
            if (IsValidateSub値範囲の整合性_計算対象期間(計算条件Tab.cstrFM分析, dtp計算対象期間From.Value, dtp計算対象期間To.Value.AddDays(1).AddMilliseconds(-1)) == false)
                return false;
 
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrFM分析, txtF2_FM, txtF3_FM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrFM分析, txtM2_FM, txtM3_FM) == false)
                return false;
#endif
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtR5_RFM, txtR4_RFM) == false) //Rは逆転する
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtR4_RFM, txtR3_RFM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtR3_RFM, txtR2_RFM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtF4_RFM, txtF5_RFM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtF3_RFM, txtF4_RFM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtF2_RFM, txtF3_RFM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtM4_RFM, txtM5_RFM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtM3_RFM, txtM4_RFM) == false)
                return false;
            if (IsValidateSub値範囲の整合性(計算条件Tab.cstrRFM分析, txtM2_RFM, txtM3_RFM) == false)
                return false;

#if 顧客分析君ZERO
#else
            if (chkRFMの入力値を使う.Checked == false)
            {
                if (IsValidateSub値範囲の整合性(計算条件Tab.cstr顧客動向表, txtF4_顧客動向表, txtF5_顧客動向表) == false)
                    return false;
                if (IsValidateSub値範囲の整合性(計算条件Tab.cstr顧客動向表, txtF3_顧客動向表, txtF4_顧客動向表) == false)
                    return false;
                if (IsValidateSub値範囲の整合性(計算条件Tab.cstr顧客動向表, txtF2_顧客動向表, txtF3_顧客動向表) == false)
                    return false;
                if (IsValidateSub値範囲の整合性(計算条件Tab.cstr顧客動向表, txtM4_顧客動向表, txtM5_顧客動向表) == false)
                    return false;
                if (IsValidateSub値範囲の整合性(計算条件Tab.cstr顧客動向表, txtM3_顧客動向表, txtM4_顧客動向表) == false)
                    return false;
                if (IsValidateSub値範囲の整合性(計算条件Tab.cstr顧客動向表, txtM2_顧客動向表, txtM3_顧客動向表) == false)
                    return false;
            }
#endif

            return true;
        }


        private bool IsValidate計算元データ有無()
        {
            if ((int)d03販売履歴ta.Scalar販売履歴Cnt() < 1)
            {
                MessageBox.Show(Properties.Resources.MSG_W_販売履歴が登録されていません, this.Text
					, MessageBoxButtons.OK,MessageBoxIcon.Warning);
                return false;
            }

            if ((int)d10顧客ta.Scalar顧客Cnt() < 1)
            {
                MessageBox.Show(Properties.Resources.MSG_W_顧客が登録されていません, this.Text
					, MessageBoxButtons.OK,MessageBoxIcon.Warning);
                return false;
            }

            D03販売履歴.D03販売履歴DataTable tb = new D03販売履歴.D03販売履歴DataTable();
            d03販売履歴ta.FillBy最大累計購入金額超_顧客(tb, (long)C_最大値.販売金額);
            if (tb.Count > 0)
            {
                string str = string.Format("{0:#,0}", (long)C_最大値.販売金額);
                MessageBox.Show(string.Format(Properties.Resources.MSG_W_顧客ID_A_が最大購買金額_B円を超えている為_計算を行う事ができません
					, tb[0].顧客ID, str), this.Text, MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);

                return false;
            }

			return true;
        }

        private bool IsValidateFM分析固有()
        {
            //計算元データ有無チェック
            if ((int)d03販売履歴ta.Scalar販売履歴Cnt_期間指定(dtp計算対象期間From.Value
				, dtp計算対象期間To.Value.AddDays(1).AddMilliseconds(-1)) < 1)
            {
                MessageBox.Show(Properties.Resources.MSG_W_FM分析タブの計算対象期間に含まれる_販売履歴が登録されていません
					, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return false;
            }

            return true;
        }

        //計算条件を保存
        private void 計算条件保存()
        {
            d05RFM計算条件ta.Update(txtR5_RFM.Text, 1);
            d05RFM計算条件ta.Update(txtR4_RFM.Text, 2);
            d05RFM計算条件ta.Update(txtR3_RFM.Text, 3);
            d05RFM計算条件ta.Update(txtR2_RFM.Text, 4);
            d05RFM計算条件ta.Update(txtF5_RFM.Text, 5);
            d05RFM計算条件ta.Update(txtF4_RFM.Text, 6);
            d05RFM計算条件ta.Update(txtF3_RFM.Text, 7);
            d05RFM計算条件ta.Update(txtF2_RFM.Text, 8);
            d05RFM計算条件ta.Update(txtM5_RFM.Text, 9);
            d05RFM計算条件ta.Update(txtM4_RFM.Text, 10);
            d05RFM計算条件ta.Update(txtM3_RFM.Text, 11);
            d05RFM計算条件ta.Update(txtM2_RFM.Text, 12);

#if 顧客分析君ZERO
#else
            if (chkRFMの入力値を使う.Checked == true)
                d05RFM計算条件ta.Update("1", 13);
            else
                d05RFM計算条件ta.Update("2", 13);

            d05RFM計算条件ta.Update(txtF5_顧客動向表.Text, 18);
            d05RFM計算条件ta.Update(txtF4_顧客動向表.Text, 19);
            d05RFM計算条件ta.Update(txtF3_顧客動向表.Text, 20);
            d05RFM計算条件ta.Update(txtF2_顧客動向表.Text, 21);
            d05RFM計算条件ta.Update(txtM5_顧客動向表.Text, 22);
            d05RFM計算条件ta.Update(txtM4_顧客動向表.Text, 23);
            d05RFM計算条件ta.Update(txtM3_顧客動向表.Text, 24);
            d05RFM計算条件ta.Update(txtM2_顧客動向表.Text, 25);

            d05RFM計算条件ta.Update(txtF3_FM.Text, 26);
            d05RFM計算条件ta.Update(txtF2_FM.Text, 27);
            d05RFM計算条件ta.Update(txtM3_FM.Text, 28);
            d05RFM計算条件ta.Update(txtM2_FM.Text, 29);

            d05RFM計算条件ta.Update(dtp計算対象期間From.Text, 30);
            d05RFM計算条件ta.Update(dtp計算対象期間To.Text, 31);
#endif

            // 計算時間を保存
            d01属性ta.Update計算日時(DateTime.Now.ToString());
        }

        //FMを計算
        private void FMを計算(byte bt計算No, byte bt計算総数)
        {
            lbl計算中の処理詳細.Text = "FMランク毎の顧客数を計算中　（" + bt計算No.ToString() + "/" + bt計算総数 .ToString() + "）";
            lbl計算中の処理詳細.Refresh();

            D03販売履歴.D03対象期間内の顧客DataTable dt顧客 = new D03販売履歴.D03対象期間内の顧客DataTable();
            DateTime dt計算対象期間From = DateTime.Parse(dtp計算対象期間From.Value.Year + "/" 
				+ dtp計算対象期間From.Value.Month + "/" + dtp計算対象期間From.Value.Day + " 00:00:00");
            DateTime dt計算対象期間To = DateTime.Parse(dtp計算対象期間To.Value.Year + "/" 
				+ dtp計算対象期間To.Value.Month + "/" + dtp計算対象期間To.Value.Day + " 23:59:59");
            d03対象期間内の顧客ta.Fill(dt顧客, dt計算対象期間From, dt計算対象期間To);

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = dt顧客.Count;

            // 過去の計算データを全て削除
            d15FMta.DeleteALL();

            int i月数 = C02業務共通処理.Get計算対象月数(dt計算対象期間From, dt計算対象期間To);
            DateTime dt最小販売日時 = C02業務共通処理.Get最小販売日時(dt計算対象期間From, dt計算対象期間To);
            dt最小販売日時 = DateTime.Parse(dt最小販売日時.Year + "/" + dt最小販売日時.Month + "/" + dt最小販売日時.Day);

            DateTime dt当月 = DateTime.Parse(dt計算対象期間From.Year + "/" + dt計算対象期間From.Month + "/1");
            for (int i月 = 0; i月 <= i月数; i月++)
            {
                //DateTime dt翌月 = DateTime.Parse(dt当月.Year + "/" + dt当月.Month + "/1").AddMonths(1).AddMilliseconds(-1);

                //顧客毎にFMレベルを計算し登録
                byte btF, btM;
                for (int iRow = 0; iRow < dt顧客.Count; iRow++)
                {
                    // F
                    int int購買回数 = (int)d03販売履歴ta.Scalar購買回数_FM(dt顧客[iRow].顧客No, dt計算対象期間From,
                        dt計算対象期間To, dt当月.AddMonths(1).AddMilliseconds(-1));

                    if (int購買回数 < 1)
                    {
                        pgs計算.PerformStep();
                        continue;
                    }
                    else if (int購買回数 >= Decimal.Parse(txtF3_FM.Text))
                        btF = 3;
                    else if (int購買回数 >= Decimal.Parse(txtF2_FM.Text))
                        btF = 2;
                    else
                        btF = 1;

                    // M
                    Nullable<long> Dec購買総金額 = (long)d03販売履歴ta.Scalar購買金額SUM_FM(dt顧客[iRow].顧客No,
                        dt計算対象期間From, dt計算対象期間To, dt当月.AddMonths(1).AddMilliseconds(-1));

                    if (Dec購買総金額 >= long.Parse(txtM3_FM.Text))
                        btM = 3;
                    else if (Dec購買総金額 >= long.Parse(txtM2_FM.Text))
                        btM = 2;
                    else
                        btM = 1;

                    d15FMta.Insert(DateTime.Parse(dt当月.Year + "/" + dt当月.Month + "/1"), dt顧客[iRow].顧客No, btF, btM);

                    pgs計算.PerformStep();
                }

                dt当月 = dt当月.AddMonths(1);
                dt当月 = DateTime.Parse(dt当月.Year + "/" + dt当月.Month + "/1");
            }
        }

        //RFMを計算
        private void RFMを計算(byte bt計算No, byte bt計算総数)
        {
            lbl計算中の処理詳細.Text = "RFMランク毎の顧客数を計算中　（" + bt計算No.ToString() + "/" + bt計算総数.ToString() + "）";
            lbl計算中の処理詳細.Refresh();
            //grp計算処理の進行状況.Refresh();

            D10顧客.D10顧客DataTable dt顧客 = new D10顧客.D10顧客DataTable();
            d10顧客ta.Fill(dt顧客);

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = dt顧客.Count;

            // 過去の計算データを全て削除
            d05RFMta.DeleteALL();

            //顧客毎にRFMレベルを計算し登録
            byte btR, btF, btM;
            for (int iRow = 0; iRow < dt顧客.Count; iRow++) 
            {
                Nullable<DateTime> dt最新購買日;

                // nullの場合は購買履歴が無いので飛ばす。
                if (d03販売履歴ta.Scalar最新購買日(dt顧客[iRow].顧客No) == null)
                {
                    pgs計算.PerformStep();
                    continue;
                }
                else
                    dt最新購買日 = (DateTime)d03販売履歴ta.Scalar最新購買日(dt顧客[iRow].顧客No);

                // R
                TimeSpan ts最新購買日と今日との差 = (TimeSpan)(DateTime.Today - dt最新購買日);
                if (ts最新購買日と今日との差.TotalDays <= double.Parse(txtR5_RFM.Text))
                    btR = 5;
                else if (ts最新購買日と今日との差.TotalDays <= double.Parse(txtR4_RFM.Text))
                    btR = 4;
                else if (ts最新購買日と今日との差.TotalDays <= double.Parse(txtR3_RFM.Text))
                    btR = 3;
                else if (ts最新購買日と今日との差.TotalDays <= double.Parse(txtR2_RFM.Text))
                    btR = 2;
                else
                    btR = 1;

                // F
                Nullable<int> int購買回数 = (int)d03販売履歴ta.Scalar購買回数(dt顧客[iRow].顧客No);
                if (int購買回数 >= Decimal.Parse(txtF5_RFM.Text))
                    btF = 5;
                else if (int購買回数 >= Decimal.Parse(txtF4_RFM.Text))
                    btF = 4;
                else if (int購買回数 >= Decimal.Parse(txtF3_RFM.Text))
                    btF = 3;
                else if (int購買回数 >= Decimal.Parse(txtF2_RFM.Text))
                    btF = 2;
                else
                    btF = 1;

                // M
                Nullable<long> Dec購買総金額 = (long)d03販売履歴ta.Scalar購買金額SUM(dt顧客[iRow].顧客No);
                if (Dec購買総金額 >= long.Parse(txtM5_RFM.Text))
                    btM = 5;
                else if (Dec購買総金額 >= long.Parse(txtM4_RFM.Text))
                    btM = 4;
                else if (Dec購買総金額 >= long.Parse(txtM3_RFM.Text))
                    btM = 3;
                else if (Dec購買総金額 >= long.Parse(txtM2_RFM.Text))
                    btM = 2;
                else
                    btM = 1;

                d05RFMta.Insert(dt顧客[iRow].顧客No, btR, btF, btM);

                pgs計算.PerformStep();
                //grp計算処理の進行状況.Refresh();
            }
        }

        private void 顧客動向表を計算(byte bt計算No, byte bt計算総数)
        {
            lbl計算中の処理詳細.Text = "顧客動向表を計算中　（" + bt計算No.ToString() + "/" + bt計算総数.ToString() + "）";
            //grp計算処理の進行状況.Refresh();
            lbl計算中の処理詳細.Refresh();

            //D05計算.D05販売期間DataTable dt = new D05計算.D05販売期間DataTable();
            //d05販売期間ta.Fill(dt);

            //// 計算対象月数を計算
            //bool b未満 = true;
            //int int月数 = 0;
            //int int年月カウント用 = 0;
            //int int終了年月 = int.Parse(dt[0].販売日時MAX.Year.ToString() + dt[0].販売日時MAX.Month.ToString("00"));
            //do
            //{
            //    int年月カウント用 = int.Parse(dt[0].販売日時MIN.AddMonths(int月数).Year.ToString()
            //        + dt[0].販売日時MIN.AddMonths(int月数).Month.ToString("00"));

            //    if (int年月カウント用 < int終了年月)
            //        int月数++;
            //    else
            //        b未満 = false;
            //}
            //while (b未満 == true);
            int i月数 = C02業務共通処理.Get計算対象月数(null, null);

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = (i月数) * 2 * 5;    // 2：種別　5：ランク

            // 過去の計算データを全て削除
            d05顧客動向表ta.DeleteALL();
            d05顧客動向表_顧客ta.DeleteALL();

            long lngF5;
            long lngF4;
            long lngF3;
            long lngF2;
            long lngM5;
            long lngM4;
            long lngM3;
            long lngM2;

            if (chkRFMの入力値を使う.Checked == true)
            {
                lngF5 = long.Parse(txtF5_RFM.Text);
                lngF4 = long.Parse(txtF4_RFM.Text);
                lngF3 = long.Parse(txtF3_RFM.Text);
                lngF2 = long.Parse(txtF2_RFM.Text);
                lngM5 = long.Parse(txtM5_RFM.Text);
                lngM4 = long.Parse(txtM4_RFM.Text);
                lngM3 = long.Parse(txtM3_RFM.Text);
                lngM2 = long.Parse(txtM2_RFM.Text);
            }
            else
            {
                lngF5 = long.Parse(txtF5_顧客動向表.Text);
                lngF4 = long.Parse(txtF4_顧客動向表.Text);
                lngF3 = long.Parse(txtF3_顧客動向表.Text);
                lngF2 = long.Parse(txtF2_顧客動向表.Text);
                lngM5 = long.Parse(txtM5_顧客動向表.Text);
                lngM4 = long.Parse(txtM4_顧客動向表.Text);
                lngM3 = long.Parse(txtM3_顧客動向表.Text);
                lngM2 = long.Parse(txtM2_顧客動向表.Text);
            }


            D05計算.D05販売期間DataTable dt = new D05計算.D05販売期間DataTable();
            d05販売期間ta.Fill(dt, null, null);
            //DateTime dt基準 = dt[0].販売日時MIN;
            DateTime dt基準 = C02業務共通処理.Get最小販売日時(null, null);
            DateTime dtFrom;
            DateTime dtTo;

            D05計算.D05動向表_顧客リストDataTable dt動向表_顧客リスト = new D05計算.D05動向表_顧客リストDataTable();
            int int動向No = 1;
            for (int i月 = 0; i月 <= i月数; i月++)
            {
                dtFrom = DateTime.Parse(dt基準.Year + "/" + dt基準.Month + "/1");
                dtTo = dtFrom.AddMonths(1).AddMilliseconds(-1);

                for (byte btRFM種別 = 2; btRFM種別 <= 3; btRFM種別++)
                {
                    int intYear = 0;
                    int lngMonth = 0;
                    for (byte btRFMランク = 1; btRFMランク <= 5; btRFMランク++)
                    {

                        //// RFM種別毎に抽出条件を変えて、顧客を検索する。
                        //if (btRFM種別 == 1)
                        //{
                        //    // 最新購買日
                        //    if (btRFMランク == 5)
                        //        d05動向表_顧客リストta.FillBy販売日(dt動向表_顧客リスト,
                        //                                            null, null, null,
                        //                                            int.Parse(txtR5_動向表.Text), int.Parse(txtR5_動向表.Text), int.Parse(txtR5_動向表.Text));
                        //    else if (btRFMランク == 4)
                        //        d05動向表_顧客リストta.FillBy販売日(dt動向表_顧客リスト,
                        //                                            int.Parse(txtR5_動向表.Text), int.Parse(txtR5_動向表.Text), int.Parse(txtR5_動向表.Text),
                        //                                            int.Parse(txtR4_動向表.Text), int.Parse(txtR4_動向表.Text), int.Parse(txtR4_動向表.Text));
                        //    else if (btRFMランク == 3)
                        //        d05動向表_顧客リストta.FillBy販売日(dt動向表_顧客リスト,
                        //                                            int.Parse(txtR4_動向表.Text), int.Parse(txtR4_動向表.Text), int.Parse(txtR4_動向表.Text),
                        //                                            int.Parse(txtR3_動向表.Text), int.Parse(txtR3_動向表.Text), int.Parse(txtR3_動向表.Text));
                        //    else if (btRFMランク == 2)
                        //        d05動向表_顧客リストta.FillBy販売日(dt動向表_顧客リスト,
                        //                                            int.Parse(txtR3_動向表.Text), int.Parse(txtR3_動向表.Text), int.Parse(txtR3_動向表.Text),
                        //                                            int.Parse(txtR2_動向表.Text), int.Parse(txtR2_動向表.Text), int.Parse(txtR2_動向表.Text));
                        //    else
                        //        d05動向表_顧客リストta.FillBy販売日(dt動向表_顧客リスト,
                        //                                            int.Parse(txtR2_動向表.Text), int.Parse(txtR2_動向表.Text), int.Parse(txtR2_動向表.Text),
                        //                                            null, null, null);
                        //}
                        //else if (btRFM種別 == 2)
                        if (btRFM種別 == 2)
                        {
                            // 累計購買回数
                            if (btRFMランク == 5)
                                d05動向表_顧客リストta.FillBy購買回数(dt動向表_顧客リスト,
                                                                      null, lngF5,
                                                                      dtFrom, dtTo);
                            else if (btRFMランク == 4)
                                d05動向表_顧客リストta.FillBy購買回数(dt動向表_顧客リスト,
                                                                      lngF5, lngF4,
                                                                      dtFrom, dtTo);
                            else if (btRFMランク == 3)
                                d05動向表_顧客リストta.FillBy購買回数(dt動向表_顧客リスト,
                                                                      lngF4, lngF3,
                                                                      dtFrom, dtTo);
                            else if (btRFMランク == 2)
                                d05動向表_顧客リストta.FillBy購買回数(dt動向表_顧客リスト,
                                                                      lngF3, lngF2,
                                                                      dtFrom, dtTo);
                            else
                                d05動向表_顧客リストta.FillBy購買回数(dt動向表_顧客リスト,
                                                                      lngF2, null,
                                                                      dtFrom, dtTo);
                        }
                        else
                        {
                            // 累計購買金額
                            if (btRFMランク == 5)
                                d05動向表_顧客リストta.FillBy販売金額(dt動向表_顧客リスト,
                                                                      null, lngM5,
                                                                      dtFrom, dtTo);
                            else if (btRFMランク == 4)
                                d05動向表_顧客リストta.FillBy販売金額(dt動向表_顧客リスト,
                                                                      lngM5, lngM4,
                                                                      dtFrom, dtTo);
                            else if (btRFMランク == 3)
                                d05動向表_顧客リストta.FillBy販売金額(dt動向表_顧客リスト,
                                                                      lngM4, lngM3,
                                                                      dtFrom, dtTo);
                            else if (btRFMランク == 2)
                                d05動向表_顧客リストta.FillBy販売金額(dt動向表_顧客リスト,
                                                                      lngM3, lngM2,
                                                                      dtFrom, dtTo);
                            else
                                d05動向表_顧客リストta.FillBy販売金額(dt動向表_顧客リスト,
                                                                      lngM2, null,
                                                                      dtFrom, dtTo);
                        }

                        //d05動向表_顧客リストta.FillBy期間(dt動向表_顧客リスト, dtFrom, dtTo);

                        //byte btColor_R = 0;
                        //byte btColor_G = 0;
                        //byte btColor_B = 0;
                        //顧客動向表のRGBを計算(btRFM種別, btRFMランク, ref btColor_R, ref btColor_G, ref btColor_B);

                        // C07顧客動向表_顧客　登録
                        for (int intRow = 0; intRow < dt動向表_顧客リスト.Count; intRow++)
                            d05顧客動向表_顧客ta.Insert(int動向No, dt動向表_顧客リスト[intRow].顧客No);

                        intYear = dt[0].販売日時MIN.AddMonths(i月).Year;
                        lngMonth = dt[0].販売日時MIN.AddMonths(i月).Month;

                        // C06顧客動向表　登録
                        d05顧客動向表ta.Insert(int動向No,
                                               dt[0].販売日時MIN.AddMonths(i月).Year,
                                               dt[0].販売日時MIN.AddMonths(i月).Month,
                                               btRFM種別,
                                               btRFMランク,
                                               dt動向表_顧客リスト.Count,
                                               0, 0, 0);

                        int動向No++;

                        pgs計算.PerformStep();
                        //grp計算処理の進行状況.Refresh();
                    }

                    顧客動向表のRGBを計算(intYear, lngMonth, btRFM種別);
                }

                dt基準 = dt基準.AddMonths(1);
            }

            //顧客動向表のRGBを計算(int販売開始年, int販売開始月, int月数);

        }

        private void 顧客動向表のRGBを計算(int intYear, int lngMonth, byte btRFM種別)
        {
            byte btR = 255;
            byte btG = 255;
            byte btB = 255;

            D05計算.D05顧客動向表DataTable dt顧客動向表 = new D05計算.D05顧客動向表DataTable();
            d05顧客動向表ta.FillBy年月RFM種別(dt顧客動向表, (short)intYear, (byte)lngMonth, btRFM種別);

            int int１つ前の顧客数 = 0;
            int i色基準値 = 0;
            for (int iRow = 0; iRow < dt顧客動向表.Count; iRow++)
            {
                if (dt顧客動向表[iRow].顧客数 == 0)
                    i色基準値 = 0;  // 顧客数が0なら白色にする。
                else
                { 
                    if (dt顧客動向表[iRow].顧客数 != int１つ前の顧客数)
                        i色基準値++;
                    //else if (i色基準値 == 0)
                    //    i色基準値++;
                }
                //else
                //    i色基準値 = iRow - 1;   
                // １つ前の顧客数と一致していたら、色を同じにする。

                if (btRFM種別 == 2)
                {
                    btR = (byte)(255 - ((i色基準値 * 50)));
                    btG = (byte)(255 - ((i色基準値 * 20)));
                    btB = (byte)(255 - ((i色基準値 * 40)));
                }
                else
                {
                    btR = (byte)(255 - ((i色基準値 * 40)));
                    btG = (byte)(255 - ((i色基準値 * 40)));
                    btB = (byte)(255 - ((i色基準値 * 10)));
                }

                d05顧客動向表ta.UpdateRGB(btR, btG, btB, dt顧客動向表[iRow].動向No);
                int１つ前の顧客数 = dt顧客動向表[iRow].顧客数;
            }
        }

        private void 商品の相関性を計算(byte bt計算No, byte bt計算総数)
        {
            lbl計算中の処理詳細.Text = "商品の相関性を計算中　（" + bt計算No.ToString() + "/" + bt計算総数.ToString() + "）";
            //grp計算処理の進行状況.Refresh();
            lbl計算中の処理詳細.Refresh();
            
            // REPLACE s_ 
		    // (u_, g_, c, cd, ud) 
		    // SELECT 
		    //     u_ 
		    // ,   g_ 
		    // ,   count(*) + COALESCE(T1.c, 0) AS c 
		    // ,   COALESCE(T1.cd, NOW()) 
		    // ,   NOW() 
		    // FROM d T0 
		    // LEFT JOIN s_ T1 USING(u_, g_) 
		    // WHERE T0.g_ = ? 
		    // GROUP BY u_, g_ 

            // INSERT INTO s 
            // SELECT 
            //     T1.u 
            // ,   T2.g 
            // ,   LEAST(T0.c, ?) 
            // FROM   s_           T0 
            //   JOIN u_ T1 USING(u_) 
            //   JOIN g_ T2 USING(g_) 
            // WHERE T2.dlf = 0 
            //   AND T2.g   = ? 


			// 過去の計算データを全て削除
			//d05購買回数ta.DeleteALL();
			D05計算.D05購買回数DataTable dt購買回数 = new D05計算.D05購買回数DataTable();
			d05購買回数ta.FillByDistinct顧客No(dt購買回数);
			for (int i購買回数Cnt = 0; i購買回数Cnt < dt購買回数.Count; i購買回数Cnt++)
			{
				d05購買回数ta.Delete顧客別(dt購買回数[i購買回数Cnt].顧客No);
			}

            D05計算.D05購買数DataTable dt購買数 = new D05計算.D05購買数DataTable();
            d05購買数ta.Fill(dt購買数);

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = dt購買数.Count;

            for (int i購買数Cnt = 0; i購買数Cnt < dt購買数.Count; i購買数Cnt++)
            {
                d05購買回数ta.Insert(dt購買数[i購買数Cnt].顧客No, dt購買数[i購買数Cnt].商品No, dt購買数[i購買数Cnt].CNT);

                pgs計算.PerformStep();
                //grp計算処理の進行状況.Refresh();
            }

            // INSERT INTO sw 
            // SELECT 
            //    T1.g                        AS g1 
            // ,  T2.g                        AS g2 
            // ,  SUM( T1.c * T2.c ) AS ip 
            // ,  SUM( T2.c * T2.c ) AS vv 
            // FROM   s T1 
            //   JOIN s T2 USING(u) 
            // WHERE T1.g = ? 
            // GROUP BY T1.g, T2.g 
            // ORDER BY COUNT(u) DESC 
            // LIMIT ? 


            //D05計算.D05購買回数の内積DataTable dt購買回数の内積 = new D05計算.D05購買回数の内積DataTable();
            //d05購買回数の内積ta.FillBy購買回数の内積を抽出(dt購買回数の内積);

            //pgs計算.Minimum = 1;
            //pgs計算.Step = 1;
            //pgs計算.Maximum = dt購買回数の内積.Count;

            //// 過去の計算データを全て削除
            //d05購買回数の内積ta.DeleteALL();

            //// C09購買回数の内積　を更新
            //for (int i購買回数の内積Cnt = 0; i購買回数の内積Cnt < dt購買回数の内積.Count; i購買回数の内積Cnt++)
            //{
            //    d05購買回数の内積ta.Insert(dt購買回数の内積[i購買回数の内積Cnt].計算元商品No,
            //                               dt購買回数の内積[i購買回数の内積Cnt].計算先商品No,
            //                               dt購買回数の内積[i購買回数の内積Cnt].購買回数の内積,
            //                               dt購買回数の内積[i購買回数の内積Cnt].内積の絶対値);

            //    pgs計算.PerformStep();
            //    //grp計算処理の進行状況.Refresh();
            //}


            D03販売履歴.D03商品DataTable dt商品 = new D03販売履歴.D03商品DataTable();
            d03商品ta.Fill(dt商品);

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = dt商品.Count;

			// 過去の計算データを全て削除
			//d05購買回数の内積ta.DeleteALL();
			D05計算.D05購買回数の内積DataTable dt購買回数の内積 = new D05計算.D05購買回数の内積DataTable();
			d05購買回数の内積ta.FillByDistinct計算元商品No(dt購買回数の内積);
			for (int i購買回数の内積Cnt = 0; i購買回数の内積Cnt < dt購買回数の内積.Count; i購買回数の内積Cnt++)
			{
				d05購買回数の内積ta.Delete計算元商品No別(dt購買回数の内積[i購買回数の内積Cnt].計算元商品No);
			}

            //D05計算.D05購買回数の内積DataTable dt購買回数の内積 = new D05計算.D05購買回数の内積DataTable();
            for (int i商品Cnt = 0; i商品Cnt < dt商品.Count; i商品Cnt++)
            {
                d05購買回数の内積ta.FillBy購買回数の内積を商品毎に抽出(dt購買回数の内積, dt商品[i商品Cnt].商品No);

                // C09購買回数の内積　を更新
                bool bFirst = true;
                float f内積の絶対値 = 0;
                for (int i購買回数の内積Cnt = 0; i購買回数の内積Cnt < dt購買回数の内積.Count; i購買回数の内積Cnt++)
                {
                    if (bFirst == true)
                    {
                        f内積の絶対値 = dt購買回数の内積[i購買回数の内積Cnt].内積の絶対値;
                        bFirst = false;
                    }

                    d05購買回数の内積ta.Insert(dt購買回数の内積[i購買回数の内積Cnt].計算元商品No,
                                               dt購買回数の内積[i購買回数の内積Cnt].計算先商品No,
                                               dt購買回数の内積[i購買回数の内積Cnt].購買回数の内積,
                                               f内積の絶対値);
                }

                pgs計算.PerformStep();
                //grp計算処理の進行状況.Refresh();
            }


            // INSERT INTO r 
            // SELECT 
            //     T0.g1           AS sbj_car_cd 
            // ,   T0.g2           AS obj_car_cd 
            // ,   @a := @a + 1                            AS r 
            // ,   1.0 * T0.ip / SQRT(1.0 * T3.vv * T0.vv) AS aff 
            // FROM    sw           T0 
            //   JOIN  sw           T3 
            //     ON  T0.g1 = T3.g1 
            //     AND T0.g1 = T3.g2 
            // WHERE T0.g1 = ? 
            //   AND T0.g1 <> T0.g2 
            // ORDER BY aff DESC, T0.g2 ASC 
            // LIMIT ? OFFSET 0 

            d05購買回数の内積ta.Fill(dt購買回数の内積);

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = dt購買回数の内積.Count;

            // 過去の計算データを全て削除
			//d05商品間の類似度ta.DeleteALL();
			D05計算.D05商品間の類似度DataTable dt商品間の類似度 = new D05計算.D05商品間の類似度DataTable();
			d05商品間の類似度ta.FillByDistinct計算元商品No(dt商品間の類似度);
			for (int i商品間の類似度Cnt = 0; i商品間の類似度Cnt < dt商品間の類似度.Count; i商品間の類似度Cnt++)
			{
				d05商品間の類似度ta.Delete商品別(dt商品間の類似度[i商品間の類似度Cnt].計算元商品No);
			}

            // C10商品間の類似度　を更新
            for (int i購買回数の内積Cnt = 0; i購買回数の内積Cnt < dt購買回数の内積.Count; i購買回数の内積Cnt++)
            {
                d05商品間の類似度ta.Insert(dt購買回数の内積[i購買回数の内積Cnt].計算元商品No,
                                           dt購買回数の内積[i購買回数の内積Cnt].計算先商品No,
                                           (float)(1.0 * dt購買回数の内積[i購買回数の内積Cnt].購買回数の内積 /
                                           Math.Sqrt(1.0 * dt購買回数の内積[i購買回数の内積Cnt].内積の絶対値 
                                           * dt購買回数の内積[i購買回数の内積Cnt].内積の絶対値)));

                pgs計算.PerformStep();
                //grp計算処理の進行状況.Refresh();
            }
        }

        private void お勧め商品_顧客毎を計算(byte bt計算No, byte bt計算総数)
        {
            lbl計算中の処理詳細.Text = "顧客毎のお勧め商品を計算中　（" + bt計算No.ToString() + "/" + bt計算総数.ToString() + "）";
            //grp計算処理の進行状況.Refresh();
            lbl計算中の処理詳細.Refresh();

            // C08購買回数 を更新
            D10顧客.D10顧客DataTable dt顧客 = new D10顧客.D10顧客DataTable();
            d10顧客ta.Fill(dt顧客);

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = dt顧客.Count;

			// 過去の計算データを全て削除
			//d05お勧め商品_顧客毎ta.DeleteALL();
			D05計算.D05お勧め商品_顧客毎DataTable dtお勧め商品_顧客毎 = new D05計算.D05お勧め商品_顧客毎DataTable();
			d05お勧め商品_顧客毎ta.FillByDistinct顧客No(dtお勧め商品_顧客毎);
			for (int iお勧め商品_顧客毎Cnt = 0; iお勧め商品_顧客毎Cnt < dtお勧め商品_顧客毎.Count; iお勧め商品_顧客毎Cnt++)
			{
				d05お勧め商品_顧客毎ta.Delete顧客別(dtお勧め商品_顧客毎[iお勧め商品_顧客毎Cnt].顧客No);
			}

            // C03お勧め商品_顧客毎　を更新
            for (int i顧客Cnt = 0; i顧客Cnt < dt顧客.Count; i顧客Cnt++)
            {
                D05計算.D05お勧め商品DataTable dtお勧め商品 = new D05計算.D05お勧め商品DataTable();
                d05お勧め商品ta.FillByお勧め商品_顧客毎(dtお勧め商品, dt顧客[i顧客Cnt].顧客No);

                for (int iお勧め商品Cnt = 0; iお勧め商品Cnt < dtお勧め商品.Count; iお勧め商品Cnt++)
                    d05お勧め商品_顧客毎ta.Insert(dt顧客[i顧客Cnt].顧客No, dtお勧め商品[iお勧め商品Cnt].計算先商品No, 
                        dtお勧め商品[iお勧め商品Cnt].類似度);

                pgs計算.PerformStep();
                //grp計算処理の進行状況.Refresh();
            }
        }

        private void お勧め商品_RFMを計算(byte bt計算No, byte bt計算総数)
        {
            lbl計算中の処理詳細.Text = "RFMランク毎のお勧め商品を計算中　（" + bt計算No.ToString() + "/" + bt計算総数.ToString() + "）";
            //grp計算処理の進行状況.Refresh();
            lbl計算中の処理詳細.Refresh();

            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = 125;

            // 過去の計算データを全て削除
            d05お勧め商品_RFMta.DeleteALL();

			D05計算.D05お勧め商品DataTable dtお勧め商品 = new D05計算.D05お勧め商品DataTable();
			D05計算.D05お勧め商品DataTable dtお勧め商品_対象商品 = new D05計算.D05お勧め商品DataTable();

			// C04お勧め商品_RFM　を更新
            for (byte iR = 1; iR <= 5; iR++)
            {
                for (byte iF = 1; iF <= 5; iF++)
                {
                    for (byte iM = 1; iM <= 5; iM++)
                    {
						d05お勧め商品ta.DeleteC12TMP商品間の類似度();

						/*

						//d05お勧め商品ta.InsertC12TMP商品間の類似度(iR, iF, iM);
						d05お勧め商品ta.InsertC12TMP商品間の類似度(iR, iF, iM);

						d05お勧め商品ta.FillByお勧め商品_RFM(dtお勧め商品, iR, iF, iM);
						for (int iRow = 0; iRow < dtお勧め商品.Count; iRow++)
							d05お勧め商品_RFMta.Insert(iR, iF, iM, dtお勧め商品[iRow].計算先商品No, iRow + 1,
								dtお勧め商品[iRow].類似度);
						*/
						/*
						*/
						d05お勧め商品ta.FillByお勧め商品_RFM_対象商品取得(dtお勧め商品_対象商品, iR, iF, iM);
						for (int i対象商品Cnt = 0; i対象商品Cnt < dtお勧め商品_対象商品.Count; i対象商品Cnt++)
						{
							d05お勧め商品ta.InsertC12TMP商品間の類似度(dtお勧め商品_対象商品[i対象商品Cnt].計算先商品No
								, dtお勧め商品_対象商品[i対象商品Cnt].類似度);

							/*
							d05お勧め商品ta.FillByお勧め商品_RFM_商品別(dtお勧め商品, iR, iF, iM, dtお勧め商品_対象商品[i対象商品Cnt].計算先商品No);

							for (int iRow = 0; iRow < dtお勧め商品.Count; iRow++)
								d05お勧め商品_RFMta.Insert(iR, iF, iM, dtお勧め商品[iRow].計算先商品No, iRow + 1,
									dtお勧め商品[iRow].類似度);
							 */
						}

						/*
						*/
						d05お勧め商品ta.FillByお勧め商品_RFM(dtお勧め商品);
						for (int iRow = 0; iRow < dtお勧め商品.Count; iRow++)
							d05お勧め商品_RFMta.Insert(iR, iF, iM, dtお勧め商品[iRow].計算先商品No, iRow + 1,
								dtお勧め商品[iRow].類似度);

						pgs計算.PerformStep();
                        //grp計算処理の進行状況.Refresh();
                    }
                }
            }
        }

        private void 売れ筋商品を計算(byte bt計算No, byte bt計算総数)
        {
            lbl計算中の処理詳細.Text = "RFMランク毎の売れ筋商品を計算中　（" + bt計算No.ToString() + "/" + bt計算総数.ToString() + "）";
            //grp計算処理の進行状況.Refresh();
            lbl計算中の処理詳細.Refresh();
            
            pgs計算.Minimum = 1;
            pgs計算.Step = 1;
            pgs計算.Maximum = 125;

            // 過去の計算データを全て削除
            d08売れ筋商品_RFMta.DeleteALL();

            for (byte iR = 1; iR <= 5; iR++) 
            {
                for (byte iF = 1; iF <= 5; iF++)
                {
                    for (byte iM = 1; iM <= 5; iM++)
                    {
                        // 本SQLは重い為、軽いSQLでデータがあるかチェックする
                        D05計算.D05販売個数DataTable dt販売個数 = new D05計算.D05販売個数DataTable();
                        if ((int)d05販売個数ta.Scalar商品有無チェック(iR, iF, iM) > 0)
                        { 
                            // 本SQL
                            d05販売個数ta.Fill(dt販売個数, iR, iF, iM);

                            for (int iRow = 0; iRow < dt販売個数.Count; iRow++)
                                d08売れ筋商品_RFMta.Insert(iR, iF, iM, dt販売個数[iRow].商品No, iRow + 1,
                                    dt販売個数[iRow].販売個数SUM);
                        }
                            
                        pgs計算.PerformStep();
                        //grp計算処理の進行状況.Refresh();
                    }
                }
            }
        }

        private void Set計算条件()
        {
            D05計算.D05RFM計算条件DataTable dt = new D05計算.D05RFM計算条件DataTable();

            //検索実行
            d05RFM計算条件ta.Fill(dt);

            //検索条件設定
            txtR5_RFM.Text = dt[0].値.Trim();
            txtR4_RFM.Text = dt[1].値.Trim();
            txtR3_RFM.Text = dt[2].値.Trim();
            txtR2_RFM.Text = dt[3].値.Trim();
            txtF5_RFM.Text = dt[4].値.Trim();
            txtF4_RFM.Text = dt[5].値.Trim();
            txtF3_RFM.Text = dt[6].値.Trim();
            txtF2_RFM.Text = dt[7].値.Trim();
            txtM5_RFM.Text = dt[8].値.Trim();
            txtM4_RFM.Text = dt[9].値.Trim();
            txtM3_RFM.Text = dt[10].値.Trim();
            txtM2_RFM.Text = dt[11].値.Trim();

#if 顧客分析君ZERO
#else
            if (dt[12].値 == "1")
                chkRFMの入力値を使う.Checked = true;
            else
                chkRFMの入力値を使う.Checked = false;

            txtF5_顧客動向表.Text = dt[17].値.Trim();
            txtF4_顧客動向表.Text = dt[18].値.Trim();
            txtF3_顧客動向表.Text = dt[19].値.Trim();
            txtF2_顧客動向表.Text = dt[20].値.Trim();
            txtM5_顧客動向表.Text = dt[21].値.Trim();
            txtM4_顧客動向表.Text = dt[22].値.Trim();
            txtM3_顧客動向表.Text = dt[23].値.Trim();
            txtM2_顧客動向表.Text = dt[24].値.Trim();

            txtF3_FM.Text = dt[25].値.Trim();
            txtF2_FM.Text = dt[26].値.Trim();
            txtM3_FM.Text = dt[27].値.Trim();
            txtM2_FM.Text = dt[28].値.Trim();

            dtp計算対象期間From.Text = dt[29].値;
            dtp計算対象期間To.Text = dt[30].値;
#endif
        }

        private void Set表示項目()
        {
#if 顧客分析君ZERO
            tab計算条件.TabPages.RemoveAt(2);
            tab計算条件.TabPages.RemoveAt(0);
#endif
        }

        #endregion


        ////////////////////////////////////////////////////////////////////////
        // イベントハンドラ
        ////////////////////////////////////////////////////////////////////////
        #region イベントハンドラ

        private void _301計算_Load(object sender, EventArgs e)
        {
            try
            {

                Cursor.Current = Cursors.WaitCursor;

                Set計算条件();

                // 計算時間を取得
                txt計算日時.Text = C02業務共通処理.最後に計算した日時();

                lbl計算中の処理詳細.Text = "計算開始待ち";
            }
            catch (Exception ex)
            {
                C04システム共通.ErrorLog("_301計算", "_301計算_Load", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Arrow;
            }
        }

        private void btn最大期間に変更_Click(object sender, EventArgs e)
        {
            try
            {
                if (false == IsValidate計算元データ有無())
                    return;

                dtp計算対象期間From.Value = C02業務共通処理.Get最小販売日時(null, null);
                dtp計算対象期間To.Value = C02業務共通処理.Get最大販売日時(null, null);

                string msg = string.Format(Properties.Resources.MSG_I_Aが完了しました, "最大期間に変更");
                MessageBox.Show(msg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                C04システム共通.ErrorLog("_301計算", "btn最大期間に変更_Click", ex);
            }
        }

		private void btn閾値を自動計算_FM分析_Click(object sender, EventArgs e)
		{
			try
			{
				if (false == IsValidate計算元データ有無())
					return;

				Cursor.Current = Cursors.WaitCursor;

				dtp計算対象期間From.Value = C02業務共通処理.Get最小販売日時(null, null);
				dtp計算対象期間To.Value = C02業務共通処理.Get最大販売日時(null, null);

				string[] strRFMパラメータ = new string[4];

				if (C02業務共通処理.Rパラメータ計算(ref strRFMパラメータ, C02業務共通処理.miFM分析) == false)
				{
					MessageBox.Show(Properties.Resources.MSG_W_販売履歴_顧客一覧に登録されているデータ件数が少な過ぎる為_閾値の自動計算に失敗しました
						, this.Text, MessageBoxButtons.OK
						, MessageBoxIcon.Warning);
					return;
				}

				if (C02業務共通処理.Fパラメータ計算(ref strRFMパラメータ, C02業務共通処理.miFM分析) == false)
				{
					MessageBox.Show(Properties.Resources.MSG_W_販売履歴_顧客一覧に登録されているデータ件数が少な過ぎる為_閾値の自動計算に失敗しました
						, this.Text, MessageBoxButtons.OK
						, MessageBoxIcon.Warning);
					return;
				}

				if (int.Parse(strRFMパラメータ[1]) > 1)
				{
					txtF3_FM.Text = strRFMパラメータ[0];
					txtF2_FM.Text = strRFMパラメータ[1];
				}
				else
				{
					txtF3_FM.Text = "3";
					txtF2_FM.Text = "2";
				}

				if (C02業務共通処理.Mパラメータ計算(ref strRFMパラメータ, C02業務共通処理.miFM分析) == false)
				{
					MessageBox.Show(Properties.Resources.MSG_W_販売履歴_顧客一覧に登録されているデータ件数が少な過ぎる為_閾値の自動計算に失敗しました
						, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
					return;
				}
				txtM3_FM.Text = strRFMパラメータ[0];
				txtM2_FM.Text = strRFMパラメータ[1];

				string msg = string.Format(Properties.Resources.MSG_I_Aが完了しました, "閾値の自動計算");
				MessageBox.Show(msg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
			catch (Exception ex)
			{
				C04システム共通.ErrorLog("_301計算", "btn閾値を自動計算", ex);
			}
			finally
			{
				Cursor.Current = Cursors.Arrow;
			}
		}
		
		private void btn自動計算から各閾値を入力_Click(object sender, EventArgs e)
        {
            try
            {
                if (false == IsValidate計算元データ有無())
                    return;

                Cursor.Current = Cursors.WaitCursor;

                string[] strRFMパラメータ = new string[4];

				if (C02業務共通処理.Rパラメータ計算(ref strRFMパラメータ, C02業務共通処理.miRFM分析) == false)
                {
                    MessageBox.Show(Properties.Resources.MSG_W_販売履歴_顧客一覧に登録されているデータ件数が少な過ぎる為_閾値の自動計算に失敗しました
						, this.Text, MessageBoxButtons.OK
                        , MessageBoxIcon.Warning);
                    return;
                }
                txtR5_RFM.Text = strRFMパラメータ[0];
                txtR4_RFM.Text = strRFMパラメータ[1];
                txtR3_RFM.Text = strRFMパラメータ[2];
                txtR2_RFM.Text = strRFMパラメータ[3];

				if (C02業務共通処理.Fパラメータ計算(ref strRFMパラメータ, C02業務共通処理.miRFM分析) == false)
                {
                    MessageBox.Show(Properties.Resources.MSG_W_販売履歴_顧客一覧に登録されているデータ件数が少な過ぎる為_閾値の自動計算に失敗しました
						, this.Text, MessageBoxButtons.OK
                        , MessageBoxIcon.Warning);
                    return;
                }

                if (int.Parse(strRFMパラメータ[3]) > 1)
                {
                    txtF5_RFM.Text = strRFMパラメータ[0];
                    txtF4_RFM.Text = strRFMパラメータ[1];
                    txtF3_RFM.Text = strRFMパラメータ[2];
                    txtF2_RFM.Text = strRFMパラメータ[3];
                }
                else
                {
                    txtF5_RFM.Text = "5";
                    txtF4_RFM.Text = "4";
                    txtF3_RFM.Text = "3";
                    txtF2_RFM.Text = "2";
                }

				if (C02業務共通処理.Mパラメータ計算(ref strRFMパラメータ, C02業務共通処理.miRFM分析) == false)
                {
                    MessageBox.Show(Properties.Resources.MSG_W_販売履歴_顧客一覧に登録されているデータ件数が少な過ぎる為_閾値の自動計算に失敗しました
						, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                txtM5_RFM.Text = strRFMパラメータ[0];
                txtM4_RFM.Text = strRFMパラメータ[1];
                txtM3_RFM.Text = strRFMパラメータ[2];
                txtM2_RFM.Text = strRFMパラメータ[3];

                string msg = string.Format(Properties.Resources.MSG_I_Aが完了しました, "閾値の自動計算");
                MessageBox.Show(msg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                C04システム共通.ErrorLog("_301計算", "btn閾値を自動計算", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Arrow;
            }
        }

		private void データの整合性を調整()
		{
			lbl計算中の処理詳細.Text = "販売履歴のデータ整合性を調整中...";
			lbl計算中の処理詳細.Refresh();

			d03販売履歴ta.Updateリプレース顧客No();
			C02業務共通処理.未登録顧客の顧客Noを0にする();

			d03販売履歴ta.Updateリプレース商品No();
		}

        private void btn計算開始_Click(object sender, EventArgs e)
        {
            try
            {
                if (false == IsValidate())
                    return;

                //計算元データ有無チェック
                if (false == IsValidate計算元データ有無())
                    return;

#if 顧客分析君ZERO
#else
                if (false == IsValidateFM分析固有())
                    return;
#endif

                if (DialogResult.Yes != MessageBox.Show(string.Format(Properties.Resources.MSG_Q_Aを開始しますか, "計算")
                    , this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                    return;

				if ((int)d10顧客ta.Scalar顧客IDが未登録の顧客Cnt() > 0)
				{
					if (DialogResult.Yes != MessageBox.Show(
						string.Format("「顧客ID」の無い顧客が {0}件登録されている為、計算が正確に行われない可能性があります。\r\n続行しますか？"
						, (int)d10顧客ta.Scalar顧客IDが未登録の顧客Cnt())
						, this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question))
						return;
				}

				Cursor.Current = Cursors.WaitCursor;
                btn計算開始.Enabled = false;
                btnキャンセル.Enabled = false;

                pgs計算.Minimum = 1;
                pgs計算.Value = 1;

				// 事前処理
				//d03販売履歴ta.Updateリプレース顧客No();
				//C02業務共通処理.未登録顧客の顧客Noを0にする();
				データの整合性を調整();

                //C02業務共通処理.DB最適化();

#if 顧客分析君ZERO
#else
				//各計算処理
				FMを計算(1, 7);
#endif

				RFMを計算(2, 7);

#if 顧客分析君ZERO
#else
				売れ筋商品を計算(3, 7);

				顧客動向表を計算(4, 7);

				//レコメンド計算処理
				商品の相関性を計算(5, 7);

				お勧め商品_顧客毎を計算(6, 7);

				お勧め商品_RFMを計算(7, 7);
#endif

				//計算条件を保存
                計算条件保存();

                // 計算時間を取得
                txt計算日時.Text = C02業務共通処理.最後に計算した日時();

                string msg = string.Format(Properties.Resources.MSG_I_Aが完了しました, "計算");
                MessageBox.Show(msg, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);

                C02業務共通処理.Insert操作履歴(this.Text, Properties.Resources.OPRT_009);

                lbl計算中の処理詳細.Text = "完了";
            }
            catch (Exception ex)
            {
                C04システム共通.ErrorLog("_301計算", "btn計算開始_Click", ex);
            }
            finally
            {
                btn計算開始.Enabled = true;
                btnキャンセル.Enabled = true;
                Cursor.Current = Cursors.Arrow;
            }
        }

        private void btnキャンセル_Click(object sender, EventArgs e)
        {
            try
            {
                this.Close();
            }
            catch (Exception ex)
            {
                C04システム共通.ErrorLog("_301計算", "btnキャンセル_Click", ex);
            }
        }

        private void chkRFMの入力値を使う_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                if (chkRFMの入力値を使う.Checked == true)
                { 
                    txtF5_顧客動向表.ReadOnly = true;
                    txtF4_顧客動向表.ReadOnly = true;
                    txtF3_顧客動向表.ReadOnly = true;
                    txtF2_顧客動向表.ReadOnly = true;
                    txtM5_顧客動向表.ReadOnly = true;
                    txtM4_顧客動向表.ReadOnly = true;
                    txtM3_顧客動向表.ReadOnly = true;
                    txtM2_顧客動向表.ReadOnly = true;
                }
                else
                {
                    txtF5_顧客動向表.ReadOnly = false;
                    txtF4_顧客動向表.ReadOnly = false;
                    txtF3_顧客動向表.ReadOnly = false;
                    txtF2_顧客動向表.ReadOnly = false;
                    txtM5_顧客動向表.ReadOnly = false;
                    txtM4_顧客動向表.ReadOnly = false;
                    txtM3_顧客動向表.ReadOnly = false;
                    txtM2_顧客動向表.ReadOnly = false;
                }
            }
            catch (Exception ex)
            {
                C04システム共通.ErrorLog("_301計算", "chkRFMの入力値を使う_CheckedChanged", ex);
            }
        }

        #endregion










    }
}
