public int[] SuggestPersons(string productName)
        {
            try
            {
                string[] relativeProducts = FindRelatives(productName);

                ECDBEntities entity = new ECDBEntities();
                var          ids    = (from purchase in entity.PurchaseTbls
                                       where
                                       relativeProducts.Contains(purchase.ProductName) &&
                                       Math.Abs((double)EntityFunctions.DiffMonths(DateTime.Today, purchase.Date.Value)) <= NumberOfMonthesForPurchase
                                       select purchase.Cid).Distinct();

                return(ids.ToArray());
            }
            catch (Exception ex)
            {
                MySoapFault fault = new MySoapFault();
                fault.Operation   = "SuggestPersons";
                fault.Reason      = "Error in suggesting persons for buyying product name :  " + productName + " .";
                fault.Details     = ex.Message;
                fault.MoreDetails = ex.StackTrace;
                throw new FaultException <MySoapFault>(fault);
            }
        }
        public string[] SuggestProducts(int personId, OrderMode mode)
        {
            try
            {
                ECDBEntities entity            = new ECDBEntities();
                var          purchasedProducts = from purchase in entity.PurchaseTbls
                                                 where purchase.Cid == personId
                                                 select purchase.ProductName;

                string[] relatives = FindAllRelatives(purchasedProducts.ToArray(), mode);

                var nowAds = from ad in entity.AdsTbls
                             select ad.ProductName;

                var result = relatives.Intersect(nowAds);
                return(result.ToArray());
            }
            catch (Exception ex)
            {
                MySoapFault fault = new MySoapFault();
                fault.Operation   = "SuggestProducts";
                fault.Reason      = "Error in suggesting products or finding relatives .";
                fault.Details     = ex.Message;
                fault.MoreDetails = ex.StackTrace;
                throw new FaultException <MySoapFault>(fault);
            }
        }
        public string[] ListAds()
        {
            try
            {
                ECDBEntities entity = new ECDBEntities();

                var prodNames = from ad in entity.AdsTbls
                                select ad.ProductName;

                return(prodNames.ToArray());
            }
            catch (Exception ex)
            {
                MySoapFault fault = new MySoapFault();
                fault.Operation   = "ListAds";
                fault.Reason      = "Error in selecting all ads from database .";
                fault.Details     = ex.Message;
                fault.MoreDetails = ex.StackTrace;
                throw new FaultException <MySoapFault>(fault);
            }
        }
        public CustomerTbl[] GetPersonsDetail(int[] persons)
        {
            try
            {
                ECDBEntities entity = new ECDBEntities();

                var q = from c in entity.CustomerTbls
                        where persons.Contains(c.Cid)
                        select c;

                return(q.ToArray());
            }
            catch (Exception ex)
            {
                MySoapFault fault = new MySoapFault();
                fault.Operation   = "GetPersonsDetail";
                fault.Reason      = "Error in selecting from CustomerTbls from database .";
                fault.Details     = ex.Message;
                fault.MoreDetails = ex.StackTrace;
                throw new FaultException <MySoapFault>(fault);
            }
        }
        public List <int>[] FindBestCustomers() // returns each customer in his/her cluster
        {
            try
            {
                List <int>[] results = new List <int> [3];
                // or 4 cluster because 4th cluster has some poor customers to recommend to purchase goods
                for (int i = 0; i < results.Length; i++)
                {
                    results[i] = new List <int>();
                }

                ECDBEntities entity        = new ECDBEntities();
                int          numberOfBests = (int)(SAMPLE_PERCENT * entity.CustomerTbls.Count());

                // ------------------------------------- FORMULAS -------------------------------------
                // Formula 1
                // (1) / (3)
                var idsFormula1 =
                    entity.CustomerTbls.OrderByDescending(
                        customer => (double)customer.NumberOfPurchases / (double)customer.NumberOfLogins).Select(
                        customer => customer.Cid).Take(numberOfBests);

                // Formula 2
                // 1 / (4) + (5) => max   or   (4) + (5) => min
                var idsFormula2 =
                    entity.CustomerTbls.OrderBy(
                        customer =>
                        (Math.Abs((int)EntityFunctions.DiffMinutes(DateTime.Now, customer.LastLoginDate.Value)) +
                         Math.Abs((int)EntityFunctions.DiffMinutes(DateTime.Now, customer.LastPurchaseDate.Value)))).
                    Select(
                        customer => customer.Cid).
                    Take(numberOfBests);

                // Formula 3
                // (4) / (5)  +  (1) / (2)
                var idsFormula3 = entity.CustomerTbls.OrderByDescending(
                    customer =>
                    Math.Abs((double)EntityFunctions.DiffMinutes(DateTime.Now, customer.LastLoginDate.Value)) /
                    Math.Abs((double)EntityFunctions.DiffMinutes(DateTime.Now, customer.LastPurchaseDate.Value)) +
                    (double)customer.NumberOfPurchases / (double)customer.LoggedInDuration).Select(
                    customer => customer.Cid)
                                  .Take(
                    numberOfBests);

                results[0].AddRange(idsFormula1.Intersect(idsFormula2).Intersect(idsFormula3));

                results[1].AddRange(
                    idsFormula1.Intersect(idsFormula2).Union(idsFormula1.Intersect(idsFormula3)).Union(
                        idsFormula2.Intersect(idsFormula3)).Except(results[0]));

                results[2].AddRange(
                    idsFormula1.Union(idsFormula2).Union(idsFormula3).Except(results[0]).Except(results[1]));


                // ------------------- Working With Database's Best Customers Table -------------------
                // Removing Last Data From Best Customers Table
                entity.ExecuteStoreCommand("DELETE BestCustomersTbls");

                // Adding Better Customers To Best Customers Table))
                for (int i = 0; i < results.Length; i++)
                {
                    foreach (var cid in results[i])
                    {
                        BestCustomersTbl bc = new BestCustomersTbl();
                        bc.ClusterId = i + 1;
                        bc.Cid       = cid;
                        entity.AddToBestCustomersTbls(bc);
                    }
                }
                entity.SaveChanges();

                return(results);
            }
            catch (Exception ex)
            {
                MySoapFault fault = new MySoapFault();
                fault.Operation   = "FindBestCustomers";
                fault.Reason      = "Error in finding best customers occurred .";
                fault.Details     = ex.Message;
                fault.MoreDetails = ex.StackTrace;
                throw new FaultException <MySoapFault>(fault);
            }
        }