Example #1
0
        /// <summary>
        /// 對指定運算符實例化
        /// </summary>
        /// <param name="sign">運算符</param>
        /// <returns>運算符實例</returns>
        public IArithmetic GetFormulaOperator(SignOfOperation sign)
        {
            // 返回緩衝區中的運算符對象
            Lazy <ArithmeticBase, IArithmeticMetaDataView> lazyArithmetic = ArithmeticCache.GetOrAdd(sign, (c) =>
            {
                // 從MEF容器中注入本類的屬性信息(注入運算符屬性)
                _composer.Compose(this);

                LogUtil.LogDebug(MessageUtil.GetMessage(() => MsgResources.I0001L));

                // 指定運算符并獲取處理類型
                IEnumerable <Lazy <ArithmeticBase, IArithmeticMetaDataView> > arithmetics = Arithmetics.Where(d => { return(d.Metadata.Sign == sign); });
                if (!arithmetics.Any())
                {
                    // 指定的題型參數對象未找到
                    throw new ArithmeticNotFoundException(MessageUtil.GetMessage(() => MsgResources.E0020L, sign.ToString()));
                }
                LogUtil.LogDebug(MessageUtil.GetMessage(() => MsgResources.I0002L, sign.ToString()));

                return(arithmetics.First());
            });

            ArithmeticBase arithmetic = lazyArithmetic.Value;

            // 內部部件組合
            _composer.Compose(arithmetic);
            // 返回該運算符處理類型的實例
            return(arithmetic);
        }
Example #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="operation"></param>
        /// <returns></returns>
        public static string ToOperationString(this SignOfOperation operation)
        {
            var flag = string.Empty;

            switch (operation)
            {
            case SignOfOperation.Plus:
                flag = "+";
                break;

            case SignOfOperation.Subtraction:
                flag = "-";
                break;

            case SignOfOperation.Division:
                flag = "÷";
                break;

            case SignOfOperation.Multiple:
                flag = "×";
                break;

            case SignOfOperation.Before:
                flag = "之前";
                break;

            case SignOfOperation.Later:
                flag = "之後";
                break;

            default:
                break;
            }
            return(flag);
        }
Example #3
0
        /// <summary>
        /// 獲取運算符對應的簡寫ID
        /// </summary>
        /// <param name="operation">運算符</param>
        /// <returns>簡寫ID</returns>
        public static string OperationToID(this SignOfOperation operation)
        {
            var flag = string.Empty;

            switch (operation)
            {
            case SignOfOperation.Plus:
                flag = "P";
                break;

            case SignOfOperation.Subtraction:
                flag = "S";
                break;

            case SignOfOperation.Division:
                flag = "D";
                break;

            case SignOfOperation.Multiple:
                flag = "M";
                break;

            default:
                break;
            }
            return(flag);
        }
 /// <summary>
 /// 算式作成
 /// </summary>
 /// <param name="p">題型參數</param>
 /// <param name="signFunc">運算符取得用的表達式</param>
 private void MarkFormulaList(TimeCalculationParameter p, Func <SignOfOperation> signFunc)
 {
     // 按照指定數量作成相應的數學計算式
     for (var i = 0; i < p.NumberOfQuestions; i++)
     {
         // 結束時間
         TimeType        endTime;
         SignOfOperation sign = signFunc();
         // 對指定運算符實例化(時間計算:之前和之後)
         IArithmetic strategy = CalculateManager(sign);
         Formula     formula  = strategy.CreateFormula(new ArithmeticParameter()
         {
             // 開始時間
             MaximumLimit = GetStartTime(p, out TimeType startTime),
             // 結束時間
             MinimumLimit = GetElapsedTime(p, out TimeType elapsedTime)
         });
Example #5
0
        /// <summary>
        /// 經過時間計算式
        /// </summary>
        /// <param name="elapsedTime">時間計算式</param>
        /// <param name="gap">填空項目</param>
        /// <param name="sign">運算符(之前\之後)</param>
        /// <param name="index">控件索引ID</param>
        /// <returns>HTML模板信息</returns>
        private string GetElapsedTimeHtml(TimeType elapsedTime, GapFilling gap, SignOfOperation sign, int index)
        {
            var html = string.Empty;

            html += string.Format(SPAN_TIME_NUM_HTML_FORMAT, "在");
            // 如果是填空項目
            if (gap == GapFilling.Right)
            {
                // 小時
                html += string.Format(INPUT_HTML_FORMAT, index.ToString().PadLeft(2, '0'), "0");
                html += string.Format(SPAN_TIME_NUM_HTML_FORMAT, Consts.HOUR_UNIT);
                // 分鐘
                html += string.Format(INPUT_HTML_FORMAT, index.ToString().PadLeft(2, '0'), "1");
                html += string.Format(SPAN_TIME_NUM_HTML_FORMAT, Consts.MINUTE_UNIT);
                // 秒
                html += string.Format(INPUT_HTML_FORMAT, index.ToString().PadLeft(2, '0'), "2");
                html += string.Format(SPAN_TIME_NUM_HTML_FORMAT, Consts.SEC_UNIT);

                // 題型答案
                html += string.Format(INPUT_ANSWER_HTML_FORMAT, index.ToString().PadLeft(2, '0'), Base64.EncodeBase64(elapsedTime.HMSValue));
            }
            else
            {
                // 時間顯示(eg: 9小時23分鐘3秒)
                // 小時
                if (elapsedTime.Hours.Value != 0)
                {
                    html += string.Format(SPAN_TIME_CN_HTML_FORMAT, elapsedTime.Hours, Consts.HOUR_UNIT);
                }
                // 分鐘
                if (elapsedTime.Minutes.Value != 0)
                {
                    html += string.Format(SPAN_TIME_CN_HTML_FORMAT, elapsedTime.Minutes, Consts.MINUTE_UNIT);
                }
                // 秒
                if (elapsedTime.Seconds.Value != 0)
                {
                    html += string.Format(SPAN_TIME_CN_HTML_FORMAT, elapsedTime.Seconds, Consts.SEC_UNIT);
                }
            }
            html += string.Format(SPAN_TIME_NUM_HTML_FORMAT, sign.ToOperationUnicode());
            return(html);
        }
Example #6
0
        /// <summary>
        /// 運算符轉換為對應的字符編碼
        /// </summary>
        /// <param name="operation">運算符(加減乘除)</param>
        /// <returns>字符編碼</returns>
        public static string ToOperationString(this SignOfOperation operation)
        {
            var flag = string.Empty;

            switch (operation)
            {
            // +
            case SignOfOperation.Plus:
                flag = "+";
                break;

            // −
            case SignOfOperation.Subtraction:
                flag = "-";
                break;

            // ÷
            case SignOfOperation.Division:
                flag = "/";
                break;

            // ×
            case SignOfOperation.Multiple:
                flag = "*";
                break;

            // 之前
            case SignOfOperation.Before:
                flag = "之前";
                break;

            // 之后
            case SignOfOperation.Later:
                flag = "之后";
                break;

            default:
                break;
            }
            return(flag);
        }
Example #7
0
        /// <summary>
        /// 運算符轉換為對應的字符編碼
        /// </summary>
        /// <param name="operation">運算符(加減乘除)</param>
        /// <returns>字符編碼</returns>
        public static string ToOperationUnicode(this SignOfOperation operation)
        {
            var flag = string.Empty;

            switch (operation)
            {
            // +
            case SignOfOperation.Plus:
                flag = "&#43;";
                break;

            // −
            case SignOfOperation.Subtraction:
                flag = "&#8722;";
                break;

            // ÷
            case SignOfOperation.Division:
                flag = "&#247;";
                break;

            // ×
            case SignOfOperation.Multiple:
                flag = "&#215;";
                break;

            // 之前
            case SignOfOperation.Before:
                flag = "&#20043;&#21069;";
                break;

            // 之后
            case SignOfOperation.Later:
                flag = "&#20043;&#21518;";
                break;

            default:
                break;
            }
            return(flag);
        }
        /// <summary>
        /// 算式作成
        /// </summary>
        /// <param name="p">題型參數</param>
        /// <param name="signFunc">運算符取得用的表達式</param>
        private void MarkFormulaList(MathWordProblemsParameter p, Func <SignOfOperation> signFunc)
        {
            // 當前反推判定次數(一次推算內次數累加)
            int defeated = 0;

            // 按照指定數量作成相應的數學計算式
            for (var i = 0; i < p.NumberOfQuestions; i++)
            {
                SignOfOperation sign         = signFunc();
                List <Problems> signProblems = GetProblemsBySign(sign, p.Levels);
                // 題庫中的數量比指定的出題數少的情況
                if (signProblems.Count == 0)
                {
                    continue;
                }

                // 計算式作成
                MarkFormulas(p, signProblems);
                // 判定是否需要反推并重新作成計算式
                if (CheckIsNeedInverseMethod(p.Formulas.Last()))
                {
                    p.Formulas.Remove(p.Formulas.Last());

                    defeated++;
                    // 如果大於兩次則認為此題無法作成繼續下一題
                    if (defeated == INVERSE_NUMBER)
                    {
                        // 當前反推判定次數復原
                        defeated = 0;
                        continue;
                    }
                    i--;
                    continue;
                }
            }
        }
Example #9
0
 /// <summary>
 /// 對指定運算符實例化
 /// </summary>
 /// <param name="sign">運算符</param>
 /// <returns>運算符實例</returns>
 public IArithmetic CreateArithmeticInstance(SignOfOperation sign)
 {
     // 運算符工廠實例化
     return(arithmeticFactory.GetFormulaOperator(sign));
 }
Example #10
0
 /// <summary>
 /// 對指定運算符實例化
 /// </summary>
 /// <param name="sign">運算符</param>
 /// <returns>運算符實例</returns>
 protected IArithmetic CalculateManager(SignOfOperation sign)
 {
     return(Helper.CreateArithmeticInstance(sign));
 }
Example #11
0
        /// <summary>
        /// 加減算式作成
        /// </summary>
        /// <param name="p">題型參數</param>
        public override void MarkFormulaList(CurrencyOperationParameter p)
        {
            // 標準題型(指定單個運算符)
            if (p.FourOperationsType == FourOperationsType.Standard)
            {
                // 考虑乘除法接龙答题结果会超出限制,所以只随机加减法策略
                if (p.Signs[0] == SignOfOperation.Division || p.Signs[0] == SignOfOperation.Multiple)
                {
                    p.Signs[0] = SignOfOperation.Plus;
                }

                // 指定單個運算符實例
                IArithmetic strategy = CalculateManager(p.Signs[0]);
                // 按照指定數量作成相應的數學計算式
                for (var i = 0; i < p.NumberOfQuestions; i++)
                {
                    Formula formula = strategy.CreateFormula(new ArithmeticParameter()
                    {
                        MaximumLimit = p.MaximumLimit,
                        QuestionType = p.QuestionType,
                        MinimumLimit = 0
                    });
                    if (CheckIsNeedInverseMethod(p.Formulas, formula))
                    {
                        i--;
                        continue;
                    }
                    // 計算式作成
                    p.Formulas.Add(new CurrencyOperationFormula
                    {
                        // 貨幣運算方程式
                        CurrencyArithmetic = formula,
                        // 等式值是不是出現在右邊
                        AnswerIsRight = IsRight
                    });
                }
            }
            else
            {
                // 按照指定數量作成相應的數學計算式
                for (var i = 0; i < p.NumberOfQuestions; i++)
                {
                    // 混合題型(加減運算符實例隨機抽取)
                    SignOfOperation sign = CommonUtil.GetRandomNumber(SignOfOperation.Plus, SignOfOperation.Subtraction);
                    // 對運算符實例進行cache管理
                    IArithmetic strategy = CalculateManager(sign);

                    var formula = strategy.CreateFormula(new ArithmeticParameter()
                    {
                        MaximumLimit = p.MaximumLimit,
                        QuestionType = p.QuestionType,
                        MinimumLimit = 0
                    });

                    if (CheckIsNeedInverseMethod(p.Formulas, formula))
                    {
                        i--;
                        continue;
                    }

                    // 計算式作成
                    p.Formulas.Add(new CurrencyOperationFormula
                    {
                        // 貨幣運算方程式
                        CurrencyArithmetic = formula,
                        // 等式值是不是出現在右邊
                        AnswerIsRight = IsRight
                    });
                }
            }
        }
 /// <summary>
 /// 獲取指定運算符出題資料庫
 /// </summary>
 /// <param name="sign">運算符</param>
 /// <param name="levels">等級選擇</param>
 /// <returns>出題資料庫</returns>
 private List <Problems> GetProblemsBySign(SignOfOperation sign, int[] levels)
 {
     return(_allProblems.Where(d => d.Sign == (int)sign && Array.IndexOf(levels, d.Level) >= 0).ToList());
 }
        /// <summary>
        /// 綜合題型巧算(合併)
        /// </summary>
        /// <param name="formulas">計算式作成</param>
        protected virtual void CleverWithSyntheticCombine(IList <CleverCalculationFormula> formulas)
        {
            // 當前反推判定次數(一次推算內次數累加)
            int defeated = 0;

            CleverCalculationFormula cleverCalculation = new CleverCalculationFormula
            {
                Type           = (int)Synthetic.Combine,
                ConfixFormulas = new List <Formula>(),
                Answer         = new List <int>()
            };

            while (1 == 1)
            {
                // 如果大於三次則認為此題無法作成繼續下一題
                if (defeated == INVERSE_NUMBER)
                {
                    cleverCalculation = null;
                    break;
                }

                cleverCalculation.ConfixFormulas.Clear();
                cleverCalculation.Answer.Clear();

                var answer = 0;
                // 獲取一個10以內的共有因數
                int factorShare = CommonUtil.GetRandomNumber(3, 9);

                // 合併方法(加法或者减法)
                SignOfOperation combine = CommonUtil.GetRandomNumber(SignOfOperation.Plus, SignOfOperation.Subtraction);

                StringBuilder express = new StringBuilder();
                // 加法合併
                if (combine == SignOfOperation.Plus)
                {
                    int factor1 = CommonUtil.GetRandomNumber(1, 9);

                    // 加法合併的兩種情況:
                    // 1.相加之和是整十數
                    int factor2 = CommonUtil.GetRandomNumber(1, 50, condition: _ => (_ % 10 == 0 || _ + factor1 <= 10) && _ != factor1, getDefault: () => 30);
                    // 2.相加之和是十
                    if (factor2 > 10)
                    {
                        factor2 -= factor1;
                    }
                    // 隨機排列計算式各參數(打亂參數位置)
                    SetNewGuidFactors(out List <int> factors1, factorShare, factor1);
                    SetNewGuidFactors(out List <int> factors2, factorShare, factor2);
                    // eg: 8 * 5 + 2 * 5 = (8 + 2) * 5 = 10 * 5
                    express.AppendFormat(CultureInfo.CurrentCulture, "{0}*{1}+{2}*{3}", factors1[0], factors1[1], factors2[0], factors2[1]);

                    answer = (factor1 + factor2) * factorShare;
                    cleverCalculation.ConfixFormulas.Add(new Formula(factor1 + factor2, factorShare, answer, SignOfOperation.Multiple));
                    cleverCalculation.Answer.Add(answer);
                }
                // 減法合併
                else
                {
                    int factor1 = CommonUtil.GetRandomNumber(11, 19);
                    int factor2 = CommonUtil.GetRandomNumber(5, 9, condition: _ => factor1 - _ <= 10, getDefault: () => 5);

                    // 隨機排列計算式各參數(打亂參數位置)
                    SetNewGuidFactors(out List <int> factors1, factorShare, factor1);
                    SetNewGuidFactors(out List <int> factors2, factorShare, factor2);
                    // eg: 18 * 5 - 9 * 5 = (18 - 9) * 5 = 20
                    express.AppendFormat(CultureInfo.CurrentCulture, "{0}*{1}-{2}*{3}", factors1[0], factors1[1], factors2[0], factors2[1]);

                    answer = (factor1 - factor2) * factorShare;
                    cleverCalculation.ConfixFormulas.Add(new Formula(factor1 - factor2, factorShare, answer, SignOfOperation.Multiple));
                    cleverCalculation.Answer.Add(answer);
                }

                // 計算式推導
                var calc = new ExpressArithmeticUtil();
                if (!calc.IsResult(express.ToString(), out int result))
                {
                    defeated++;
                    continue;
                }
                if (result != answer)
                {
                    defeated++;
                    continue;
                }
                // 加入推導出計算式集合
                calc.Formulas.ToList().ForEach(f => cleverCalculation.ConfixFormulas.Add(f));
                defeated = 0;

                break;
            }

            if (cleverCalculation != null)
            {
                formulas.Add(cleverCalculation);
            }
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="sign"></param>
 public ArithmeticAttribute(SignOfOperation sign) : base(typeof(ArithmeticBase))
 {
     Sign = sign;
 }