예제 #1
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="plan">The plan to get suggestions for, it will be unchanged.</param>
        internal PlanSuggestions(Plan plan)
        {
            m_originalPlan = plan;
            m_plan         = new PlanScratchpad(plan.Character, plan);

            var baseTime = m_plan.TotalTrainingTime;

            using (m_plan.SuspendingEvents())
            {
                // Search for new benefits, in a recursive way (adding new skills change the opportunities for new improvements)
                while (true)
                {
                    bool foundNewBenefits = false;
                    foundNewBenefits |= CheckForTimeBenefit(GetLearningEntries(EveAttribute.Intelligence));
                    foundNewBenefits |= CheckForTimeBenefit(GetLearningEntries(EveAttribute.Perception));
                    foundNewBenefits |= CheckForTimeBenefit(GetLearningEntries(EveAttribute.Willpower));
                    foundNewBenefits |= CheckForTimeBenefit(GetLearningEntries(EveAttribute.Memory));
                    foundNewBenefits |= CheckForTimeBenefit(GetLearningEntries(EveAttribute.Charisma));
                    foundNewBenefits |= CheckForTimeBenefit(GetLearningEntries());
                    if (!foundNewBenefits)
                    {
                        break;
                    }
                }
            }

            // Update the time benefit
            m_timeBenefit = baseTime - m_plan.TotalTrainingTime;
        }
예제 #2
0
        /// <summary>
        /// Try to set the priority of the given entries and cancel if a conflict arises.
        /// </summary>
        /// <param name="entries">The list of entries to change priority of</param>
        /// <param name="priority">The new priority to set</param>
        /// <returns>True when successful, false when a conflict arised.</returns>
        public bool TrySetPriority(PlanScratchpad m_displayPlan, IEnumerable <PlanEntry> entries, int priority)
        {
            // Change priorities and make a backup
            Queue <int> oldPriorities = new Queue <int>();

            foreach (var entry in entries)
            {
                oldPriorities.Enqueue(entry.Priority);
                entry.Priority = priority;
            }

            // We are rebuilding the plan with the new priorities in order to check them
            RebuildPlanFrom(m_displayPlan, true);

            // Check priorities
            if (FixPrioritiesOrder(false, false))
            {
                // Priorities are OK we save them and return
                OnChanged(PlanChange.Notification);
                return(true);
            }

            // Failure, restore the priorities
            foreach (var entry in entries)
            {
                entry.Priority = oldPriorities.Dequeue();
            }

            // We are rebuilding the plan from the old priorities
            RebuildPlanFrom(m_displayPlan, true);

            return(false);
        }
예제 #3
0
        /// <summary>
        /// Check, among the sequence of skills, the number of them to add to get the best training time.
        /// Matched skills are then added to the plan and to the suggestions list.
        /// </summary>
        /// <param name="attribute"></param>
        /// <returns></returns>
        private bool CheckForTimeBenefit(IEnumerable <PlanEntry> entries)
        {
            // Gets the skills which are neither known nor planned
            var entriesToAdd = new List <PlanEntry>();

            foreach (var entry in entries)
            {
                if (entry.CharacterSkill.Level < entry.Level && !m_plan.IsPlanned(entry.Skill, entry.Level))
                {
                    entriesToAdd.Add(entry);
                }
            }

            // Check which is the best level to train
            int entriesCount     = 0;
            int bestEntriesCount = 0;
            var bestTime         = m_plan.TotalTrainingTime;
            var testPlan         = new PlanScratchpad(m_plan.Character, m_plan);

            foreach (var entry in entriesToAdd)
            {
                // Insert the skill at the best position, making sure its prerequisites are trained first.
                entriesCount++;
                testPlan.InsertAtBestPosition(entry.Skill, entry.Level);

                // Compare the new training time with the old one
                TimeSpan newTime = testPlan.TotalTrainingTime;
                if (newTime < bestTime)
                {
                    bestTime         = newTime;
                    bestEntriesCount = entriesCount;
                }
            }

            // Add the suggested entries to the plan and the suggestions list
            entriesCount = 0;
            foreach (var entry in entriesToAdd)
            {
                // Stop when we reached the desired entries count
                if (entriesCount == bestEntriesCount)
                {
                    break;
                }

                entriesCount++;

                m_items.Add(entry);
                m_plan.InsertAtBestPosition(entry.Skill, entry.Level);
            }

            // Returns true if new benefits have been found
            return(bestEntriesCount != 0);
        }
예제 #4
0
        /// <summary>
        /// Removes a set of skill levels from this plan.
        /// </summary>
        /// <param name="skillsToRemove">The skill levels to remove.</param>
        /// <returns>An object allowing to perform and control the removal.</returns>
        public IPlanOperation TryRemoveSet <T>(IEnumerable <T> skillsToRemove)
            where T : ISkillLevel
        {
            var allEntriesToRemove = GetAllEntriesToRemove(skillsToRemove);

            // Creates a plan where the entries and their dependencies have been removed
            var freePlan = new PlanScratchpad(m_character);

            freePlan.RebuildPlanFrom(m_items);
            foreach (var entry in allEntriesToRemove)
            {
                freePlan.Remove(entry);
            }

            // Gather removables prerequisites now useless
            var removablePrerequisites = new List <PlanEntry>();

            foreach (var entryToRemove in allEntriesToRemove)
            {
                foreach (var prereq in m_items)
                {
                    // Skip if this skill was not dependent of the prereq.
                    if (!entryToRemove.IsDependentOf(prereq))
                    {
                        continue;
                    }

                    // Skip if still required
                    if (freePlan.GetMinimumLevel(prereq.Skill) != 0)
                    {
                        continue;
                    }

                    // Add the entry if its type is Prerequisite
                    var prereqEntry = freePlan.GetEntry(prereq.Skill, prereq.Level);
                    if (prereqEntry == null)
                    {
                        continue;
                    }

                    // Adds it as a removable prerequisite
                    if (prereqEntry.Type == PlanEntryType.Prerequisite)
                    {
                        removablePrerequisites.Add(prereqEntry);
                        freePlan.Remove(prereqEntry);
                    }
                }
            }

            // Create the operation
            return(new PlanOperation(this, skillsToRemove.Cast <ISkillLevel>(), allEntriesToRemove, removablePrerequisites));
        }
예제 #5
0
        /// <summary>
        /// Optimize the learning skills order
        /// </summary>
        /// <param name="baseEntries"></param>
        /// <param name="startSP"></param>
        /// <returns></returns>
        private PlanScratchpad OptimizeLearningSkills(IEnumerable <PlanEntry> baseEntries, int startSP)
        {
            var learningPlan = new PlanScratchpad(m_character);
            var entries      = PrepareLearningSkillsInsertionQueue(baseEntries);

            // Insert all the entries in an optimal order
            while (entries.Count != 0)
            {
                // Pops the next level when there is one, quit otherwise
                PlanEntry entry = entries.Dequeue();
                learningPlan.InsertAtBestPosition(entry.Skill, entry.Level);
            }

            return(learningPlan);
        }
예제 #6
0
        /// <summary>
        /// Set the priorities by force, fixing conflicts when required.
        /// </summary>
        /// <param name="entries">The list of entries to change priority of</param>
        /// <param name="priority">The new priority to set</param>
        public void SetPriority(PlanScratchpad m_displayPlan, IEnumerable <PlanEntry> entries, int priority)
        {
            // Change priorities and determine how conflicts are going to be fixed
            bool loweringPriorities = true;

            foreach (var entry in entries)
            {
                loweringPriorities &= (priority > entry.Priority);
                entry.Priority      = priority;
            }

            // We are rebuilding the plan with the new priorities
            RebuildPlanFrom(m_displayPlan, true);

            // Fix things up
            FixPrioritiesOrder(true, loweringPriorities);
            OnChanged(PlanChange.Notification);
        }
예제 #7
0
        /// <summary>
        /// Exports the plan under a text format.
        /// </summary>
        /// <param name="planToExport"></param>
        /// <param name="settings"></param>
        /// <param name="exportActions"></param>
        /// <returns></returns>
        public static string ExportAsText(Plan planToExport, PlanExportSettings settings, ExportPlanEntryActions exportActions)
        {
            var plan = new PlanScratchpad(planToExport.Character, planToExport);
            plan.Sort(planToExport.SortingPreferences);
            plan.UpdateStatistics();

            var builder = new StringBuilder();
            var timeFormat = DescriptiveTextOptions.FullText | DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText;
            var character = (Character)plan.Character;

            // Initialize constants
            string lineFeed = Environment.NewLine;
            string boldStart = String.Empty;
            string boldEnd = String.Empty;

            switch (settings.Markup)
            {
                default:
                    break;
                case MarkupType.Forum:
                    boldStart = "[b]";
                    boldEnd = "[/b]";
                    break;
                case MarkupType.Html:
                    lineFeed = String.Format(CultureInfo.InvariantCulture, "<br />{0}", Environment.NewLine);
                    boldStart = "<b>";
                    boldEnd = "</b>";
                    break;
            }

            // Header
            if (settings.IncludeHeader)
            {
                builder.Append(boldStart);
                if (settings.ShoppingList)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "Shopping list for {0}", character.Name);
                }
                else
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "Skill plan for {0}", character.Name);
                }
                builder.Append(boldEnd);
                builder.Append(lineFeed);
                builder.Append(lineFeed);
            }

            // Scroll through entries
            int index = 0;
            DateTime endTime = DateTime.Now;
            foreach (PlanEntry entry in plan)
            {
                // Remapping point
                if (!settings.ShoppingList && entry.Remapping != null)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "***{0}***", entry.Remapping);
                    builder.Append(lineFeed);
                }

                // Skip is we're only build a shopping list
                bool shoppingListCandidate = !(entry.CharacterSkill.IsKnown || entry.Level != 1 || entry.CharacterSkill.IsOwned);
                if (settings.ShoppingList && !shoppingListCandidate) 
                    continue;

                // Entry's index
                index++;
                if (settings.EntryNumber)
                    builder.AppendFormat(CultureConstants.DefaultCulture, "{0}. ", index);

                // Name
                builder.Append(boldStart);

                if (settings.Markup.Equals(MarkupType.Html))
                {
                    if (!settings.ShoppingList)
                    {
                        builder.AppendFormat(CultureConstants.DefaultCulture, "<a href=\"\" onclick=\"CCPEVE.showInfo({0})\">", entry.Skill.ID);
                    }
                    else
                    {
                        builder.AppendFormat(CultureConstants.DefaultCulture, "<a href=\"\" onclick=\"CCPEVE.showMarketDetails({0})\">", entry.Skill.ID);
                    }
                }
                builder.Append(entry.Skill.Name);

                if (settings.Markup == MarkupType.Html)
                    builder.Append("</a>");

                if (!settings.ShoppingList)
                    builder.AppendFormat(CultureConstants.DefaultCulture, " {0}", Skill.GetRomanForInt(entry.Level));

                builder.Append(boldEnd);

                // Training time
                if (settings.EntryTrainingTimes || settings.EntryStartDate || settings.EntryFinishDate || (settings.EntryCost && shoppingListCandidate))
                {
                    builder.Append(" (");
                    bool needComma = false;

                    // Training time
                    if (settings.EntryTrainingTimes)
                    {
                        needComma = true;
                        builder.Append(entry.TrainingTime.ToDescriptiveText(timeFormat));
                    }

                    // Training start date
                    if (settings.EntryStartDate)
                    {
                        if (needComma)
                            builder.Append("; ");

                        needComma = true;

                        builder.AppendFormat(CultureConstants.DefaultCulture, "Start: {0}", entry.StartTime);
                    }

                    // Training end date
                    if (settings.EntryFinishDate)
                    {
                        if (needComma)
                            builder.Append("; ");

                        needComma = true;

                        builder.AppendFormat(CultureConstants.DefaultCulture, "Finish: {0}", entry.EndTime);
                    }

                    // Skill cost
                    if (settings.EntryCost && shoppingListCandidate)
                    {
                        if (needComma)
                            builder.Append("; ");

                        needComma = true;

                        builder.AppendFormat(CultureConstants.DefaultCulture, "{0} ISK",  entry.Skill.FormattedCost);
                    }

                    builder.Append(')');
                }

                if (exportActions != null)
                    exportActions(builder, entry, settings);

                builder.Append(lineFeed);

                // End time
                endTime = entry.EndTime;
            }

            // Footer
            if (settings.FooterCount || settings.FooterTotalTime || settings.FooterDate || settings.FooterCost)
            {
                builder.AppendLine(lineFeed);
                bool needComma = false;

                // Skills count
                if (settings.FooterCount)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "{0}{1}{2}", boldStart, index, boldEnd);
                    builder.Append((index == 1 ? " skill" : " skills"));
                    needComma = true;
                }

                // Plan's training duration
                if (settings.FooterTotalTime)
                {
                    if (needComma)
                        builder.Append("; ");

                    needComma = true;

                    builder.AppendFormat(CultureConstants.DefaultCulture, "Total time: {0}{1}{2}",
                        boldStart, plan.GetTotalTime(null, true).ToDescriptiveText(timeFormat), boldEnd);
                }

                // End training date
                if (settings.FooterDate)
                {
                    if (needComma)
                        builder.Append("; ");

                    needComma = true;

                    builder.AppendFormat(CultureConstants.DefaultCulture, "Completion: {0}{1}{2}", boldStart, endTime, boldEnd);
                }

                // Total books cost
                if (settings.FooterCost)
                {
                    if (needComma)
                        builder.Append("; ");

                    needComma = true;

                    string formattedIsk = String.Format(CultureConstants.TidyInteger, "{0:n}", plan.NotKnownSkillBooksCost);
                    builder.AppendFormat(CultureConstants.DefaultCulture, "Cost: {0}{1}{2}", boldStart, formattedIsk, boldEnd);
                }

                // Warning about skill costs
                builder.Append(lineFeed);
                if (settings.FooterCost || settings.EntryCost)
                    builder.Append("N.B. Skill costs are based on CCP's database and are indicative only");
            }

            // Returns the text representation.
            return builder.ToString();
        }
예제 #8
0
        /// <summary>
        /// Exports the plan under a text format.
        /// </summary>
        /// <param name="planToExport"></param>
        /// <param name="settings"></param>
        /// <param name="exportActions"></param>
        /// <returns></returns>
        public static string ExportAsText(Plan planToExport, PlanExportSettings settings, ExportPlanEntryActions exportActions)
        {
            var plan = new PlanScratchpad(planToExport.Character, planToExport);

            plan.Sort(planToExport.SortingPreferences);
            plan.UpdateStatistics();

            var builder    = new StringBuilder();
            var timeFormat = DescriptiveTextOptions.FullText | DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText;
            var character  = (Character)plan.Character;

            // Initialize constants
            string lineFeed  = Environment.NewLine;
            string boldStart = String.Empty;
            string boldEnd   = String.Empty;

            switch (settings.Markup)
            {
            default:
                break;

            case MarkupType.Forum:
                boldStart = "[b]";
                boldEnd   = "[/b]";
                break;

            case MarkupType.Html:
                lineFeed  = String.Format(CultureInfo.InvariantCulture, "<br />{0}", Environment.NewLine);
                boldStart = "<b>";
                boldEnd   = "</b>";
                break;
            }

            // Header
            if (settings.IncludeHeader)
            {
                builder.Append(boldStart);
                if (settings.ShoppingList)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "Shopping list for {0}", character.Name);
                }
                else
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "Skill plan for {0}", character.Name);
                }
                builder.Append(boldEnd);
                builder.Append(lineFeed);
                builder.Append(lineFeed);
            }

            // Scroll through entries
            int      index   = 0;
            DateTime endTime = DateTime.Now;

            foreach (PlanEntry entry in plan)
            {
                // Remapping point
                if (!settings.ShoppingList && entry.Remapping != null)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "***{0}***", entry.Remapping);
                    builder.Append(lineFeed);
                }

                // Skip is we're only build a shopping list
                bool shoppingListCandidate = !(entry.CharacterSkill.IsKnown || entry.Level != 1 || entry.CharacterSkill.IsOwned);
                if (settings.ShoppingList && !shoppingListCandidate)
                {
                    continue;
                }

                // Entry's index
                index++;
                if (settings.EntryNumber)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "{0}. ", index);
                }

                // Name
                builder.Append(boldStart);

                if (settings.Markup.Equals(MarkupType.Html))
                {
                    if (!settings.ShoppingList)
                    {
                        builder.AppendFormat(CultureConstants.DefaultCulture, "<a href=\"\" onclick=\"CCPEVE.showInfo({0})\">", entry.Skill.ID);
                    }
                    else
                    {
                        builder.AppendFormat(CultureConstants.DefaultCulture, "<a href=\"\" onclick=\"CCPEVE.showMarketDetails({0})\">", entry.Skill.ID);
                    }
                }
                builder.Append(entry.Skill.Name);

                if (settings.Markup == MarkupType.Html)
                {
                    builder.Append("</a>");
                }

                if (!settings.ShoppingList)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, " {0}", Skill.GetRomanForInt(entry.Level));
                }

                builder.Append(boldEnd);

                // Training time
                if (settings.EntryTrainingTimes || settings.EntryStartDate || settings.EntryFinishDate || (settings.EntryCost && shoppingListCandidate))
                {
                    builder.Append(" (");
                    bool needComma = false;

                    // Training time
                    if (settings.EntryTrainingTimes)
                    {
                        needComma = true;
                        builder.Append(entry.TrainingTime.ToDescriptiveText(timeFormat));
                    }

                    // Training start date
                    if (settings.EntryStartDate)
                    {
                        if (needComma)
                        {
                            builder.Append("; ");
                        }

                        needComma = true;

                        builder.AppendFormat(CultureConstants.DefaultCulture, "Start: {0}", entry.StartTime);
                    }

                    // Training end date
                    if (settings.EntryFinishDate)
                    {
                        if (needComma)
                        {
                            builder.Append("; ");
                        }

                        needComma = true;

                        builder.AppendFormat(CultureConstants.DefaultCulture, "Finish: {0}", entry.EndTime);
                    }

                    // Skill cost
                    if (settings.EntryCost && shoppingListCandidate)
                    {
                        if (needComma)
                        {
                            builder.Append("; ");
                        }

                        needComma = true;

                        builder.AppendFormat(CultureConstants.DefaultCulture, "{0} ISK", entry.Skill.FormattedCost);
                    }

                    builder.Append(')');
                }

                if (exportActions != null)
                {
                    exportActions(builder, entry, settings);
                }

                builder.Append(lineFeed);

                // End time
                endTime = entry.EndTime;
            }

            // Footer
            if (settings.FooterCount || settings.FooterTotalTime || settings.FooterDate || settings.FooterCost)
            {
                builder.AppendLine(lineFeed);
                bool needComma = false;

                // Skills count
                if (settings.FooterCount)
                {
                    builder.AppendFormat(CultureConstants.DefaultCulture, "{0}{1}{2}", boldStart, index, boldEnd);
                    builder.Append((index == 1 ? " skill" : " skills"));
                    needComma = true;
                }

                // Plan's training duration
                if (settings.FooterTotalTime)
                {
                    if (needComma)
                    {
                        builder.Append("; ");
                    }

                    needComma = true;

                    builder.AppendFormat(CultureConstants.DefaultCulture, "Total time: {0}{1}{2}",
                                         boldStart, plan.GetTotalTime(null, true).ToDescriptiveText(timeFormat), boldEnd);
                }

                // End training date
                if (settings.FooterDate)
                {
                    if (needComma)
                    {
                        builder.Append("; ");
                    }

                    needComma = true;

                    builder.AppendFormat(CultureConstants.DefaultCulture, "Completion: {0}{1}{2}", boldStart, endTime, boldEnd);
                }

                // Total books cost
                if (settings.FooterCost)
                {
                    if (needComma)
                    {
                        builder.Append("; ");
                    }

                    needComma = true;

                    string formattedIsk = String.Format(CultureConstants.TidyInteger, "{0:n}", plan.NotKnownSkillBooksCost);
                    builder.AppendFormat(CultureConstants.DefaultCulture, "Cost: {0}{1}{2}", boldStart, formattedIsk, boldEnd);
                }

                // Warning about skill costs
                builder.Append(lineFeed);
                if (settings.FooterCost || settings.EntryCost)
                {
                    builder.Append("N.B. Skill costs are based on CCP's database and are indicative only");
                }
            }

            // Returns the text representation.
            return(builder.ToString());
        }
예제 #9
0
        /// <summary>
        /// Exports the plan under a text format.
        /// </summary>
        /// <param name="planToExport"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public static string ExportAsText(Plan planToExport, PlanExportSettings settings)
        {
            var plan = new PlanScratchpad(planToExport.Character, planToExport);

            plan.Sort(planToExport.SortingPreferences);
            plan.UpdateStatistics();

            var builder    = new StringBuilder();
            var timeFormat = DescriptiveTextOptions.FullText | DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText;
            var character  = (Character)plan.Character;

            // Initialize constants
            string lineFeed  = "";
            string boldStart = "";
            string boldEnd   = "";

            switch (settings.Markup)
            {
            default:
                break;

            case MarkupType.Forum:
                boldStart = "[b]";
                boldEnd   = "[/b]";
                break;

            case MarkupType.Html:
                lineFeed  = "<br />";
                boldStart = "<b>";
                boldEnd   = "</b>";
                break;
            }

            // Header
            if (settings.IncludeHeader)
            {
                builder.Append(boldStart);
                if (settings.ShoppingList)
                {
                    builder.Append("Shopping list for ").Append(character.Name);
                }
                else
                {
                    builder.Append("Skill plan for ").Append(character.Name);
                }
                builder.Append(boldEnd);
                builder.AppendLine(lineFeed);
                builder.AppendLine(lineFeed);
            }

            // Scroll through entries
            int      index   = 0;
            DateTime endTime = DateTime.Now;

            foreach (PlanEntry entry in plan)
            {
                // Remapping point
                if (!settings.ShoppingList && entry.Remapping != null)
                {
                    builder.Append("***").Append(entry.Remapping.ToString()).Append("***");
                    builder.AppendLine(lineFeed);
                }

                // Skip is we're only build a shopping list
                bool shoppingListCandidate = !(entry.CharacterSkill.IsKnown || entry.Level != 1 || entry.CharacterSkill.IsOwned);
                if (settings.ShoppingList && !shoppingListCandidate)
                {
                    continue;
                }

                // Entry's index
                index++;
                if (settings.EntryNumber)
                {
                    builder.Append(index.ToString()).Append(". ");
                }

                // Name
                builder.Append(boldStart);

                if (settings.Markup == MarkupType.Html)
                {
                    builder.Append("<a href=\"\" onclick=\"CCPEVE.showInfo(").Append(entry.Skill.ID.ToString()).Append(")\">");
                }
                builder.Append(entry.Skill.Name);
                if (settings.Markup == MarkupType.Html)
                {
                    builder.Append("</a>");
                }

                if (!settings.ShoppingList)
                {
                    builder.Append(' ').Append(Skill.GetRomanForInt(entry.Level));
                }

                builder.Append(boldEnd);

                // Training time
                if (settings.EntryTrainingTimes || settings.EntryStartDate || settings.EntryFinishDate || (settings.EntryCost && shoppingListCandidate))
                {
                    builder.Append(" (");
                    bool needComma = false;

                    // Training time
                    if (settings.EntryTrainingTimes)
                    {
                        needComma = true;
                        builder.Append(Skill.TimeSpanToDescriptiveText(entry.TrainingTime, timeFormat));
                    }

                    // Training start date
                    if (settings.EntryStartDate)
                    {
                        if (needComma)
                        {
                            builder.Append("; ");
                        }
                        needComma = true;

                        builder.Append("Start: ").Append(entry.StartTime.ToString());
                    }

                    // Training end date
                    if (settings.EntryFinishDate)
                    {
                        if (needComma)
                        {
                            builder.Append("; ");
                        }
                        needComma = true;

                        builder.Append("Finish: ").Append(entry.EndTime.ToString());
                    }

                    // Skill cost
                    if (settings.EntryCost && shoppingListCandidate)
                    {
                        if (needComma)
                        {
                            builder.Append("; ");
                        }
                        needComma = true;

                        builder.Append(entry.Skill.FormattedCost + " ISK");
                    }

                    builder.Append(')');
                }
                builder.AppendLine(lineFeed);

                // End time
                endTime = entry.EndTime;
            }

            // Footer
            if (settings.FooterCount || settings.FooterTotalTime || settings.FooterDate || settings.FooterCost)
            {
                builder.AppendLine(lineFeed);
                bool needComma = false;

                // Skills count
                if (settings.FooterCount)
                {
                    builder.Append(boldStart).Append(index.ToString()).Append(boldEnd);
                    builder.Append((index == 1 ? " skill" : " skills"));
                    needComma = true;
                }

                // Plan's training duration
                if (settings.FooterTotalTime)
                {
                    if (needComma)
                    {
                        builder.Append("; ");
                    }
                    needComma = true;

                    builder.Append("Total time: ");
                    builder.Append(boldStart);
                    builder.Append(Skill.TimeSpanToDescriptiveText(plan.GetTotalTime(null, true), timeFormat));
                    builder.Append(boldEnd);
                }

                // End training date
                if (settings.FooterDate)
                {
                    if (needComma)
                    {
                        builder.Append("; ");
                    }
                    needComma = true;

                    builder.Append("Completion: ");
                    builder.Append(boldStart).Append(endTime.ToString()).Append(boldEnd);
                }

                // Total books cost
                if (settings.FooterCost)
                {
                    if (needComma)
                    {
                        builder.Append("; ");
                    }
                    needComma = true;

                    builder.Append("Cost: ");
                    builder.Append(boldStart);
                    builder.Append((plan.TotalBooksCost == 0 ? "0 ISK" : String.Format("{0:0,0,0} ISK", plan.TotalBooksCost)));
                    builder.Append(boldEnd);
                }

                // Warning about skill costs
                builder.AppendLine(lineFeed);
                if (settings.FooterCost || settings.EntryCost)
                {
                    builder.Append("N.B. Skill costs are based on CCP's database and are indicative only");
                    builder.AppendLine(lineFeed);
                }
            }

            // Returns the text representation.
            return(builder.ToString());
        }
예제 #10
0
        /// <summary>
        /// Performs the sort
        /// </summary>
        /// <param name="startSp"></param>
        /// <returns></returns>
        public IEnumerable <PlanEntry> Sort(int startSp)
        {
            int initialCount = m_entries.Count();

            // Apply first pass (learning skills)
            // We split the entries into a head (learnings) and a tail (non-learnings)
            PlanScratchpad   headPlan    = new PlanScratchpad(m_character);
            List <PlanEntry> tailEntries = new List <PlanEntry>();

            if (m_learningSkillsFirst)
            {
                tailEntries.AddRange(m_entries.Where(x => x.Skill.LearningClass == LearningClass.None));

                var learningSkills = m_entries.Where(x => x.Skill.LearningClass != LearningClass.None);
                headPlan = OptimizeLearningSkills(learningSkills, startSp);
            }
            else
            {
                tailEntries.AddRange(m_entries);
            }


            // Apply second pass (priorities grouping)
            // We split the tail into multiple tail groups
            List <PlanScratchpad> tailEntryPlans = new List <PlanScratchpad>();
            var scratchpad = new CharacterScratchpad(m_character);

            scratchpad.Train(headPlan);

            if (m_groupByPriority)
            {
                foreach (var group in tailEntries.GroupBy(x => x.Priority))
                {
                    tailEntryPlans.Add(new PlanScratchpad(scratchpad, group));
                }
            }
            else
            {
                tailEntryPlans.Add(new PlanScratchpad(scratchpad, tailEntries));
            }


            // Apply third pass (sorts)
            // We sort every tail group, and merge them once they're sorted.
            List <PlanEntry> list = new List <PlanEntry>();

            list.AddRange(headPlan);

            foreach (var tailPlan in tailEntryPlans)
            {
                tailPlan.UpdateStatistics(scratchpad, false, false);
                tailPlan.SimpleSort(m_sort, m_reverseOrder);
                list.AddRange(tailPlan);
            }

            // This is actually what GroupByPriority should do
            if (m_groupByPriority)
            {
                list.StableSort(PlanSorter.CompareByPriority);
            }

            // Fix prerequisites order
            FixPrerequisitesOrder(list);

            // Check we didn't mess up anything
            if (initialCount != list.Count)
            {
                throw new UnauthorizedAccessException("The sort algorithm messed up and deleted items");
            }

            // Return
            return(list);
        }