private bool GetFeastStatus(RdfGraphContainer graphContainer, string pageTitle)
        {
            Triple tripleItemType = graphContainer.GetGraph().Triples.Where(x => x.Nodes.Any(y => y.NodeType == NodeType.Uri && ((UriNode)y).Uri.ToString().EndsWith("Property-3AHas_item_type"))).FirstOrDefault();

            if (tripleItemType != null &&
                tripleItemType.Object is LiteralNode &&
                ((LiteralNode)tripleItemType.Object).Value.Contains("Feast", StringComparison.OrdinalIgnoreCase))
            {
                return(true);
            }
            return(false);
        }
        /// <summary>
        /// Resolves a Feast
        /// </summary>
        /// <param name="pageTitle"></param>
        /// <param name="graphContainer"></param>
        /// <returns></returns>
        private async Task <Food> ResolveFeast(string pageTitle, RdfGraphContainer graphContainer)
        {
            int    recipeId;
            string ingredientName = null;


            //Parsing Feasts
            Triple tripleItemType = graphContainer.GetGraph().Triples.Where(x => x.Nodes.Any(y => y.NodeType == NodeType.Uri && ((UriNode)y).Uri.ToString().EndsWith("Property-3AHas_item_type"))).FirstOrDefault();

            if (tripleItemType != null &&
                tripleItemType.Object is LiteralNode &&
                ((LiteralNode)tripleItemType.Object).Value.Contains("Feast", StringComparison.OrdinalIgnoreCase))
            {
                _log.Info($"{pageTitle} has item type: Feast - trying to resolve");

                Triple tripleRecipeId = graphContainer.GetGraph().Triples.Where(x => x.Nodes.Any(y => y.NodeType == NodeType.Uri && ((UriNode)y).Uri.ToString().EndsWith("Property-3AHas_recipe_id"))).FirstOrDefault();

                if (tripleRecipeId != null &&
                    tripleRecipeId.Object is LiteralNode &&
                    int.TryParse(((LiteralNode)tripleRecipeId.Object).Value, out recipeId))
                {
                    try
                    {
                        ingredientName = await ApiWrapper.Instance.GetSingleIngredientNameForRecipeId(recipeId);
                    }
                    catch (Gw2Sharp.WebApi.Http.NotFoundException)
                    {
                        _log.Error($"Could not resolve recipe for {recipeId}");
                    }

                    if (!string.IsNullOrEmpty(ingredientName))
                    {
                        (string ingredientPageTitle, string ingredientPageContent) = await WikiWrapper.Instance.GetPageContent(ingredientName);

                        RdfGraphContainer ingredientGraphContainer = WikiWrapper.Instance.GetRdfGraph(ingredientPageTitle);
                        return(await ParseFood(ingredientPageTitle, ingredientPageContent, ingredientGraphContainer));
                    }
                    else
                    {
                        _log.Warn($"Ingredient/Recipe could not be resolved for {pageTitle}");
                    }
                }
            }
            return(null);
        }
        private int GetDuration(RdfGraphContainer graph, string pageTitle)
        {
            int    duration;
            Triple tripleDuration = graph.GetGraph().Triples.Where(x => x.Nodes.Any(y => y.NodeType == NodeType.Uri && ((UriNode)y).Uri.ToString().EndsWith("Property-3AHas_nourishment_duration"))).FirstOrDefault();

            if (tripleDuration != null &&
                tripleDuration.Object is LiteralNode)
            {
                string value = ((LiteralNode)tripleDuration.Object).Value;
                Regex  regex = new Regex(@"((\\+|\\-)* *([0-9]+ *))");

                if (regex.IsMatch(value) &&
                    int.TryParse(regex.Match(value).Value, out duration))
                {
                    if (value.Trim().EndsWith("m"))
                    {
                        return((int)TimeSpan.FromMinutes(duration).TotalSeconds);
                    }
                    else if (value.Trim().EndsWith("h"))
                    {
                        return((int)TimeSpan.FromHours(duration).TotalSeconds);
                    }
                    else
                    {
                        throw new InvalidFoodDurationException(pageTitle);
                    }
                }
                else
                {
                    throw new InvalidFoodDurationException(pageTitle);
                }
            }
            else
            {
                throw new InvalidFoodDurationException(pageTitle);
            }
        }
        /// <summary>
        /// Parses the page for food
        /// </summary>
        /// <param name="pageTitle"></param>
        /// <param name="pageContent"></param>
        /// <param name="graphContainer"></param>
        /// <returns></returns>
        private async Task <Food> ParseFood(string pageTitle, string pageContent, RdfGraphContainer graphContainer)
        {
            Food food = null;
            int  id;

            try
            {
                Triple tripleNourishmentBonus = graphContainer.GetGraph().Triples.Where(x => x.Nodes.Any(y => y.NodeType == NodeType.Uri && ((UriNode)y).Uri.ToString().EndsWith("Property-3AHas_nourishment_bonus"))).FirstOrDefault();
                Triple tripleId = graphContainer.GetGraph().Triples.Where(x => x.Nodes.Any(y => y.NodeType == NodeType.Uri && ((UriNode)y).Uri.ToString().EndsWith("Property-3AHas_game_id"))).FirstOrDefault();

                //Page RDF information has Nourishment Bonus and ID
                if (tripleId != null &&
                    tripleId.Object is LiteralNode &&
                    int.TryParse(((LiteralNode)tripleId.Object).Value, out id))
                {
                    if (tripleNourishmentBonus != null &&
                        tripleNourishmentBonus.Object is LiteralNode)
                    {
                        string[] nourishmentBonusLines = ((LiteralNode)tripleNourishmentBonus.Object).Value.Split("<br>", StringSplitOptions.RemoveEmptyEntries);
                        File.AppendAllLines(_allEffectsFile, nourishmentBonusLines, Encoding.UTF8);
                        food = new Food()
                        {
                            Id              = id,
                            Name            = pageTitle,
                            DurationSeconds = GetDuration(graphContainer, pageTitle),
                            IsFeast         = GetFeastStatus(graphContainer, pageTitle)
                        };

                        foreach (string line in nourishmentBonusLines)
                        {
                            FoodEffect effect = FoodEffect.GetEffect(line);
                            food.Effects.Add(effect);
                        }
                    }
                    else
                    {
                        _log.Warn($"{pageTitle}: RDF does not contain Nourishment");

                        Food feastIngredient = await ResolveFeast(pageTitle, graphContainer);

                        if (feastIngredient != null)
                        {
                            food = new Food()
                            {
                                Id              = id,
                                Name            = pageTitle,
                                Effects         = feastIngredient.Effects,
                                IsFeast         = true,
                                DurationSeconds = (int)TimeSpan.FromHours(1).TotalSeconds
                            };
                        }
                        else
                        {
                            _log.Warn($"Feast {pageTitle} could not be resolved");
                            food = null;
                        }
                    }
                }
                else
                {
                    _log.Error($"{pageTitle} does not have ID");
                    food = null;
                }
            }
            catch (InvalidFoodDurationException ex)
            {
                _log.Warn(ex);
                food = null;
            }
            catch (UnmatchedFoodEffectException ex)
            {
                _log.Warn(ex);
                File.AppendAllText(_errorFile, ex.Line + Environment.NewLine, Encoding.UTF8);
                food = null;
            }

            return(food);
        }