/// <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> protected IEnumerable <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 (T itemToRemove in skillsToRemove.Where( itemToRemove => IsPlanned(itemToRemove.Skill, itemToRemove.Level)).Where( itemToRemove => !entriesSet.Contains(itemToRemove))) { // Let's first gather dependencies foreach (PlanEntry dependencyEntry in Items.Where( dependencyEntry => !entriesSet.Contains(dependencyEntry)).Where( dependencyEntry => dependencyEntry.IsDependentOf(itemToRemove))) { // Gather this entry planEntries.Add(dependencyEntry); entriesSet.Set(dependencyEntry); } // Then add the item itself PlanEntry entryToRemove = GetEntry(itemToRemove.Skill, itemToRemove.Level); planEntries.Add(entryToRemove); entriesSet.Set(entryToRemove); } return(planEntries); }
/// <summary> /// Rebuild the plan from the given entries enumeration. /// </summary> /// <param name="entries">The entries.</param> /// <param name="preserveOldEntries">When true, old entries will be reused as often as possible, preserving their statistics.</param> /// <exception cref="System.ArgumentNullException">entries</exception> /// <remarks> /// Entries from another plan will be cloned. /// </remarks> public void RebuildPlanFrom(IEnumerable <PlanEntry> entries, bool preserveOldEntries) { entries.ThrowIfNull(nameof(entries)); if (!preserveOldEntries) { RebuildPlanFrom(entries); return; } using (SuspendingEvents()) { // Save the old entries SkillLevelSet <PlanEntry> set = new SkillLevelSet <PlanEntry>(); foreach (PlanEntry entry in Items) { set[entry.Skill, entry.Level] = entry; } // Clear items Items.Clear(); for (int i = 0; i < m_lookup.Length; i++) { m_lookup[i] = null; } // Add the new entries foreach (PlanEntry entry in entries) { PlanEntry 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); } } }
/// <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> protected IEnumerable <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 (T itemToAdd in skillsToAdd.Where( itemToAdd => Character.GetSkillLevel(itemToAdd.Skill) < itemToAdd.Level)) { // 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 excluding those that the dependent skill is already trained StaticSkillLevel item = new StaticSkillLevel(itemToAdd); if (Character.GetSkillLevel(itemToAdd.Skill) < 1) { foreach (StaticSkillLevel dependency in item.AllDependencies.Where( dependency => !entriesSet.Contains(dependency) && dependency.Skill != item.Skill && Character.GetSkillLevel(dependency.Skill) < dependency.Level) .Select(dependency => new { dependency, depItems = item.AllDependencies.Where( dep => item.Skill != dep.Skill && dep.Skill.Prerequisites.Any( prereq => prereq.Skill == dependency.Skill)) }) .Where(dep => !dep.depItems.Any() || !dep.depItems.All(depItem => Character.GetSkillLevel(depItem.Skill) >= depItem.Level)) .Select(dep => dep.dependency)) { // Create an entry (even for existing ones, we will update them later from those new entries) PlanEntry 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 PlanEntry entry = CreateEntryToAdd(itemToAdd.Skill, itemToAdd.Level, PlanEntryType.Planned, note, ref lowestPrereqPriority); planEntries.Add(entry); entriesSet.Set(entry); } return(planEntries); }