Exemple #1
0
        private bool CalcIsPrimitive()
        {
            var nonZeroSides = Sides.Where(s => s != 0).ToArray();

            for (int f = 2; f <= (int)Math.Ceiling((double)Sides.Max()); f++)
            {
                if (nonZeroSides.All(s => Numerics.IsIntegral((double)s / f)))
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// The on post event
        /// </summary>
        public void OnPost()
        {
            Combos  = Menu.AvailableCombos;
            Drinks  = Menu.AvailableDrinks;
            Entrees = Menu.AvailableEntrees;
            Sides   = Menu.AvailableSides;


            if (search != null)
            {
                Combos  = Combos.Where(item => item.ToString().Contains(search, StringComparison.OrdinalIgnoreCase));
                Drinks  = Drinks.Where(item => item.ToString().Contains(search, StringComparison.OrdinalIgnoreCase));
                Entrees = Entrees.Where(item => item.ToString().Contains(search, StringComparison.OrdinalIgnoreCase));
                Sides   = Sides.Where(item => item.ToString().Contains(search, StringComparison.OrdinalIgnoreCase));
            }

            if (minimumPrice != null)
            {
                Combos  = Combos.Where(item => item.Price >= minimumPrice);
                Drinks  = Drinks.Where(item => item.Price >= minimumPrice);
                Entrees = Entrees.Where(item => item.Price >= minimumPrice);
                Sides   = Sides.Where(item => item.Price >= minimumPrice);
            }

            if (maximumPrice != null)
            {
                Combos  = Combos.Where(item => item.Price <= maximumPrice);
                Drinks  = Drinks.Where(item => item.Price <= maximumPrice);
                Entrees = Entrees.Where(item => item.Price <= maximumPrice);
                Sides   = Sides.Where(item => item.Price <= maximumPrice);
            }

            if (possibleIngredients.Count > 0)
            {
                foreach (string ingredients in possibleIngredients)
                {
                    Combos  = Combos.Where(item => !(item.Ingredients.Contains(ingredients)));
                    Drinks  = Drinks.Where(item => !(item.Ingredients.Contains(ingredients)));
                    Entrees = Entrees.Where(item => !(item.Ingredients.Contains(ingredients)));
                    Sides   = Sides.Where(item => !(item.Ingredients.Contains(ingredients)));
                }
            }

            if (menuCategory.Count > 0)
            {
            }
        }
Exemple #3
0
 public void OnPost()
 {
     Combos  = Menu.AvailableCombos;
     Entrees = Menu.AvailableEntrees;
     Sides   = Menu.AvailableSides;
     Drinks  = Menu.AvailableDrinks;
     if (search != null)
     {
         Combos  = Combos.Where(combo => combo.Description.Contains(search, StringComparison.OrdinalIgnoreCase));
         Entrees = Entrees.Where(entree => entree.Description.Contains(search, StringComparison.OrdinalIgnoreCase));
         Sides   = Sides.Where(side => side.Description.Contains(search, StringComparison.OrdinalIgnoreCase));
         Drinks  = Drinks.Where(drink => drink.Description.Contains(search, StringComparison.OrdinalIgnoreCase));
     }
     if (menuCategory.Count != 0)
     {
         Combos  = Combos.Where(combo => menuCategory.Contains("Combo"));
         Entrees = Entrees.Where(entree => menuCategory.Contains("Entree"));
         Sides   = Sides.Where(side => menuCategory.Contains("Side"));
         Drinks  = Drinks.Where(drink => menuCategory.Contains("Drink"));
     }
     if (ingredients.Count != 0)
     {
         foreach (string c in ingredients)
         {
             Combos  = Combos.Where(combo => !combo.Ingredients.Contains(c));
             Entrees = Entrees.Where(entree => !entree.Ingredients.Contains(c));
             Sides   = Sides.Where(side => !side.Ingredients.Contains(c));
             Drinks  = Drinks.Where(drink => !drink.Ingredients.Contains(c));
         }
     }
     if (minimumPrice != null)
     {
         Combos  = Combos.Where(combo => combo.Price > minimumPrice || Math.Abs(combo.Price - (double)minimumPrice) < .0001);
         Entrees = Entrees.Where(entree => entree.Price >= minimumPrice || Math.Abs(entree.Price - (double)minimumPrice) < .0001);
         Sides   = Sides.Where(side => side.Price >= minimumPrice || Math.Abs(side.Price - (double)minimumPrice) < .0001);
         Drinks  = Drinks.Where(drink => drink.Price >= minimumPrice || Math.Abs(drink.Price - (double)minimumPrice) < .0001);
     }
     if (maximumPrice != null)
     {
         Combos  = Combos.Where(combo => combo.Price <= maximumPrice || Math.Abs(combo.Price - (double)maximumPrice) < .0001);
         Entrees = Entrees.Where(entree => entree.Price <= maximumPrice || Math.Abs(entree.Price - (double)maximumPrice) < .0001);
         Sides   = Sides.Where(side => side.Price <= maximumPrice || Math.Abs(side.Price - (double)maximumPrice) < .0001);
         Drinks  = Drinks.Where(drink => drink.Price <= maximumPrice || Math.Abs(drink.Price - (double)maximumPrice) < .0001);
     }
 }
Exemple #4
0
 /// <summary>
 /// Whenever something is clicked this happens
 /// </summary>
 public void OnPost()
 {
     Combos    = Menu.AvailableCombos;
     Entrees   = Menu.AvailableEntrees;
     Sides     = Menu.AvailableSides;
     MenuItems = Menu.AvailableMenuItems;
     Drinks    = Menu.AvailableDrinks;
     Menu.AllIngredients(Menu.AvailableCombos);
     Menu.AllIngredients(Menu.AvailableEntrees);
     Menu.AllIngredients(Menu.AvailableSides);
     Menu.AllIngredients(Menu.AvailableDrinks);
     PossibleIngredientsHashSet = Menu.PossibleIngredients;
     if (Search != null)
     {
         Combos  = Combos.Where(combo => combo.ToString().Contains(Search));
         Entrees = Entrees.Where(entree => entree.ToString().Contains(Search));
         Sides   = Sides.Where(side => side.ToString().Contains(Search));
         Drinks  = Drinks.Where(drink => drink.ToString().Contains(Search));
     }
     if (Filter.Count != 0)
     {
         Combos  = Combos.Where(combo => combo is CretaceousCombo && Filter.Contains("Combo"));;
         Entrees = Entrees.Where(entree => entree is Entree && Filter.Contains("Entree"));
         Sides   = Sides.Where(side => side is Side && Filter.Contains("Side"));
         Drinks  = Drinks.Where(drink => drink is Drink && Filter.Contains("Drink"));
     }
     if (Ingredients.Count != 0)
     {
         Combos = Combos.Where(combo =>
         {
             bool keep = false;
             for (int i = 0; i < Ingredients.Count; i++)
             {
                 if (combo.Ingredients.Contains(Ingredients[i]))
                 {
                     keep = true;
                 }
             }
             return(keep);
         });
         Entrees = Entrees.Where(entree =>
         {
             bool keep = false;
             for (int i = 0; i < Ingredients.Count; i++)
             {
                 if (entree.Ingredients.Contains(Ingredients[i]))
                 {
                     keep = true;
                 }
             }
             return(keep);
         });
         Sides = Sides.Where(side =>
         {
             bool keep = false;
             for (int i = 0; i < Ingredients.Count; i++)
             {
                 if (side.Ingredients.Contains(Ingredients[i]))
                 {
                     keep = true;
                 }
             }
             return(keep);
         });
         Drinks = Drinks.Where(drink =>
         {
             bool keep = false;
             for (int i = 0; i < Ingredients.Count; i++)
             {
                 if (drink.Ingredients.Contains(Ingredients[i]))
                 {
                     keep = true;
                 }
             }
             return(keep);
         });
     }
     if (MinimumPrice != null)
     {
         Combos  = Combos.Where(combo => combo.Price >= MinimumPrice);
         Entrees = Entrees.Where(entree => entree.Price >= MinimumPrice);
         Sides   = Sides.Where(side => side.Price >= MinimumPrice);
         Drinks  = Drinks.Where(drink => drink.Price >= MinimumPrice);
     }
     if (MaximumPrice != null)
     {
         Combos  = Combos.Where(combo => combo.Price <= MaximumPrice);
         Entrees = Entrees.Where(entree => entree.Price <= MaximumPrice);
         Sides   = Sides.Where(side => side.Price <= MaximumPrice);
         Drinks  = Drinks.Where(drink => drink.Price <= MaximumPrice);
     }
 }
Exemple #5
0
        private static Int3 StepAlongPath(Room room, Int3 currentLocation, Sides[] possibleSides,
            Directions[] possibleDirections, List<Int3> solutionPath, int i, int minPathLength, ref Directions lastDirection)
        {
            var currentSide = room.roomBuffer[currentLocation.X, currentLocation.Y, currentLocation.Z];

            if (lastDirection != Directions.None && UnityEngine.Random.Range(0, 2) == 0)
            {
                var side = currentSide;
                var direction = lastDirection;

                var desirableSides = possibleSides
                    .Where(s => (s & side) == 0 && s != Sides.None &&
                                (
                                    s == Sides.Left && direction != Directions.Right
                                    || s == Sides.Right && direction != Directions.Left
                                    || s == Sides.Top && direction != Directions.Down
                                    || s == Sides.Bottom && direction != Directions.Up
                                    || s == Sides.Front && direction != Directions.Back
                                    || s == Sides.Rear && direction != Directions.Forward
                                    ));

                if (desirableSides.Any())
                {
                    currentSide = desirableSides.SelectRandom();
                    room.roomBuffer[currentLocation.X, currentLocation.Y, currentLocation.Z] |= currentSide;
                }
            }

            var intendedLocation = DetermineNextLocation(room, currentLocation, possibleDirections, ref lastDirection);

            room.roomBuffer[intendedLocation.X, intendedLocation.Y, intendedLocation.Z] |= currentSide;
            currentLocation = intendedLocation;
            solutionPath.Add(currentLocation);

            return currentLocation;
        }
Exemple #6
0
        /// <summary>
        /// The Post method responses to the server, use the LINQ Enumberable.Where method
        /// </summary>
        public void OnPost()
        {
            Combos  = Menu.AvailableCombos;
            Entrees = Menu.AvailableEntrees;
            Sides   = Menu.AvailableSides;
            Drinks  = Menu.AvailableDrinks;

            Menu.AllIngredients(Menu.AvailableCombos);
            Menu.AllIngredients(Menu.AvailableEntrees);
            Menu.AllIngredients(Menu.AvailableSides);
            Menu.AllIngredients(Menu.AvailableDrinks);
            Ingre = Menu.PossibleIngredients;

            if (search != null)
            {
                Combos  = Combos.Where(combo => combo.ToString().Contains(search));
                Entrees = Entrees.Where(entree => entree.ToString().Contains(search));
                Sides   = Sides.Where(side => side.ToString().Contains(search));
                Drinks  = Drinks.Where(drink => drink.ToString().Contains(search));
            }

            if (filters.Count != 0)
            {
                Combos  = Combos.Where(combo => combo is CretaceousCombo && filters.Contains("Combo"));
                Entrees = Entrees.Where(entree => entree is Entree && filters.Contains("Entree"));
                Sides   = Sides.Where(side => side is Side && filters.Contains("Side"));
                Drinks  = Drinks.Where(drink => drink is Drink && filters.Contains("Drink"));
            }

            if (minPrice != null)
            {
                Combos  = Combos.Where(combo => combo.Price >= minPrice);
                Entrees = Entrees.Where(entree => entree.Price >= minPrice);
                Sides   = Sides.Where(side => side.Price >= minPrice);
                Drinks  = Drinks.Where(drink => drink.Price >= minPrice);
            }

            if (maxPrice != null)
            {
                Combos  = Combos.Where(combo => combo.Price <= maxPrice);
                Entrees = Entrees.Where(entree => entree.Price <= maxPrice);
                Sides   = Sides.Where(side => side.Price <= maxPrice);
                Drinks  = Drinks.Where(drink => drink.Price <= maxPrice);
            }


            if (ingredients.Count != 0)
            {
                Combos = Combos.Where(combo =>
                {
                    List <IMenuItem> results = new List <IMenuItem>();
                    bool safeToAdd           = true;
                    for (int j = 0; j < ingredients.Count; j++)
                    {
                        if (combo.Ingredients.Contains(ingredients[j]))
                        {
                            safeToAdd = false;
                            break;
                        }
                    }
                    return(safeToAdd);
                });

                Entrees = Entrees.Where(entree =>
                {
                    List <IMenuItem> results = new List <IMenuItem>();
                    bool safeToAdd           = true;
                    for (int j = 0; j < ingredients.Count; j++)
                    {
                        if (entree.Ingredients.Contains(ingredients[j]))
                        {
                            safeToAdd = false;
                            break;
                        }
                    }
                    return(safeToAdd);
                });

                Sides = Sides.Where(side =>
                {
                    List <IMenuItem> results = new List <IMenuItem>();
                    bool safeToAdd           = true;
                    for (int j = 0; j < ingredients.Count; j++)
                    {
                        if (side.Ingredients.Contains(ingredients[j]))
                        {
                            safeToAdd = false;
                            break;
                        }
                    }
                    return(safeToAdd);
                });

                Drinks = Drinks.Where(drink =>
                {
                    List <IMenuItem> results = new List <IMenuItem>();
                    bool safeToAdd           = true;
                    for (int j = 0; j < ingredients.Count; j++)
                    {
                        if (drink.Ingredients.Contains(ingredients[j]))
                        {
                            safeToAdd = false;
                            break;
                        }
                    }
                    return(safeToAdd);
                });
            }
        }
        /// <summary>
        /// Gets the filters, gets new lists using the filters, and reloads the page
        /// </summary>
        /// <param name="SearchTerms">Phrase to search for</param>
        /// <param name="Category">Entree, Side, or Drink</param>
        /// <param name="PriceMin">Min price</param>
        /// <param name="PriceMax">Max price</param>
        /// <param name="CalorieMin">min Calorie</param>
        /// <param name="CalorieMax">max Calorie</param>
        public void OnGet(string SearchTerms, string[] Category, double?PriceMin, double?PriceMax, int?CalorieMin, int?CalorieMax)
        {
            this.SearchTerms = SearchTerms;
            this.Category    = Category;
            this.PriceMin    = PriceMin;
            this.PriceMax    = PriceMax;
            this.CalorieMin  = CalorieMin;
            this.CalorieMax  = CalorieMax;
            Entrees          = Menu.Entrees();
            Sides            = Menu.Sides();
            Drinks           = Menu.Drinks();

            if (SearchTerms != null && SearchTerms != "")
            {
                string[] array = SearchTerms.Split(' ');
                int      count = 0;
                foreach (string k in array)
                {
                    array[count] = k.ToLower();
                    count++;
                }

                Entrees = Entrees.Where(entree => Entrees.ToString() != null && (entree.ToString().Contains(SearchTerms, StringComparison.OrdinalIgnoreCase) || array.Any(entree.Description.ToLower().Contains)));
                Sides   = Sides.Where(side => Sides.ToString() != null && (side.ToString().Contains(SearchTerms, StringComparison.OrdinalIgnoreCase) || array.Any(side.Description.ToLower().Contains)));
                Drinks  = Drinks.Where(drink => Drinks.ToString() != null && (drink.ToString().Contains(SearchTerms, StringComparison.OrdinalIgnoreCase) || array.Any(drink.Description.ToLower().Contains)));
            }

            if (Category.Count() != 0)
            {
                bool[] cont = new bool[3];

                foreach (string item in Category)
                {
                    switch (item)
                    {
                    case "Entree":
                        cont[0] = true;
                        break;

                    case "Side":
                        cont[1] = true;
                        break;

                    case "Drink":
                        cont[2] = true;
                        break;
                    }
                }
                if (!cont[0])
                {
                    Entrees = new List <IOrderItem>();
                }
                if (!cont[1])
                {
                    Sides = new List <IOrderItem>();
                }
                if (!cont[2])
                {
                    Drinks = new List <IOrderItem>();
                }
            }

            ///?PriceMin=0&PriceMax=1&Category=Side&CalorieMin=0&CalorieMax=100&SearchTerms=vokun

            if (CalorieMin != null && CalorieMax == null)
            {
                Entrees = Entrees.Where(entree => entree.Calories >= CalorieMin);
                Sides   = Sides.Where(side => side.Calories >= CalorieMin);
                Drinks  = Drinks.Where(drink => drink.Calories >= CalorieMin);
            }

            if (CalorieMin == null && CalorieMax != null)
            {
                Entrees = Entrees.Where(entree => entree.Calories <= CalorieMax);
                Sides   = Sides.Where(side => side.Calories <= CalorieMax);
                Drinks  = Drinks.Where(drink => drink.Calories <= CalorieMax);
            }

            if (CalorieMin != null && CalorieMax != null)
            {
                Entrees = Entrees.Where(entree => entree.Calories >= CalorieMin && entree.Calories <= CalorieMax);
                Sides   = Sides.Where(side => side.Calories >= CalorieMin && side.Calories <= CalorieMax);
                Drinks  = Drinks.Where(drink => drink.Calories >= CalorieMin && drink.Calories <= CalorieMax);
            }

            if (PriceMin != null && PriceMax == null)
            {
                Entrees = Entrees.Where(entree => entree.Price >= PriceMin);
                Sides   = Sides.Where(side => side.Price >= PriceMin);
                Drinks  = Drinks.Where(drink => drink.Price >= PriceMin);
            }

            if (PriceMin == null && PriceMax != null)
            {
                Entrees = Entrees.Where(entree => entree.Price <= PriceMax);
                Sides   = Sides.Where(side => side.Price <= PriceMax);
                Drinks  = Drinks.Where(drink => drink.Price <= PriceMax);
            }

            if (PriceMin != null && PriceMax != null)
            {
                Entrees = Entrees.Where(entree => entree.Price >= PriceMin && entree.Price <= PriceMax);
                Sides   = Sides.Where(side => side.Price >= PriceMin && side.Price <= PriceMax);
                Drinks  = Drinks.Where(drink => drink.Price >= PriceMin && drink.Price <= PriceMax);
            }

            Entrees = Entrees.ToList();
            Sides   = Sides.ToList();
            Drinks  = Drinks.ToList();

            /*
             * Entrees = Menu.Search(Entrees, SearchTerms);
             * Sides = Menu.Search(Sides, SearchTerms);
             * Drinks = Menu.Search(Drinks, SearchTerms);
             *
             * Entrees = Menu.FilterByCategory(Entrees, Category);
             * Sides = Menu.FilterByCategory(Sides, Category);
             * Drinks = Menu.FilterByCategory(Drinks, Category);
             *
             * Entrees = Menu.FilterByCalories(Entrees, CalorieMin, CalorieMax);
             * Sides = Menu.FilterByCalories(Sides, CalorieMin, CalorieMax);
             * Drinks = Menu.FilterByCalories(Drinks, CalorieMin, CalorieMax);
             *
             * Entrees = Menu.FilterByPrice(Entrees, PriceMin, PriceMax);
             * Sides = Menu.FilterByPrice(Sides, PriceMin, PriceMax);
             * Drinks = Menu.FilterByPrice(Drinks, PriceMin, PriceMax);*/
        }
Exemple #8
0
        /// <summary>
        /// filters the items when the page is sent a request
        /// </summary>
        /// <param name="SearchTerms"></param>
        /// <param name="OrderTypes"></param>
        /// <param name="calMin"></param>
        /// <param name="calMax"></param>
        /// <param name="priceMin"></param>
        /// <param name="priceMax"></param>
        public void OnGet(string SearchTerms, string[] OrderTypes, int?calMin, int?calMax, double?priceMin, double?priceMax)

        {
            if (SearchTerms != null)
            {
                string[] words = SearchTerms.Split(' ');
                for (int i = 0; i < words.Length; i++)
                {
                    words[i] = words[i].ToLower();
                }


                //Entrees = Menu.Entrees().Where(item =>  item.ToString().Contains(SearchTerms, StringComparison.InvariantCultureIgnoreCase));
                Entrees = Menu.Entrees().Where(item => words.Any(item.ToString().ToLower().Contains) || words.Any(item.Description.ToLower().Contains));
                Drinks  = Menu.Drinks().Where(item => words.Any(item.ToString().ToLower().Contains) || words.Any(item.Description.ToLower().Contains));
                Sides   = Menu.Sides().Where(item => words.Any(item.ToString().ToLower().Contains) || words.Any(item.Description.ToLower().Contains));

                // Drinks = Menu.Drinks().Where(item => item.ToString().Contains(SearchTerms, StringComparison.InvariantCultureIgnoreCase));

                // Sides = Menu.Sides().Where(item => item.ToString().Contains(SearchTerms, StringComparison.InvariantCultureIgnoreCase));
                //DO MULTIPLE WORDS AND DESCRIPTION
            }

            if (OrderTypes != null && OrderTypes.Length != 0)
            {
                Entrees = Entrees.Where(item =>
                                        item.Type != null &&
                                        OrderTypes.Contains(item.Type)
                                        );

                Drinks = Drinks.Where(item =>
                                      item.Type != null &&
                                      OrderTypes.Contains(item.Type)
                                      );

                Sides = Sides.Where(item =>
                                    item.Type != null &&
                                    OrderTypes.Contains(item.Type)
                                    );
            }

            if (calMin != null && calMax != null)
            {
                Entrees = Entrees.Where(item =>
                                        item.Calories >= calMin &&
                                        item.Calories <= calMax

                                        );
                Drinks = Drinks.Where(item =>
                                      item.Calories >= calMin &&
                                      item.Calories <= calMax

                                      );
                Sides = Sides.Where(item =>
                                    item.Calories >= calMin &&
                                    item.Calories <= calMax

                                    );
            }

            if (priceMin != null && priceMax != null)
            {
                Entrees = Entrees.Where(item =>
                                        item.Price >= priceMin &&
                                        item.Price <= priceMax

                                        );
                Drinks = Drinks.Where(item =>
                                      item.Price >= priceMin &&
                                      item.Price <= priceMax

                                      );
                Sides = Sides.Where(item =>
                                    item.Price >= priceMin &&
                                    item.Price <= priceMax

                                    );
            }


            //Entrees = Menu.Search(Menu.Entrees(),SearchTerms);
            //Drinks = Menu.Search(Menu.Drinks(), SearchTerms);
            //Sides = Menu.Search(Menu.Sides(), SearchTerms);

            //Entrees = Menu.FilterByCategory(Entrees, OrderTypes);
            //Drinks = Menu.FilterByCategory(Drinks, OrderTypes);
            //Sides = Menu.FilterByCategory(Sides, OrderTypes);

            //Entrees = Menu.FilterByCalories(Entrees, calMin, calMax);
            //Drinks = Menu.FilterByCalories(Drinks, calMin, calMax);
            //Sides = Menu.FilterByCalories(Sides, calMin, calMax);

            //Entrees = Menu.FilterByPrice(Entrees, priceMin, priceMax);
            //Drinks = Menu.FilterByPrice(Drinks, priceMin, priceMax);

            //Sides = Menu.FilterByPrice(Sides, priceMin, priceMax);
        }
Exemple #9
0
        internal async Task <WorkPreview> PreviewAsync(IPrinter printer)
        {
            void PrintSide(ISideRunner si)
            {
                printer.Foreach($"Side '{si.Definition.Name}' {(si.Definition.IsMaster ? "(MASTER)" : "")}:", si.SubSides, s => PrintSide(s));
            }

            using (printer.Indent($"Work '{Definition.Name}'"))
            {
                // Get master side
                var masters = Sides.Where(s => s.Definition.IsMaster);
                if (masters.Count() != 1)
                {
                    throw new ArgumentException($"One, and only one '{nameof(ISide)}' must be the master side");
                }
                MasterSide = masters.Single();

                // Determine what sides are sub-sides of others
                void PopulateSubSides(ISideRunner side)
                {
                    side.SubSides = Sides.Where(s => s.GetSourceType() == side.GetItemType()).ToList();
                    foreach (var s in side.SubSides)
                    {
                        if (side.Definition.IsMaster)
                        {
                            s.Definition.IsMaster = true;
                        }
                        PopulateSubSides(s);
                    }
                }

                var rootSides = Sides.Where(s => !Sides.Any(s2 => s2.GetItemType() == s.GetSourceType())).OrderByDescending(s => s.Definition.IsMaster).ThenBy(s => s.Definition.Name).ToList();
                foreach (var side in rootSides)
                {
                    PopulateSubSides(side);
                }
                printer.Foreach("Sides tree:", rootSides, side =>
                {
                    PrintSide(side);
                });

                // Search for comparators for any side with master side
                void SearchComparator(ISideRunner side)
                {
                    var cc = Comparators.Where(c =>
                    {
                        var mts = MasterSide.GetAllItemsType();
                        var st  = side.GetItemType();
                        var ct  = c.GetItemTypes();
                        return((mts.Contains(ct.Item1) && ct.Item2 == st) || (mts.Contains(ct.Item2) && ct.Item1 == st));
                    }).Cast <IComparatorRunner>();

                    if (cc.Count() != 1)
                    {
                        throw new ArgumentException($"One, and only one '{nameof(ISide)}' must be added for master side '{MasterSide.Definition.Name}' and each side");
                    }
                    side.Comparator = cc.Single();
                    printer.WriteLine($"Comparator for side '{side.Definition.Name}' is '{side.Comparator.GetItemTypes().Item1.Name}' <> '{side.Comparator.GetItemTypes().Item2.Name}'");
                    foreach (var subSide in side.SubSides)
                    {
                        Sides.Where(s => s.GetSourceType() == subSide.GetItemType());
                        SearchComparator(subSide);
                    }
                }

                // Iterate non master sides to search for a comparator for they
                printer.Foreach("Comparators: ", rootSides.Where(s => !s.Definition.IsMaster), side => SearchComparator(side));

                // Load sides
                using (printer.Indent($"Loading sides {(Definition.LoadSidesInParallel ? "in parallel" : "sequentially")} ..."))
                {
                    if (Definition.LoadSidesInParallel)
                    {
                        await Task.WhenAll(rootSides.Select(s => s.Load()));
                    }
                    else
                    {
                        await TaskManager.StartNew(async() =>
                        {
                            foreach (var side in rootSides)
                            {
                                await side.Load();
                            }
                        });
                    }
                }

                // Comparing sides
                printer.Foreach("Comparing each side with master side ...", rootSides.Where(s => !s.Definition.IsMaster), sid => {
                    if (sid.Comparator.GetItemTypes().Item1 == MasterSide.GetItemType())
                    {
                        // Master is A in this comparer
                        sid.Results = sid.Comparator.CompareSides(MasterSide, sid, false, printer);
                    }
                    else
                    {
                        // Master is B in this comparer
                        sid.Results = sid.Comparator.CompareSides(sid, MasterSide, true, printer);
                    }
                });
                printer.WriteLine("Analyzing results ...");
                ICollection <IItemRunner> AnalyzeResults(ICollection <ISideRunner> sides)
                {
                    var res = new List <IItemRunner>();

                    // Group side results by item key and populate with sides results
                    foreach (var gro in sides
                             .SelectMany(side => side.Results.Select(result => new
                    {
                        Key = result.Key,
                        MasterRunner = side.SearchMasterSubSide(MasterSide),
                        MasterItemType = side.SearchMasterSubSide(MasterSide).GetItemType(),
                        MasterItem = result.MasterItem,
                        MasterItemName = side.SearchMasterSubSide(MasterSide).GetItemName(result.MasterItem),
                        MasterItemTag = side.SearchMasterSubSide(MasterSide).GetItemTag(result.MasterItem),
                        //SideId = side.Id,
                        Side = side,
                        SideItemType = side.GetItemType(),
                        SideItem = result.SideItem,
                        SideItemName = side.GetItemName(result.SideItem),
                        SideItemTag = side.GetItemTag(result.SideItem),
                        SideName = side.Definition.Name,
                        SideSubSides = result.SubSides,
                        Properties = result.Properties.ToArray()
                    }))
                             .GroupBy(r => r.Key))
                    {
                        // Create item
                        var fir      = gro.First(); // Use first element to get master info, all items in this group has the same master item
                        var itemType = typeof(ItemRunner <>).MakeGenericType(fir.MasterItemType);
                        var item     = (IItemRunner)Activator.CreateInstance(itemType, fir.MasterRunner, fir.MasterItem, fir.MasterItemName, fir.MasterItemTag);
                        foreach (var i in gro)
                        {
                            // Create side
                            var sideItemType = typeof(ItemSideRunner <,>).MakeGenericType(i.SideItemType, i.Key.GetType());
                            var sideItem     = (IItemSideRunner)Activator.CreateInstance(sideItemType, i.Side, i.SideName, i.Key, i.SideItem, i.SideItemName, i.SideItemTag);
                            foreach (var pro in i.Properties)
                            {
                                ((IList <IPropertyRunner>)sideItem.Properties).Add(pro);
                            }
                            sideItem.SubItems = AnalyzeResults(i.SideSubSides);
                            // Add side to item
                            ((IList <IItemSideRunner>)item.SideRunners).Add(sideItem);
                        }
                        // Add item to work
                        res.Add(item);
                    }
                    return(res);
                }

                foreach (var item in AnalyzeResults(rootSides.Where(side => !side.Definition.IsMaster).ToList()))
                {
                    Items.Add(item);
                }

                // Create preview response
                printer.WriteLine("Creating preview result ...");
                var preWork = new WorkPreview(Definition.Id);
                preWork.Name           = Definition.Name;
                preWork.MasterSideName = MasterSide.Definition.Name;
                var preItems = new List <ItemPreview>();
                foreach (var item in Items)
                {
                    var preItem = new ItemPreview(preWork, item.Id);
                    preItem.MasterItemExist        = item.MasterItem != null;
                    preItem.MasterItemName         = item.MasterItemName;
                    preItem.MasterItemTag          = item.MasterItemTag;
                    preItem.SingularMasterTypeName = MasterSide.Definition.SingularItemTypeName;
                    preItem.PluralMasterTypeName   = MasterSide.Definition.PluralItemTypeName;
                    preItem.MasterTypeIsMale       = MasterSide.Definition.ItemTypeIsMale;

                    var preSides = new List <ItemSidePreview>();
                    foreach (var side in item.SideRunners)
                    {
                        var preSide = new ItemSidePreview(preItem, side.Side.Id);
                        preSide.Key                  = side.Key.ToString();
                        preSide.SideAllowInsert      = side.Side.Definition.AllowInsert;
                        preSide.SideAllowDelete      = side.Side.Definition.AllowDelete;
                        preSide.SideAllowUpdate      = side.Side.Definition.AllowUpdate;
                        preSide.SideItemExist        = side.SideItem != null;
                        preSide.SideItemName         = side.SideItemName;
                        preSide.SideItemTag          = side.SideItemTag;
                        preSide.SingularSideTypeName = side.Side.Definition.SingularItemTypeName;
                        preSide.PluralSideTypeName   = side.Side.Definition.PluralItemTypeName;
                        preSide.ItemTypeIsMale       = side.Side.Definition.ItemTypeIsMale;
                        preSide.SideName             = side.Name;
                        foreach (var pro in side.Properties)
                        {
                            var prePro = new PropertyPreview(preSide);
                            prePro.MasterValue  = pro.MasterNamingFunction(pro.MasterValue);
                            prePro.SideValue    = pro.SideNamingFunction(pro.SideValue);
                            prePro.PropertyName = pro.PropertyName;
                            preSide.Properties.Add(prePro);
                        }
                        ICollection <ItemRelationPreview> ProcessSubItems(object parent, ICollection <IItemRunner> items)
                        {
                            var res = new List <ItemRelationPreview>();

                            foreach (var i in items)
                            {
                                ItemRelationPreview rel;
                                if (parent is ItemSidePreview)
                                {
                                    rel = new ItemRelationPreview(parent as ItemSidePreview, i.Id);
                                }
                                else
                                {
                                    rel = new ItemRelationPreview(parent as ItemRelationPreview, i.Id);
                                }
                                rel.SideAllowInsert        = i.SideRunners.Single().Side.Definition.AllowInsert;
                                rel.SideAllowDelete        = i.SideRunners.Single().Side.Definition.AllowDelete;
                                rel.SideAllowUpdate        = i.SideRunners.Single().Side.Definition.AllowUpdate;
                                rel.MasterItemExist        = i.MasterItem != null;
                                rel.MasterItemName         = i.MasterItemName;
                                rel.MasterItemTag          = i.MasterItemTag;
                                rel.SingularMasterTypeName = i.MasterRunner.Definition.SingularItemTypeName;
                                rel.PluralMasterTypeName   = i.MasterRunner.Definition.PluralItemTypeName;
                                rel.SingularSideTypeName   = i.SideRunners.Single().Side.Definition.SingularItemTypeName;
                                rel.PluralSideTypeName     = i.SideRunners.Single().Side.Definition.PluralItemTypeName;
                                var subSide = i.SideRunners.Single();
                                rel.Key           = subSide.Key.ToString();
                                rel.SideItemExist = subSide.SideItem != null;
                                rel.SideItemName  = subSide.SideItemName;
                                rel.SideItemTag   = subSide.SideItemTag;
                                rel.SideName      = subSide.Name;
                                foreach (var pro in subSide.Properties)
                                {
                                    var prePro = new PropertyPreview(rel);
                                    prePro.MasterValue  = pro.MasterNamingFunction(pro.MasterValue);
                                    prePro.SideValue    = pro.SideNamingFunction(pro.SideValue);
                                    prePro.PropertyName = pro.PropertyName;
                                    rel.Properties.Add(prePro);
                                }
                                rel.Relations = ProcessSubItems(rel, subSide.SubItems);
                                res.Add(rel);
                            }
                            return(res);
                        }

                        preSide.Relations = ProcessSubItems(preSide, side.SubItems);
                        preSides.Add(preSide);
                    }
                    preItem.Sides = preSides;
                    preItems.Add(preItem);
                }
                preWork.Items = preItems;

                // Check result and suggest an action
                printer.WriteLine("Determining default actions ...");
                foreach (var item in preWork.Items)
                {
                    foreach (var side in item.Sides)
                    {
                        if (!item.MasterItemExist && side.SideAllowDelete)
                        {
                            side.Action = SynchronizationAction.Delete;
                        }
                        else if (!side.SideItemExist && side.SideAllowInsert)
                        {
                            side.Action = SynchronizationAction.Insert;
                        }
                        else if (side.Properties.Count() > 0 && side.SideAllowUpdate)
                        {
                            side.Action = SynchronizationAction.Update;
                        }
                        void ProcessRelations(ICollection <ItemRelationPreview> relations)
                        {
                            foreach (var rel in relations)
                            {
                                if (!rel.MasterItemExist && rel.SideAllowDelete)
                                {
                                    rel.Action = SynchronizationAction.Delete;
                                }
                                else if (!rel.SideItemExist && rel.SideAllowInsert)
                                {
                                    rel.Action = SynchronizationAction.Insert;
                                }
                                else if (rel.Properties.Count() > 0 && rel.SideAllowUpdate)
                                {
                                    rel.Action = SynchronizationAction.Update;
                                }
                                ProcessRelations(rel.Relations);
                            }
                        }

                        ProcessRelations(side.Relations);
                    }
                }
                return(preWork);
            }
            //return printer.IndentAsync($"Work '{Definition.Name}'", async () =>
            //{
            //    // Get master side
            //    var masters = Sides.Where(s => s.Definition.IsMaster);
            //    if (masters.Count() != 1) throw new ArgumentException($"One, and only one '{nameof(ISide)}' must be the master side");
            //    MasterSide = masters.Single();

            //    // Determine what sides are sub-sides of others
            //    void PopulateSubSides(ISideRunner side)
            //    {
            //        side.SubSides = Sides.Where(s => s.GetSourceType() == side.GetItemType()).ToList();
            //        foreach (var s in side.SubSides)
            //        {
            //            if (side.Definition.IsMaster) s.Definition.IsMaster = true;
            //            PopulateSubSides(s);
            //        }
            //    }
            //    var rootSides = Sides.Where(s => !Sides.Any(s2 => s2.GetItemType() == s.GetSourceType())).OrderByDescending(s => s.Definition.IsMaster).ThenBy(s => s.Definition.Name).ToList();
            //    foreach (var side in rootSides)
            //        PopulateSubSides(side);
            //    printer.Foreach("Sides tree:", rootSides, side =>
            //    {
            //        PrintSide(side);
            //    });

            //    // Search for comparators for any side with master side
            //    void SearchComparator(ISideRunner side)
            //    {
            //        var cc = Comparators.Where(c =>
            //        {
            //            var mts = MasterSide.GetAllItemsType();
            //            var st = side.GetItemType();
            //            var ct = c.GetItemTypes();
            //            return (mts.Contains(ct.Item1) && ct.Item2 == st) || (mts.Contains(ct.Item2) && ct.Item1 == st);
            //        }).Cast<IComparatorRunner>();
            //        if (cc.Count() != 1) throw new ArgumentException($"One, and only one '{nameof(ISide)}' must be added for master side '{MasterSide.Definition.Name}' and each side");
            //        side.Comparator = cc.Single();
            //        printer.WriteLine($"Comparator for side '{side.Definition.Name}' is '{side.Comparator.GetItemTypes().Item1.Name}' <> '{side.Comparator.GetItemTypes().Item2.Name}'");
            //        foreach (var subSide in side.SubSides)
            //        {
            //            Sides.Where(s => s.GetSourceType() == subSide.GetItemType());
            //            SearchComparator(subSide);
            //        }
            //    }
            //    // Iterate non master sides to search for a comparator for they
            //    printer.Foreach("Comparators: ", rootSides.Where(s => !s.Definition.IsMaster), side => SearchComparator(side));

            //    // Load sides
            //    await printer.IndentAsync($"Loading sides {(Definition.LoadSidesInParallel ? "in parallel" : "sequentially")} ...", () =>
            //    {
            //        if (Definition.LoadSidesInParallel)
            //        {
            //            return Task.WhenAll(rootSides.Select(s => s.Load()));
            //        }else
            //        {
            //            return TaskManager.StartNew(async () =>
            //            {
            //                foreach (var side in rootSides)
            //                {
            //                    await side.Load();
            //                }
            //            });
            //        }
            //    });

            //    // Comparing sides
            //    printer.Foreach("Comparing each side with master side ...", rootSides.Where(s => !s.Definition.IsMaster), sid=> {
            //        if (sid.Comparator.GetItemTypes().Item1 == MasterSide.GetItemType())
            //        {
            //            // Master is A in this comparer
            //            sid.Results = sid.Comparator.CompareSides(MasterSide, sid, false, printer);
            //        }
            //        else
            //        {
            //            // Master is B in this comparer
            //            sid.Results = sid.Comparator.CompareSides(sid, MasterSide, true, printer);
            //        }
            //    });
            //    printer.WriteLine("Analyzing results ...");
            //    ICollection<IItemRunner> AnalyzeResults(ICollection<ISideRunner> sides)
            //    {
            //        var res = new List<IItemRunner>();
            //        // Group side results by item key and populate with sides results
            //        foreach (var gro in sides
            //            .SelectMany(side => side.Results.Select(result => new
            //            {
            //                Key = result.Key,
            //                MasterRunner = side.SearchMasterSubSide(MasterSide),
            //                MasterItemType = side.SearchMasterSubSide(MasterSide).GetItemType(),
            //                MasterItem = result.MasterItem,
            //                MasterItemName = side.SearchMasterSubSide(MasterSide).GetItemName(result.MasterItem),
            //                MasterItemTag = side.SearchMasterSubSide(MasterSide).GetItemTag(result.MasterItem),
            //                //SideId = side.Id,
            //                Side = side,
            //                SideItemType = side.GetItemType(),
            //                SideItem = result.SideItem,
            //                SideItemName = side.GetItemName(result.SideItem),
            //                SideItemTag = side.GetItemTag(result.SideItem),
            //                SideName = side.Definition.Name,
            //                SideSubSides = result.SubSides,
            //                Properties = result.Properties.ToArray()
            //            }))
            //            .GroupBy(r => r.Key))
            //        {
            //            // Create item
            //            var fir = gro.First(); // Use first element to get master info, all items in this group has the same master item
            //            var itemType = typeof(ItemRunner<>).MakeGenericType(fir.MasterItemType);
            //            var item = (IItemRunner)Activator.CreateInstance(itemType, fir.MasterRunner, fir.MasterItem, fir.MasterItemName, fir.MasterItemTag);
            //            foreach (var i in gro)
            //            {
            //                // Create side
            //                var sideItemType = typeof(ItemSideRunner<,>).MakeGenericType(i.SideItemType, i.Key.GetType());
            //                var sideItem = (IItemSideRunner)Activator.CreateInstance(sideItemType, i.Side, i.SideName, i.Key, i.SideItem, i.SideItemName, i.SideItemTag);
            //                foreach (var pro in i.Properties)
            //                    ((IList<IPropertyRunner>)sideItem.Properties).Add(pro);
            //                sideItem.SubItems = AnalyzeResults(i.SideSubSides);
            //                // Add side to item
            //                ((IList<IItemSideRunner>)item.SideRunners).Add(sideItem);
            //            }
            //            // Add item to work
            //            res.Add(item);
            //        }
            //        return res;
            //    }
            //    foreach (var item in AnalyzeResults(rootSides.Where(side => !side.Definition.IsMaster).ToList())) Items.Add(item);

            //    // Create preview response
            //    printer.WriteLine("Creating preview result ...");
            //    var preWork = new WorkPreview(Definition.Id);
            //    preWork.Name = Definition.Name;
            //    preWork.MasterSideName = MasterSide.Definition.Name;
            //    var preItems = new List<ItemPreview>();
            //    foreach (var item in Items)
            //    {
            //        var preItem = new ItemPreview(preWork, item.Id);
            //        preItem.MasterItemExist = item.MasterItem != null;
            //        preItem.MasterItemName = item.MasterItemName;
            //        preItem.MasterItemTag = item.MasterItemTag;
            //        preItem.SingularMasterTypeName = MasterSide.Definition.SingularItemTypeName;
            //        preItem.PluralMasterTypeName = MasterSide.Definition.PluralItemTypeName;
            //        preItem.MasterTypeIsMale = MasterSide.Definition.ItemTypeIsMale;

            //        var preSides = new List<ItemSidePreview>();
            //        foreach (var side in item.SideRunners)
            //        {
            //            var preSide = new ItemSidePreview(preItem, side.Side.Id);
            //            preSide.Key = side.Key.ToString();
            //            preSide.SideAllowInsert = side.Side.Definition.AllowInsert;
            //            preSide.SideAllowDelete = side.Side.Definition.AllowDelete;
            //            preSide.SideAllowUpdate = side.Side.Definition.AllowUpdate;
            //            preSide.SideItemExist = side.SideItem != null;
            //            preSide.SideItemName = side.SideItemName;
            //            preSide.SideItemTag = side.SideItemTag;
            //            preSide.SingularSideTypeName = side.Side.Definition.SingularItemTypeName;
            //            preSide.PluralSideTypeName = side.Side.Definition.PluralItemTypeName;
            //            preSide.ItemTypeIsMale = side.Side.Definition.ItemTypeIsMale;
            //            preSide.SideName = side.Name;
            //            foreach (var pro in side.Properties)
            //            {
            //                var prePro = new PropertyPreview(preSide);
            //                prePro.MasterValue = pro.MasterNamingFunction(pro.MasterValue);
            //                prePro.SideValue = pro.SideNamingFunction(pro.SideValue);
            //                prePro.PropertyName = pro.PropertyName;
            //                preSide.Properties.Add(prePro);
            //            }
            //            ICollection<ItemRelationPreview> ProcessSubItems(object parent, ICollection<IItemRunner> items)
            //            {
            //                var res = new List<ItemRelationPreview>();
            //                foreach (var i in items)
            //                {
            //                    ItemRelationPreview rel;
            //                    if (parent is ItemSidePreview)
            //                        rel = new ItemRelationPreview(parent as ItemSidePreview, i.Id);
            //                    else
            //                        rel = new ItemRelationPreview(parent as ItemRelationPreview, i.Id);
            //                    rel.SideAllowInsert = i.SideRunners.Single().Side.Definition.AllowInsert;
            //                    rel.SideAllowDelete = i.SideRunners.Single().Side.Definition.AllowDelete;
            //                    rel.SideAllowUpdate = i.SideRunners.Single().Side.Definition.AllowUpdate;
            //                    rel.MasterItemExist = i.MasterItem != null;
            //                    rel.MasterItemName = i.MasterItemName;
            //                    rel.MasterItemTag = i.MasterItemTag;
            //                    rel.SingularMasterTypeName = i.MasterRunner.Definition.SingularItemTypeName;
            //                    rel.PluralMasterTypeName = i.MasterRunner.Definition.PluralItemTypeName;
            //                    rel.SingularSideTypeName = i.SideRunners.Single().Side.Definition.SingularItemTypeName;
            //                    rel.PluralSideTypeName = i.SideRunners.Single().Side.Definition.PluralItemTypeName;
            //                    var subSide = i.SideRunners.Single();
            //                    rel.Key = subSide.Key.ToString();
            //                    rel.SideItemExist = subSide.SideItem != null;
            //                    rel.SideItemName = subSide.SideItemName;
            //                    rel.SideItemTag = subSide.SideItemTag;
            //                    rel.SideName = subSide.Name;
            //                    foreach (var pro in subSide.Properties)
            //                    {
            //                        var prePro = new PropertyPreview(rel);
            //                        prePro.MasterValue = pro.MasterNamingFunction(pro.MasterValue);
            //                        prePro.SideValue = pro.SideNamingFunction(pro.SideValue);
            //                        prePro.PropertyName = pro.PropertyName;
            //                        rel.Properties.Add(prePro);
            //                    }
            //                    rel.Relations = ProcessSubItems(rel, subSide.SubItems);
            //                    res.Add(rel);
            //                }
            //                return res;
            //            }
            //            preSide.Relations = ProcessSubItems(preSide, side.SubItems);
            //            preSides.Add(preSide);
            //        }
            //        preItem.Sides = preSides;
            //        preItems.Add(preItem);
            //    }
            //    preWork.Items = preItems;

            //    // Check result and suggest an action
            //    printer.WriteLine("Determining default actions ...");
            //    foreach (var item in preWork.Items)
            //    {
            //        foreach (var side in item.Sides)
            //        {
            //            if (!item.MasterItemExist && side.SideAllowDelete)
            //                side.Action = SynchronizationAction.Delete;
            //            else if (!side.SideItemExist && side.SideAllowInsert)
            //                side.Action = SynchronizationAction.Insert;
            //            else if (side.Properties.Count() > 0 && side.SideAllowUpdate)
            //                side.Action = SynchronizationAction.Update;
            //            void ProcessRelations(ICollection<ItemRelationPreview> relations)
            //            {
            //                foreach (var rel in relations)
            //                {
            //                    if (!rel.MasterItemExist && rel.SideAllowDelete)
            //                        rel.Action = SynchronizationAction.Delete;
            //                    else if (!rel.SideItemExist && rel.SideAllowInsert)
            //                        rel.Action = SynchronizationAction.Insert;
            //                    else if (rel.Properties.Count() > 0 && rel.SideAllowUpdate)
            //                        rel.Action = SynchronizationAction.Update;
            //                    ProcessRelations(rel.Relations);
            //                }
            //            }
            //            ProcessRelations(side.Relations);
            //        }
            //    }
            //    return preWork;
            //});
        }