/// <summary>
        /// This rule tries to boost the ranking for Mathematics if it appears under multiple attribute types.
        /// If Mathematics appears for both Skills and Knowledge in our result set.
        /// Delete the  lowest ranking one.
        /// Times the rank for the remaining one by 1.1 adds 10%  (this number was as a result of testing the results)
        /// </summary>
        /// <param name="attributes">The attributes.</param>
        /// <returns></returns>
        public IEnumerable <OnetSkill> BoostMathsSkills(IEnumerable <OnetSkill> attributes)
        {
            OnetSkill skillsMaths    = attributes.FirstOrDefault(a => a.Name == MathsTitle && a.Category == CategoryType.Skill);
            OnetSkill knowledgeMaths = attributes.FirstOrDefault(a => a.Name == MathsTitle && a.Category == CategoryType.Knowledge);

            //if we have both remove one
            if (skillsMaths != null && knowledgeMaths != null)
            {
                if (skillsMaths.Score > knowledgeMaths.Score)
                {
                    attributes = attributes.Where(a => a.Name != MathsTitle || a.Category != CategoryType.Knowledge);
                }
                else
                {
                    attributes = attributes.Where(a => a.Name != MathsTitle || a.Category != CategoryType.Skill);
                }

                var attributeList = attributes.ToList();
                for (int ii = 0; ii < attributeList.Count(); ii++)
                {
                    if (attributeList[ii].Name == MathsTitle)
                    {
                        attributeList[ii].Score = attributeList[ii].Score * 1.1m;
                    }
                }
                return(attributeList);
            }
            return(attributes);
        }
        /// <summary>
        /// Some times in our top 20 results set we get attributes that are similar -
        /// We improve user experience by combining similar in the top 20.
        /// Using the combination table we combine simular attributes that are in the top 20 results"
        /// After each combination we need to get a new top 20 of the attributes
        /// </summary>
        /// <param name="attributes"></param>
        /// <returns></returns>
        public IEnumerable <OnetSkill> CombineSimilarAttributes(IList <OnetSkill> attributes)
        {
            var combinations = combinationsQueryRepository.GetAll();

            foreach (var combination in combinations)
            {
                var       topAttributes = SelectTopAttributes(attributes);
                OnetSkill elementOne    = topAttributes.FirstOrDefault(a => a.Id == combination.OnetElementOneId);
                OnetSkill elementTwo    = topAttributes.FirstOrDefault(a => a.Id == combination.OnetElementTwoId);

                //if we have both combine them
                if (elementOne != null && elementTwo != null)
                {
                    var scoreToUse = (elementOne.Score > elementTwo.Score) ? elementOne.Score : elementTwo.Score;

                    attributes = attributes.Where(a => a.Id != elementOne.Id && a.Id != elementTwo.Id).ToList();

                    attributes.Add(new OnetSkill {
                        Name = combination.Title, Category = CategoryType.Combination, Id = combination.CombinedElementId, OnetOccupationalCode = elementOne.OnetOccupationalCode, Score = scoreToUse
                    });
                }
            }
            return(attributes);
        }