Пример #1
0
        /// <summary>
        /// Inserts the given learning skill at the best possible position
        /// </summary>
        /// <param name="skill"></param>
        /// <param name="level"></param>
        public void InsertAtBestPosition(StaticSkill skill, int level)
        {
            using (SuspendingEvents())
            {
                var entry = new PlanEntry(this, skill, level);

                // Look at prerequisites to search min and max insertion positions
                int minPosition = 0, maxPosition = m_items.Count;
                for (int i = 0; i < m_items.Count; i++)
                {
                    var pEntry = m_items[i];
                    if (entry.IsDependentOf(pEntry))
                    {
                        minPosition = Math.Max(minPosition, i + 1);
                    }
                    if (pEntry.IsDependentOf(entry))
                    {
                        maxPosition = Math.Min(maxPosition, i);
                    }
                }

                var bestTime              = TimeSpan.MaxValue;
                var bestCandidatePosition = maxPosition;
                var scratchpad            = new CharacterScratchpad(m_character);

                // We now search for the best insertion position
                for (int index = maxPosition; index >= minPosition; index--)
                {
                    using (scratchpad.BeginTemporaryChanges())
                    {
                        // Compute list's training time if the next item was inserted at index
                        for (int i = 0; i <= m_items.Count; i++)
                        {
                            if (i < index)
                            {
                                scratchpad.Train(m_items[i]);
                            }
                            else if (i > index)
                            {
                                scratchpad.Train(m_items[i - 1]);
                            }
                            else
                            {
                                scratchpad.Train(entry);
                            }
                        }

                        // Is it better with this index ? Then, we retain this as the best candidate
                        if (bestTime > scratchpad.TrainingTime)
                        {
                            bestTime = scratchpad.TrainingTime;
                            bestCandidatePosition = index;
                        }
                    }
                }

                // Insert at the best candidate position
                InsertCore(bestCandidatePosition, entry);
            }
        }
Пример #2
0
        /// <summary>
        /// Gets the list of remapping results from a plan.
        /// </summary>
        /// <param name="plan"></param>
        /// <returns></returns>
        public static List <RemappingResult> GetResultsFromRemappingPoints(BasePlan plan)
        {
            var             scratchpad    = new CharacterScratchpad(plan.Character.After(plan.ChosenImplantSet));
            var             remappingList = new List <RemappingResult>();
            var             list          = new List <ISkillLevel>();
            RemappingResult remapping     = null;

            // Scroll through the entries and split it into remappings
            foreach (var entry in plan)
            {
                // Ends the current remapping and start a new one
                if (entry.Remapping != null)
                {
                    // Creates a new remapping
                    remapping = new RemappingResult(entry.Remapping, scratchpad.Clone());
                    remappingList.Add(remapping);
                    list = remapping.Skills;
                }

                // Add this skill to the training list
                scratchpad.Train(entry);
                list.Add(entry);
            }

            // Return
            return(remappingList);
        }
Пример #3
0
        /// <summary>
        /// Updates the statistics of the entries in the same way the given character would train this plan.
        /// </summary>
        /// <param name="scratchpad"></param>
        /// <param name="applyRemappingPoints"></param>
        /// <param name="trainSkills">When true, the character will train every skill, increasing SP, etc.</param>
        public void UpdateStatistics(CharacterScratchpad scratchpad, bool applyRemappingPoints, bool trainSkills)
        {
            var scratchpadWithoutImplants = scratchpad.Clone();

            scratchpadWithoutImplants.ClearImplants();
            DateTime time = DateTime.Now;

            // Update the statistics
            foreach (var entry in m_items)
            {
                // Apply the remapping
                if (applyRemappingPoints && entry.Remapping != null && entry.Remapping.Status == RemappingPoint.PointStatus.UpToDate)
                {
                    scratchpad.Remap(entry.Remapping);
                    scratchpadWithoutImplants.Remap(entry.Remapping);
                }

                // Update entry's statistics
                entry.UpdateStatistics(scratchpad, scratchpadWithoutImplants, ref time);

                // Update the scratchpad
                if (trainSkills)
                {
                    scratchpad.Train(entry.Skill, entry.Level);
                    scratchpadWithoutImplants.Train(entry.Skill, entry.Level);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Gets a character scratchpad representing this character after the provided skill levels trainings.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="trainings"></param>
        /// <returns></returns>
        public CharacterScratchpad After <T>(IEnumerable <T> trainings)
            where T : ISkillLevel
        {
            var scratchpad = new CharacterScratchpad(this);

            scratchpad.Train(trainings);
            return(scratchpad);
        }
Пример #5
0
        /// <summary>
        /// Updates the statistics of the entries in the same way the given character would train this plan.
        /// </summary>
        /// <param name="scratchpad"></param>
        /// <param name="applyRemappingPoints"></param>
        /// <param name="trainSkills">When true, the character will train every skill, increasing SP, etc.</param>
        public void UpdateOldTrainingTimes(CharacterScratchpad scratchpad, bool applyRemappingPoints, bool trainSkills)
        {
            // Update the statistics
            foreach (var entry in m_items)
            {
                // Apply the remapping
                if (applyRemappingPoints && entry.Remapping != null && entry.Remapping.Status == RemappingPoint.PointStatus.UpToDate)
                {
                    scratchpad.Remap(entry.Remapping);
                }

                // Update entry's statistics
                entry.UpdateOldTrainingTime(scratchpad);

                // Update the scratchpad
                if (trainSkills)
                {
                    scratchpad.Train(entry.Skill, entry.Level);
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Compute the best possible attributes to fulfill the given trainings array
        /// </summary>
        /// <param name="skills"></param>
        /// <param name="baseScratchpad"></param>
        /// <param name="maxDuration"></param>
        /// <returns></returns>
        private static CharacterScratchpad Optimize <T>(IEnumerable <T> skills, CharacterScratchpad baseScratchpad, TimeSpan maxDuration)
            where T : ISkillLevel
        {
            CharacterScratchpad bestScratchpad = new CharacterScratchpad(baseScratchpad);
            CharacterScratchpad tempScratchpad = new CharacterScratchpad(baseScratchpad);
            TimeSpan            baseTime       = baseScratchpad.TrainingTime;
            TimeSpan            bestTime       = TimeSpan.MaxValue;
            int bestSkillCount = 0;

            // Now, we have the points to spend, let's perform all the
            // combinations (less than 11^4 = 14,641)
            for (int per = 0; per <= EveConstants.MaxRemappablePointsPerAttribute; per++)
            {
                // WIL
                int maxWillpower = EveConstants.SpareAttributePointsOnRemap - per;
                for (int will = 0; will <= maxWillpower && will <= EveConstants.MaxRemappablePointsPerAttribute; will++)
                {
                    // INT
                    int maxIntelligence = maxWillpower - will;
                    for (int intell = 0; intell <= maxIntelligence && intell <= EveConstants.MaxRemappablePointsPerAttribute; intell++)
                    {
                        // MEM
                        int maxMemory = maxIntelligence - intell;
                        for (int mem = 0; mem <= maxMemory && mem <= EveConstants.MaxRemappablePointsPerAttribute; mem++)
                        {
                            // CHA
                            int cha = maxMemory - mem;

                            // Reject invalid combinations
                            if (cha <= EveConstants.MaxRemappablePointsPerAttribute)
                            {
                                // Resets the scratchpad
                                tempScratchpad.Reset();

                                // Set new attributes
                                tempScratchpad.Memory.Base       = mem + EveConstants.CharacterBaseAttributePoints;
                                tempScratchpad.Charisma.Base     = cha + EveConstants.CharacterBaseAttributePoints;
                                tempScratchpad.Willpower.Base    = will + EveConstants.CharacterBaseAttributePoints;
                                tempScratchpad.Perception.Base   = per + EveConstants.CharacterBaseAttributePoints;
                                tempScratchpad.Intelligence.Base = intell + EveConstants.CharacterBaseAttributePoints;

                                // Train skills
                                int tempSkillCount = 0;
                                foreach (var skill in skills)
                                {
                                    tempSkillCount++;
                                    tempScratchpad.Train(skill);

                                    // Did it go over max duration ?
                                    if (tempScratchpad.TrainingTime - baseTime > maxDuration)
                                    {
                                        break;
                                    }

                                    // Did it go over the best time so far without training more skills ?
                                    if (tempSkillCount <= bestSkillCount && tempScratchpad.TrainingTime > bestTime)
                                    {
                                        break;
                                    }
                                }

                                // Did it manage to train more skills before the max duration,
                                // or did it train the same number of skills in a lesser time ?
                                if (tempSkillCount > bestSkillCount || (tempSkillCount == bestSkillCount && tempScratchpad.TrainingTime < bestTime))
                                {
                                    bestScratchpad.Reset();
                                    bestScratchpad.Memory.Base       = tempScratchpad.Memory.Base;
                                    bestScratchpad.Charisma.Base     = tempScratchpad.Charisma.Base;
                                    bestScratchpad.Willpower.Base    = tempScratchpad.Willpower.Base;
                                    bestScratchpad.Perception.Base   = tempScratchpad.Perception.Base;
                                    bestScratchpad.Intelligence.Base = tempScratchpad.Intelligence.Base;
                                    bestTime       = tempScratchpad.TrainingTime;
                                    bestSkillCount = tempSkillCount;
                                }
                            }
                        }
                    }
                }
            }

            // Return the best scratchpad found
            return(bestScratchpad);
        }
Пример #7
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);
        }