qstbak/Questionable/Questionable.Data/JournalData.cs
2025-12-20 04:56:36 +10:00

209 lines
7.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Plugin.Services;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Microsoft.Extensions.Logging;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Data;
internal sealed class JournalData
{
internal sealed class Genre
{
public uint Id { get; }
public string Name { get; }
public uint CategoryId { get; }
public List<IQuestInfo> Quests { get; }
public bool IsUnderOtherQuests { get; set; }
public Genre(JournalGenre journalGenre, List<IQuestInfo> quests)
{
Id = journalGenre.RowId;
Name = journalGenre.Name.ToString();
CategoryId = journalGenre.JournalCategory.RowId;
Quests = quests;
IsUnderOtherQuests = false;
}
public Genre(uint id, string name, uint categoryId, List<IQuestInfo> quests)
{
Id = id;
Name = name;
CategoryId = categoryId;
Quests = quests;
IsUnderOtherQuests = false;
}
public Genre(uint id, string name, uint categoryId, List<IQuestInfo> quests, bool isUnderOtherQuests = false)
{
Id = id;
Name = name;
CategoryId = categoryId;
Quests = quests;
IsUnderOtherQuests = isUnderOtherQuests;
}
}
internal sealed class Category
{
public uint Id { get; } = journalCategory.RowId;
public string Name { get; } = journalCategory.Name.ToString();
public uint SectionId { get; } = journalCategory.JournalSection.RowId;
public IReadOnlyList<Genre> Genres { get; }
public Category(JournalCategory journalCategory, IReadOnlyList<Genre> genres)
{
Genres = genres;
base._002Ector();
}
}
internal sealed class Section
{
public uint Id { get; } = journalSection.RowId;
public string Name { get; } = journalSection.Name.ToString();
public IReadOnlyList<Category> Categories { get; }
public Section(JournalSection journalSection, IReadOnlyList<Category> categories)
{
Categories = categories;
base._002Ector();
}
}
private readonly ILogger<JournalData> _logger;
public uint? SeasonalEventsCategoryId { get; }
public IReadOnlySet<uint> SeasonalEventGenreIds { get; }
public uint? MoogleDeliveryGenreId { get; }
public List<Genre> Genres { get; }
public List<Category> Categories { get; }
public List<Section> Sections { get; }
public int? OtherQuestsSectionRowId { get; private set; }
public JournalData(IDataManager dataManager, QuestData questData, ILogger<JournalData> logger)
{
JournalData journalData = this;
_logger = logger;
ExcelSheet<JournalGenre> excelSheet = dataManager.GetExcelSheet<JournalGenre>();
JournalCategory journalCategory = dataManager.GetExcelSheet<JournalCategory>().FirstOrDefault((JournalCategory x) => x.Name.ToString().Equals("Seasonal Events", StringComparison.OrdinalIgnoreCase));
if (journalCategory.RowId != 0)
{
SeasonalEventsCategoryId = journalCategory.RowId;
_logger.LogInformation("Resolved 'Seasonal Events' JournalCategory ID: {CategoryId}", SeasonalEventsCategoryId);
}
else
{
SeasonalEventsCategoryId = null;
_logger.LogWarning("Could not find 'Seasonal Events' JournalCategory - seasonal event detection may not work correctly");
}
if (SeasonalEventsCategoryId.HasValue)
{
SeasonalEventGenreIds = (from x in excelSheet
where x.RowId != 0 && x.JournalCategory.RowId == journalData.SeasonalEventsCategoryId.Value
select x.RowId).ToHashSet();
_logger.LogInformation("Resolved {Count} seasonal event JournalGenre IDs from JournalCategory {CategoryId}: [{Ids}]", SeasonalEventGenreIds.Count, SeasonalEventsCategoryId.Value, string.Join(", ", SeasonalEventGenreIds.OrderBy((uint x) => x)));
}
else
{
SeasonalEventGenreIds = new HashSet<uint>();
}
JournalGenre journalGenre = excelSheet.FirstOrDefault((JournalGenre x) => x.Name.ToString().Equals("Delivery Moogle Quests", StringComparison.OrdinalIgnoreCase));
if (journalGenre.RowId != 0)
{
MoogleDeliveryGenreId = journalGenre.RowId;
_logger.LogInformation("Resolved 'Delivery Moogle Quests' JournalGenre ID: {GenreId}", MoogleDeliveryGenreId);
}
else
{
MoogleDeliveryGenreId = null;
_logger.LogWarning("Could not find 'Delivery Moogle Quests' JournalGenre - moogle delivery quest detection may not work correctly");
}
List<Genre> list = (from x in excelSheet
where x.RowId != 0 && x.Icon > 0
select new Genre(x, questData.GetAllByJournalGenre(x.RowId))).ToList();
QuestRedo row = dataManager.GetExcelSheet<QuestRedo>().GetRow(1u);
QuestRedo row2 = dataManager.GetExcelSheet<QuestRedo>().GetRow(2u);
QuestRedo row3 = dataManager.GetExcelSheet<QuestRedo>().GetRow(3u);
Genre genreLimsa = new Genre(4294967292u, "Starting in Limsa Lominsa", 1u, (from x in new uint[2] { 108u, 109u }.Concat(row.QuestRedoParam.Select((QuestRedo.QuestRedoParamStruct x) => x.Quest.RowId))
where x != 0
select questData.GetQuestInfo(QuestId.FromRowId(x))).ToList());
Genre genreGridania = new Genre(4294967293u, "Starting in Gridania", 1u, (from x in new uint[3] { 85u, 123u, 124u }.Concat(row2.QuestRedoParam.Select((QuestRedo.QuestRedoParamStruct x) => x.Quest.RowId))
where x != 0
select questData.GetQuestInfo(QuestId.FromRowId(x))).ToList());
Genre genreUldah = new Genre(4294967294u, "Starting in Ul'dah", 1u, (from x in new uint[3] { 568u, 569u, 570u }.Concat(row3.QuestRedoParam.Select((QuestRedo.QuestRedoParamStruct x) => x.Quest.RowId))
where x != 0
select questData.GetQuestInfo(QuestId.FromRowId(x))).ToList());
list.InsertRange(0, new Genre[3] { genreLimsa, genreGridania, genreUldah });
list.Single((Genre x) => x.Id == 1).Quests.RemoveAll((IQuestInfo x) => genreLimsa.Quests.Contains(x) || genreGridania.Quests.Contains(x) || genreUldah.Quests.Contains(x));
Genres = list.ToList();
Categories = (from x in dataManager.GetExcelSheet<JournalCategory>()
where x.RowId != 0
select new Category(x, journalData.Genres.Where((Genre y) => y.CategoryId == x.RowId).ToList())).ToList();
Sections = (from x in dataManager.GetExcelSheet<JournalSection>()
select new Section(x, journalData.Categories.Where((Category y) => y.SectionId == x.RowId).ToList())).ToList();
OtherQuestsSectionRowId = GetOtherQuestsSectionRowId(dataManager);
int? otherQuestsSectionRowId = OtherQuestsSectionRowId;
if (otherQuestsSectionRowId.HasValue)
{
int valueOrDefault = otherQuestsSectionRowId.GetValueOrDefault();
uint otherIdU = (uint)valueOrDefault;
Section section = Sections.FirstOrDefault((Section s) => s.Id == otherIdU);
if (section != null)
{
int num = 0;
foreach (Category category in section.Categories)
{
foreach (Genre genre in category.Genres)
{
genre.IsUnderOtherQuests = true;
num++;
}
}
_logger.LogInformation("Marked {Count} genres as under 'Other Quests' (OtherQuestsSectionRowId={Id})", num, valueOrDefault);
}
else
{
_logger.LogWarning("OtherQuestsSectionRowId = {Id} found, but matching Section not present in constructed Sections", valueOrDefault);
}
}
else
{
_logger.LogDebug("OtherQuestsSectionRowId not found - falling back to localized name lookup when necessary");
}
}
private int? GetOtherQuestsSectionRowId(IDataManager dataManager)
{
JournalSection journalSection = dataManager.GetExcelSheet<JournalSection>().FirstOrDefault((JournalSection s) => s.Name.ToString() == "Other Quests");
int? result = ((journalSection.RowId != 0) ? new int?((int)journalSection.RowId) : ((int?)null));
if (!result.HasValue)
{
Section section = Sections.FirstOrDefault((Section s) => s.Name.Equals("Other Quests", StringComparison.OrdinalIgnoreCase));
if (section != null)
{
result = (int)section.Id;
}
}
return result;
}
}