Пример #1
0
        /// <summary>
        /// Given a list of skill to add, we return a list of all entries to add, also including all dependencies. No entry is added by this method.
        /// </summary>
        /// <param name="skillsToAdd">The enumerations of skills to add.</param>
        /// <param name="note">The note for new entries.</param>
        /// <param name="lowestPrereqPriority">The lowest priority (highest number) among all the prerequisites.</param>
        /// <returns>A list of all the entries to add.</returns>
        public List <PlanEntry> GetAllEntriesToAdd <T>(IEnumerable <T> skillsToAdd, string note, out int lowestPrereqPriority)
            where T : ISkillLevel
        {
            SkillLevelSet <PlanEntry> entriesSet  = new SkillLevelSet <PlanEntry>();
            List <PlanEntry>          planEntries = new List <PlanEntry>();

            lowestPrereqPriority = 1;

            // For every items to add
            foreach (var itemToAdd in skillsToAdd)
            {
                // Already trained ? We skip it.
                if (m_character.GetSkillLevel(itemToAdd.Skill) >= itemToAdd.Level)
                {
                    continue;
                }

                // Already planned ? We update the lowestPrereqPriority and skip it.
                if (IsPlanned(itemToAdd.Skill, itemToAdd.Level))
                {
                    lowestPrereqPriority = Math.Max(GetEntry(itemToAdd.Skill, itemToAdd.Level).Priority, lowestPrereqPriority);
                    continue;
                }

                // Let's first add dependencies
                var item = new StaticSkillLevel(itemToAdd);
                foreach (var dependency in item.AllDependencies)
                {
                    // Already in the "entries to add" list ? We skip it.
                    if (entriesSet.Contains(dependency))
                    {
                        continue;
                    }

                    // Already trained ? We skip it.
                    if (m_character.GetSkillLevel(dependency.Skill) >= dependency.Level)
                    {
                        continue;
                    }

                    // Create an entry (even for existing ones, we will update them later from those new entries)
                    var dependencyEntry = CreateEntryToAdd(dependency.Skill, dependency.Level, PlanEntryType.Prerequisite, note, ref lowestPrereqPriority);
                    planEntries.Add(dependencyEntry);
                    entriesSet.Set(dependencyEntry);
                }

                // Already in the "entries to add" list ? We skip it (done at this point only because of recursive prereqs)
                if (entriesSet.Contains(itemToAdd))
                {
                    continue;
                }

                // Then add the item itself
                var entry = CreateEntryToAdd(itemToAdd.Skill, itemToAdd.Level, PlanEntryType.Planned, note, ref lowestPrereqPriority);
                planEntries.Add(entry);
                entriesSet.Set(entry);
            }

            return(planEntries);
        }
Пример #2
0
        /// <summary>
        /// Ensures the prerequsiites order is correct
        /// </summary>
        /// <param name="list"></param>
        private void FixPrerequisitesOrder(List <PlanEntry> list)
        {
            // Gather prerequisites/postrequisites relationships and use them to connect nodes - O(n²) operation
            var dependencies = new Dictionary <PlanEntry, List <PlanEntry> >();

            foreach (var entry in list)
            {
                dependencies[entry] = new List <PlanEntry>(list.Where(x => entry.IsDependentOf(x)));
            }


            // Insert entries
            var entriesToAdd = new LinkedList <PlanEntry>(list);
            var set          = new SkillLevelSet <PlanEntry>();

            list.Clear();

            while (entriesToAdd.Count != 0)
            {
                // Gets the first entry which has all its prerequisites satisfied.
                var item = entriesToAdd.First(x => dependencies[x].All(y => set[y.Skill, y.Level] != null));

                // Add it to the set and list, and remove it from the entries to add
                set[item.Skill, item.Level] = item;
                entriesToAdd.Remove(item);
                list.Add(item);
            }
        }
Пример #3
0
        /// <summary>
        /// Given a list of skill to remove, we return a list of entries also including all dependencies. No entry is removed by this method.
        /// </summary>
        /// <returns>A list of all the entries to remove.</returns>
        public List <PlanEntry> GetAllEntriesToRemove <T>(IEnumerable <T> skillsToRemove)
            where T : ISkillLevel
        {
            SkillLevelSet <PlanEntry> entriesSet  = new SkillLevelSet <PlanEntry>();
            List <PlanEntry>          planEntries = new List <PlanEntry>();

            // For every items to add
            foreach (var itemToRemove in skillsToRemove)
            {
                // Not planned ? We skip it.
                if (!IsPlanned(itemToRemove.Skill, itemToRemove.Level))
                {
                    continue;
                }

                // Already in the "entries to remove" list ? We skip it (done at this point only because of recursive prereqs)
                if (entriesSet.Contains(itemToRemove))
                {
                    continue;
                }

                // Let's first gather dependencies
                var item = new StaticSkillLevel(itemToRemove);
                foreach (var dependencyEntry in m_items)
                {
                    // Already in the "entries to remove" list ? We skip it.
                    if (entriesSet.Contains(dependencyEntry))
                    {
                        continue;
                    }

                    // Not dependent ? We skip it.
                    if (!dependencyEntry.IsDependentOf(itemToRemove))
                    {
                        continue;
                    }

                    // Gather this entry
                    planEntries.Add(dependencyEntry);
                    entriesSet.Set(dependencyEntry);
                }

                // Then add the item itself
                var entryToRemove = GetEntry(itemToRemove.Skill, itemToRemove.Level);
                planEntries.Add(entryToRemove);
                entriesSet.Set(entryToRemove);
            }

            return(planEntries);
        }
Пример #4
0
        /// <summary>
        /// Rebuild the plan from the given entries enumeration.
        /// </summary>
        /// <remarks>Entries from another plan will be cloned.</remarks>
        /// <param name="preserveOldEntries">When true, old entries will be reused as often as possible, preserving their statistics.</param>
        /// <param name="entries"></param>
        public void RebuildPlanFrom(IEnumerable <PlanEntry> entries, bool preserveOldEntries)
        {
            if (!preserveOldEntries)
            {
                RebuildPlanFrom(entries);
                return;
            }

            using (SuspendingEvents())
            {
                // Save the old entries
                var set = new SkillLevelSet <PlanEntry>();
                foreach (var entry in m_items)
                {
                    set[entry.Skill, entry.Level] = entry;
                }

                // Clear items
                m_items.Clear();
                for (int i = 0; i < m_lookup.Length; i++)
                {
                    m_lookup[i] = null;
                }

                // Add the new entries
                foreach (var entry in entries)
                {
                    var oldEntry = set[entry.Skill, entry.Level];

                    PlanEntry entryToAdd;
                    if (entry.Plan != this)
                    {
                        entryToAdd = entry.Clone(this);
                    }
                    else if (oldEntry != null)
                    {
                        entryToAdd = oldEntry;
                    }
                    else
                    {
                        entryToAdd = entry;
                    }

                    AddCore(entryToAdd);
                }
            }
        }