using System.Collections.Generic; using System.Linq; using Questionable.Model; using Questionable.Model.Questing; namespace Questionable.Data; internal sealed class QuestChainBuilder { private readonly QuestData _questData; private readonly Dictionary> _descendants = new Dictionary>(); private readonly Dictionary _cache = new Dictionary(); private readonly Dictionary _graphCache = new Dictionary(); public QuestChainBuilder(QuestData questData) { _questData = questData; foreach (var (elementId2, questInfo2) in _questData.AllQuests) { if (!(elementId2 is QuestId item)) { continue; } foreach (PreviousQuestInfo previousQuest in questInfo2.PreviousQuests) { if (!_descendants.TryGetValue(previousQuest.QuestId, out List value)) { value = new List(); _descendants[previousQuest.QuestId] = value; } value.Add(item); } } } public QuestChain GetChain(QuestId questId) { if (_cache.TryGetValue(questId, out QuestChain value)) { return value; } List list = new List(); CollectAncestors(questId, list, new HashSet()); list.Add(questId); List list2 = new List(); CollectDescendants(questId, list2, new HashSet()); QuestChain questChain = new QuestChain(list, list2, questId); _cache[questId] = questChain; return questChain; } public QuestChainGraph GetChainGraph(QuestId questId) { if (_graphCache.TryGetValue(questId, out QuestChainGraph value)) { return value; } HashSet hashSet = new HashSet(); CollectAllRelated(questId, hashSet); Dictionary> prerequisites = new Dictionary>(); Dictionary> dictionary = new Dictionary>(); foreach (QuestId item in hashSet) { prerequisites[item] = new List(); dictionary[item] = new List(); } foreach (QuestId item2 in hashSet) { if (!_questData.TryGetQuestInfo(item2, out IQuestInfo questInfo)) { continue; } foreach (PreviousQuestInfo previousQuest in questInfo.PreviousQuests) { if (hashSet.Contains(previousQuest.QuestId)) { prerequisites[item2].Add(previousQuest.QuestId); dictionary[previousQuest.QuestId].Add(item2); } } } Dictionary dictionary2 = new Dictionary(); List list = hashSet.Where((QuestId q) => prerequisites[q].Count == 0).ToList(); foreach (QuestId item3 in hashSet) { dictionary2[item3] = 0; } Dictionary dictionary3 = new Dictionary(); foreach (QuestId item4 in hashSet) { dictionary3[item4] = prerequisites[item4].Count; } Queue queue = new Queue(list); foreach (QuestId item5 in list) { dictionary2[item5] = 0; } while (queue.Count > 0) { QuestId key = queue.Dequeue(); foreach (QuestId item6 in dictionary[key]) { int num = dictionary2[key] + 1; if (num > dictionary2[item6]) { dictionary2[item6] = num; } dictionary3[item6]--; if (dictionary3[item6] == 0) { queue.Enqueue(item6); } } } foreach (QuestId item7 in hashSet) { if (!dictionary2.ContainsKey(item7)) { dictionary2[item7] = 0; } } int num2 = ((hashSet.Count > 0) ? dictionary2.Values.Max() : 0); List> list2 = new List>(); for (int num3 = 0; num3 <= num2; num3++) { list2.Add(new List()); } foreach (QuestId item8 in hashSet) { list2[dictionary2[item8]].Add(item8); } foreach (List item9 in list2) { item9.Sort((QuestId a, QuestId b) => a.Value.CompareTo(b.Value)); } QuestChainGraph questChainGraph = new QuestChainGraph(prerequisites, dictionary, dictionary2, list2, questId); _graphCache[questId] = questChainGraph; return questChainGraph; } public void Invalidate() { _cache.Clear(); _graphCache.Clear(); } private void CollectAllRelated(QuestId questId, HashSet result) { CollectAncestorsSet(questId, result); result.Add(questId); CollectDescendantsSet(questId, result); } private void CollectAncestorsSet(QuestId questId, HashSet visited) { if (!visited.Add(questId) || !_questData.TryGetQuestInfo(questId, out IQuestInfo questInfo)) { return; } foreach (PreviousQuestInfo previousQuest in questInfo.PreviousQuests) { CollectAncestorsSet(previousQuest.QuestId, visited); } } private void CollectDescendantsSet(QuestId questId, HashSet visited) { if (!visited.Add(questId) || !_descendants.TryGetValue(questId, out List value)) { return; } foreach (QuestId item in value) { CollectDescendantsSet(item, visited); } } private void CollectAncestors(QuestId questId, List result, HashSet visited) { if (!visited.Add(questId) || !_questData.TryGetQuestInfo(questId, out IQuestInfo questInfo)) { return; } foreach (PreviousQuestInfo previousQuest in questInfo.PreviousQuests) { CollectAncestors(previousQuest.QuestId, result, visited); if (!result.Contains(previousQuest.QuestId)) { result.Add(previousQuest.QuestId); } } } private void CollectDescendants(QuestId questId, List result, HashSet visited) { if (!visited.Add(questId) || !_descendants.TryGetValue(questId, out List value)) { return; } foreach (QuestId item in value) { if (!result.Contains(item)) { result.Add(item); } CollectDescendants(item, result, visited); } } }