qstbak/Questionable/Questionable.Data/QuestChainBuilder.cs
2026-08-17 20:29:32 +10:00

212 lines
5.6 KiB
C#

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<QuestId, List<QuestId>> _descendants = new Dictionary<QuestId, List<QuestId>>();
private readonly Dictionary<QuestId, QuestChain> _cache = new Dictionary<QuestId, QuestChain>();
private readonly Dictionary<QuestId, QuestChainGraph> _graphCache = new Dictionary<QuestId, QuestChainGraph>();
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<QuestId> value))
{
value = new List<QuestId>();
_descendants[previousQuest.QuestId] = value;
}
value.Add(item);
}
}
}
public QuestChain GetChain(QuestId questId)
{
if (_cache.TryGetValue(questId, out QuestChain value))
{
return value;
}
List<QuestId> list = new List<QuestId>();
CollectAncestors(questId, list, new HashSet<QuestId>());
list.Add(questId);
List<QuestId> list2 = new List<QuestId>();
CollectDescendants(questId, list2, new HashSet<QuestId>());
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<QuestId> hashSet = new HashSet<QuestId>();
CollectAllRelated(questId, hashSet);
Dictionary<QuestId, List<QuestId>> prerequisites = new Dictionary<QuestId, List<QuestId>>();
Dictionary<QuestId, List<QuestId>> dictionary = new Dictionary<QuestId, List<QuestId>>();
foreach (QuestId item in hashSet)
{
prerequisites[item] = new List<QuestId>();
dictionary[item] = new List<QuestId>();
}
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<QuestId, int> dictionary2 = new Dictionary<QuestId, int>();
List<QuestId> list = hashSet.Where((QuestId q) => prerequisites[q].Count == 0).ToList();
foreach (QuestId item3 in hashSet)
{
dictionary2[item3] = 0;
}
Dictionary<QuestId, int> dictionary3 = new Dictionary<QuestId, int>();
foreach (QuestId item4 in hashSet)
{
dictionary3[item4] = prerequisites[item4].Count;
}
Queue<QuestId> queue = new Queue<QuestId>(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<List<QuestId>> list2 = new List<List<QuestId>>();
for (int num3 = 0; num3 <= num2; num3++)
{
list2.Add(new List<QuestId>());
}
foreach (QuestId item8 in hashSet)
{
list2[dictionary2[item8]].Add(item8);
}
foreach (List<QuestId> 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<QuestId> result)
{
CollectAncestorsSet(questId, result);
result.Add(questId);
CollectDescendantsSet(questId, result);
}
private void CollectAncestorsSet(QuestId questId, HashSet<QuestId> 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<QuestId> visited)
{
if (!visited.Add(questId) || !_descendants.TryGetValue(questId, out List<QuestId> value))
{
return;
}
foreach (QuestId item in value)
{
CollectDescendantsSet(item, visited);
}
}
private void CollectAncestors(QuestId questId, List<QuestId> result, HashSet<QuestId> 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<QuestId> result, HashSet<QuestId> visited)
{
if (!visited.Add(questId) || !_descendants.TryGetValue(questId, out List<QuestId> value))
{
return;
}
foreach (QuestId item in value)
{
if (!result.Contains(item))
{
result.Add(item);
}
CollectDescendants(item, result, visited);
}
}
}