public void TestCompundDiscountPolicy_XOR()
        {
            cart.AddProduct(store, 1, 1, false);
            cart.AddProduct(store, 2, 7, false);
            PurchaseBasket basket = cart.GetBasket(store);

            DiscountPolicy minItemsBasketPolicy  = new ConditionalBasketDiscount(preCondition: preConditionsDict[CommonStr.DiscountPreConditions.NumUnitsInBasketAboveEqX], discount: 20, minUnitsAtBasket: 7);
            DiscountPolicy MinUnitsProductPolicy = new ConditionalProductDiscount(preCondition: preConditionsDict[CommonStr.DiscountPreConditions.NumUnitsOfProductAboveEqX], discount: 30, minUnits: 1, productId: 1);

            List <DiscountPolicy> policies_lst = new List <DiscountPolicy>();

            policies_lst.Add(minItemsBasketPolicy);
            policies_lst.Add(MinUnitsProductPolicy);
            DiscountPolicy compundDiscount = new CompundDiscount(CommonStr.DiscountMergeTypes.XOR, policies_lst);
            double         discount        = compundDiscount.CalcDiscount(basket);
            double         expected        = 3000;

            Assert.AreEqual(expected, discount);
        }
        public static DiscountPolicy Parse(string text)
        {
            if (simpleDiscountRegex.IsMatch(text))
            {
                if (conditionalBasketDiscountRegex.IsMatch(text))
                {
                    string[] constructs   = text.Split(':');
                    int      precondition = Convert.ToInt32(constructs[1]);
                    double   discount     = Convert.ToDouble(constructs[2]);
                    return(new ConditionalBasketDiscount(discount, new DiscountPreCondition(precondition)));
                }
                else if (conditionalBasketDiscountMBPRegex.IsMatch(text))
                {
                    string[] constructs     = text.Split(':');
                    int      precondition   = Convert.ToInt32(constructs[1]);
                    double   discount       = Convert.ToDouble(constructs[2]);
                    double   minBasketPrice = Convert.ToDouble(constructs[3]);
                    return(new ConditionalBasketDiscount(new DiscountPreCondition(precondition), discount, minBasketPrice));
                }
                else if (conditionalBasketDiscountMPPRegex.IsMatch(text))
                {
                    string[] constructs      = text.Split(':');
                    int      precondition    = Convert.ToInt32(constructs[1]);
                    double   discount        = Convert.ToDouble(constructs[2]);
                    double   minProductPrice = Convert.ToDouble(constructs[3]);
                    return(new ConditionalBasketDiscount(minProductPrice, discount, new DiscountPreCondition(precondition)));
                }
                else if (conditionalBasketDiscountMUBRegex.IsMatch(text))
                {
                    string[] constructs       = text.Split(':');
                    int      precondition     = Convert.ToInt32(constructs[1]);
                    double   discount         = Convert.ToDouble(constructs[2]);
                    int      minUnitsAtBasket = Convert.ToInt32(constructs[3]);
                    return(new ConditionalBasketDiscount(new DiscountPreCondition(precondition), discount, minUnitsAtBasket));
                }
                else if (conditionalProductDiscountRegex.IsMatch(text))
                {
                    string[] constructs   = text.Split(':');
                    int      minUnits     = Convert.ToInt32(constructs[1]);
                    int      productId    = Convert.ToInt32(constructs[2]);
                    int      precondition = Convert.ToInt32(constructs[3]);
                    double   discount     = Convert.ToDouble(constructs[4]);
                    return(new ConditionalProductDiscount(new DiscountPreCondition(precondition), discount, minUnits, productId));
                }
                else if (revealdDiscountRegex.IsMatch(text))
                {
                    string[] constructs = text.Split(':');
                    double   discount   = Convert.ToDouble(constructs[1]);
                    int      productId  = Convert.ToInt32(constructs[2]);
                    return(new RevealdDiscount(productId, discount));
                }
            }
            else // compount discount
            {
                int      counter    = 0;
                string   curr       = "";
                string[] constructs = Regex.Split(text, "(XOR|OR|AND)");
                if (constructs.Length <= 1)
                {
                    return(new RevealdDiscount(-1, -1));
                }
                string opStr = constructs[1];
                int    op    = opStr == "XOR" ? 0 : opStr == "OR" ? 1 : opStr == "AND" ? 2 : -1;
                if (op == -1)
                {
                    return(new RevealdDiscount(-3, -3));
                }
                string        restText  = text.Substring(opStr.Length + 2, text.Length - 1 - opStr.Length - 2);
                List <string> discounts = new List <string>();
                for (int i = 0; i < restText.Length; i++)
                {
                    if (restText[i] == '(')
                    {
                        if (counter == 0) // shift from 0 to 1 -> new element
                        {
                            curr = "";
                        }
                        counter++;
                    }
                    else if (restText[i] == ')')
                    {
                        if (counter == 1) // shift from 1 to 0 -> finish the current element
                        {
                            curr += restText[i];
                            discounts.Add(curr);
                            curr = "";
                        }
                        counter--;
                    }
                    else if (restText[i] == ' ' && counter == 0)
                    {
                        if (!discounts.Contains(curr) && curr != "")
                        {
                            discounts.Add(curr);
                            curr = "";
                        }
                    }
                    if (!(counter == 0 || curr == ")"))
                    {
                        curr += restText[i];
                    }
                    if (counter == 0 && restText[i] != ')' && restText[i] != '(' && restText[i] != ' ')
                    {
                        curr += restText[i];
                    }
                }
                if (curr != "")
                {
                    discounts.Add(curr);
                }
                if (counter != 0)
                {
                    return(new RevealdDiscount(-1, -1));
                }

                List <DiscountPolicy> children = new List <DiscountPolicy>();

                foreach (string discount in discounts)
                {
                    DiscountPolicy discountPolicy = Parse(discount);
                    if (checkDiscount(discountPolicy) == false) // this indicates an error!
                    {
                        return(new RevealdDiscount(-2, -2));
                    }
                    else
                    {
                        children.Add(discountPolicy);
                    }
                }
                DiscountPolicy compoundDiscount = new CompundDiscount(op, children);
                return(compoundDiscount);
            }
            return(new RevealdDiscount(-4, -4));
        }