163 lines
5.3 KiB
C#
163 lines
5.3 KiB
C#
using System.ComponentModel;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Newtonsoft.Json.Linq;
|
|
using Pf2eDataScrapper.App;
|
|
using Pf2eDataScrapper.Helpers;
|
|
using Pf2eDataScrapper.Importers;
|
|
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Compendium;
|
|
using Pf2eDataScrapper.Importers.Implementations.FoundryEn.Compendium;
|
|
|
|
namespace Pf2eDataScrapper.Processors;
|
|
|
|
internal sealed class ProcessorExecutor(
|
|
IServiceProvider serviceProvider,
|
|
ProcessorCollection collection,
|
|
ProcessProgress progress,
|
|
AonprdCompendium aonprdCompendium,
|
|
FoundryEnCompendium foundryEnCompendium,
|
|
ApplicationSettings settings
|
|
)
|
|
{
|
|
public IServiceProvider ServiceProvider { get; } = serviceProvider;
|
|
public ProcessorCollection Collection { get; } = collection;
|
|
public ProcessProgress Progress { get; } = progress;
|
|
public AonprdCompendium AonprdCompendium { get; } = aonprdCompendium;
|
|
public FoundryEnCompendium FoundryEnCompendium { get; } = foundryEnCompendium;
|
|
public ApplicationSettings Settings { get; } = settings;
|
|
|
|
public void Start()
|
|
{
|
|
Collection.SortItems();
|
|
|
|
Progress.Processors.Reset(Collection.Items.Count);
|
|
|
|
StartItem();
|
|
}
|
|
|
|
private int _currentIndex;
|
|
|
|
private void StartItem()
|
|
{
|
|
ProcessorCollectionItem item = Collection.Items[_currentIndex];
|
|
|
|
Progress.Processors.Start(item.Description);
|
|
Progress.Progress(Progress.Processors.ToString());
|
|
|
|
BackgroundWorker worker = new();
|
|
|
|
worker.DoWork += (_, _) =>
|
|
{
|
|
Parallel.ForEach(
|
|
IterateProcessors(item),
|
|
new() { MaxDegreeOfParallelism = item.Parallel ? Settings.MaxThreads : 1 },
|
|
RunProcessor
|
|
);
|
|
};
|
|
|
|
worker.RunWorkerCompleted += (_, _) => Continue();
|
|
|
|
worker.RunWorkerAsync();
|
|
}
|
|
|
|
private void RunProcessor(IProcessor processor, ParallelLoopState state, long arg3)
|
|
{
|
|
try
|
|
{
|
|
processor.Process();
|
|
processor.Save();
|
|
}
|
|
catch (SkipItemException exception)
|
|
{
|
|
Progress.Information(exception.Message);
|
|
}
|
|
catch (SilentSkipItemException)
|
|
{
|
|
//
|
|
}
|
|
}
|
|
|
|
private void Continue()
|
|
{
|
|
Progress.Processors.End();
|
|
_currentIndex++;
|
|
|
|
if (_currentIndex < Collection.Items.Count)
|
|
{
|
|
StartItem();
|
|
}
|
|
else
|
|
{
|
|
Progress.Processors.Complete();
|
|
}
|
|
}
|
|
|
|
private IEnumerable<IProcessor> IterateProcessors(ProcessorCollectionItem item)
|
|
{
|
|
if (!item.IsCollection)
|
|
{
|
|
Progress.Local.Reset(1);
|
|
Progress.Local.Start(item.Description);
|
|
yield return (IProcessor)ActivatorUtilities.CreateInstance(ServiceProvider, item.Type);
|
|
Progress.Local.Complete();
|
|
yield break;
|
|
}
|
|
|
|
if (item.Group == ProcessorGroupEnum.General)
|
|
{
|
|
throw new(
|
|
$"Обработчик {item.Description} помечен как общий (поле Group == General) и коллекционный (поле InnerType), что запрещено."
|
|
);
|
|
}
|
|
|
|
AbstractCompendium compendium = item.Compendium switch
|
|
{
|
|
ProcessorCompendiumEnum.Aonprd => AonprdCompendium,
|
|
ProcessorCompendiumEnum.FoundryEn => FoundryEnCompendium,
|
|
_ => throw new($"Не могу выбрать импортёр для группы {item.Group}"),
|
|
};
|
|
|
|
ICollection<string> types = item.InnerType is null
|
|
? Collection.GetTypesOfCompendium(item.Compendium ?? throw new("impossible"))
|
|
: [item.InnerType];
|
|
|
|
Progress.Local.Reset(compendium.Count(types));
|
|
|
|
foreach ((AbstractCompendiumItem compendiumItem, JObject json) in compendium.Iterate(types))
|
|
{
|
|
Progress.Local.Start(compendiumItem.Id);
|
|
|
|
ProcessorInput processorInput = ActivatorUtilities.CreateInstance<ProcessorInput>(
|
|
ServiceProvider,
|
|
compendiumItem.Id,
|
|
json
|
|
);
|
|
|
|
yield return (IProcessor)
|
|
ActivatorUtilities.CreateInstance(ServiceProvider, item.Type, processorInput);
|
|
|
|
Progress.Local.End();
|
|
}
|
|
|
|
Progress.Local.Complete();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Исключение, показывающее, что обработка сущности пропускается как устаревшая.
|
|
/// </summary>
|
|
/// <param name="name">Название сущности.</param>
|
|
public class LegacyItemException(string name) : SkipItemException(name, "Устаревший элемент") { }
|
|
|
|
/// <summary>
|
|
/// Исключение, показывающее, что обработка сущности пропускается.
|
|
/// </summary>
|
|
/// <param name="name">Название сущности.</param>
|
|
/// <param name="reason">Причина пропуска.</param>
|
|
public class SkipItemException(string name, string reason)
|
|
: Exception($"Пропускаю элемент '{name}', указана причина: {reason}.") { }
|
|
|
|
/// <summary>
|
|
/// Исключение, показывающее, что обработка сущности пропускается без вывода сообщения.
|
|
/// </summary>
|
|
public class SilentSkipItemException : Exception { }
|