diff --git a/source/LootDumpProcessor/GCHandler.cs b/source/LootDumpProcessor/GCHandler.cs
deleted file mode 100644
index f4efcb9..0000000
--- a/source/LootDumpProcessor/GCHandler.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace LootDumpProcessor;
-
-public static class GCHandler
-{
- public static void Collect()
- {
- if (LootDumpProcessorContext.GetConfig().ManualGarbageCollectionCalls) GC.Collect();
- }
-}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/LootDumpProcessor.csproj b/source/LootDumpProcessor/LootDumpProcessor.csproj
index 64cb73e..16c0bb7 100644
--- a/source/LootDumpProcessor/LootDumpProcessor.csproj
+++ b/source/LootDumpProcessor/LootDumpProcessor.csproj
@@ -11,7 +11,11 @@
+
+
+
+
diff --git a/source/LootDumpProcessor/LootDumpProcessorContext.cs b/source/LootDumpProcessor/LootDumpProcessorContext.cs
deleted file mode 100644
index 9c50f90..0000000
--- a/source/LootDumpProcessor/LootDumpProcessorContext.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.Text.Json;
-using LootDumpProcessor.Model.Config;
-using LootDumpProcessor.Model.Output.StaticContainer;
-using LootDumpProcessor.Serializers.Json;
-using LootDumpProcessor.Serializers.Yaml;
-
-namespace LootDumpProcessor;
-
-public static class LootDumpProcessorContext
-{
- private static Config? _config;
- private static readonly object _configLock = new();
- private static ForcedStatic? _forcedStatic;
- private static readonly object _forcedStaticLock = new();
- private static HashSet? _staticWeaponIds;
- private static readonly object _staticWeaponIdsLock = new();
- private static Dictionary>? _forcedItems;
- private static readonly object _forcedItemsLock = new();
- private static Dictionary>? _forcedLoose;
- private static readonly object _forcedLooseLock = new();
-
- public static Config GetConfig()
- {
- lock (_configLock)
- {
- if (_config == null)
- // This is the only instance where manual selection of the serializer is required
- // after this, GetInstance() for the JsonSerializerFactory should used without
- // parameters
- _config = JsonSerializer.Deserialize(File.ReadAllText("./Config/config.json"),
- JsonSerializerSettings.Default);
- }
-
- return _config;
- }
-
- public static ForcedStatic GetForcedStatic()
- {
- lock (_forcedStaticLock)
- {
- if (_forcedStatic == null)
- _forcedStatic = Yaml.Deserializer
- .Deserialize(File.ReadAllText("./Config/forced_static.yaml"));
- }
-
- return _forcedStatic;
- }
-
- public static HashSet GetStaticWeaponIds()
- {
- lock (_staticWeaponIdsLock)
- {
- if (_staticWeaponIds == null) _staticWeaponIds = GetForcedStatic().StaticWeaponIds.ToHashSet();
- }
-
- return _staticWeaponIds;
- }
-
- public static Dictionary> GetForcedItems()
- {
- lock (_forcedItemsLock)
- {
- if (_forcedItems == null) _forcedItems = GetForcedStatic().ForcedItems;
- }
-
- return _forcedItems;
- }
-
- public static Dictionary> GetForcedLooseItems()
- {
- lock (_forcedLooseLock)
- {
- if (_forcedLoose == null)
- _forcedLoose = Yaml.Deserializer.Deserialize>>(
- File.ReadAllText("./Config/forced_loose.yaml"));
- }
-
- return _forcedLoose;
- }
-}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/CollectorConfig.cs b/source/LootDumpProcessor/Model/Config/CollectorConfig.cs
index 9c5d39e..42f8685 100644
--- a/source/LootDumpProcessor/Model/Config/CollectorConfig.cs
+++ b/source/LootDumpProcessor/Model/Config/CollectorConfig.cs
@@ -1,10 +1,12 @@
+using System.ComponentModel.DataAnnotations;
+using JetBrains.Annotations;
using LootDumpProcessor.Process.Collector;
namespace LootDumpProcessor.Model.Config;
-public class CollectorConfig
-{
- public CollectorType CollectorType { get; set; }
- public int MaxEntitiesBeforeDumping { get; set; }
- public string DumpLocation { get; set; }
-}
\ No newline at end of file
+[UsedImplicitly]
+public record CollectorConfig(
+ [Required] CollectorType CollectorType,
+ [Required] int MaxEntitiesBeforeDumping,
+ [Required] string DumpLocation
+);
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/Config.cs b/source/LootDumpProcessor/Model/Config/Config.cs
index 2d0f9a0..60f93b7 100644
--- a/source/LootDumpProcessor/Model/Config/Config.cs
+++ b/source/LootDumpProcessor/Model/Config/Config.cs
@@ -1,15 +1,19 @@
+using System.ComponentModel.DataAnnotations;
+using JetBrains.Annotations;
+
namespace LootDumpProcessor.Model.Config;
-public class Config
+[UsedImplicitly]
+public record Config
{
- public string ServerLocation { get; set; } = string.Empty;
- public bool ManualGarbageCollectionCalls { get; set; }
- public DataStorageConfig DataStorageConfig { get; set; }
- public ReaderConfig ReaderConfig { get; set; }
- public ProcessorConfig ProcessorConfig { get; set; }
- public DumpProcessorConfig DumpProcessorConfig { get; set; }
- public WriterConfig WriterConfig { get; set; }
- public CollectorConfig CollectorConfig { get; set; }
- public Dictionary ContainerIgnoreList { get; set; }
- public List MapsToProcess { get; set; }
+ [Required] public string ServerLocation { get; init; } = string.Empty;
+ [Required] public bool ManualGarbageCollectionCalls { get; init; }
+ [Required] public DataStorageConfig DataStorageConfig { get; init; } = null!;
+ [Required] public ReaderConfig ReaderConfig { get; init; } = null!;
+ [Required] public ProcessorConfig ProcessorConfig { get; init; } = null!;
+ [Required] public DumpProcessorConfig DumpProcessorConfig { get; init; } = null!;
+ [Required] public WriterConfig WriterConfig { get; init; } = null!;
+ [Required] public CollectorConfig CollectorConfig { get; init; } = null!;
+ [Required] public IReadOnlyDictionary ContainerIgnoreList { get; init; } = null!;
+ [Required] public IReadOnlyList MapsToProcess { get; init; } = null!;
}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/DataStorageConfig.cs b/source/LootDumpProcessor/Model/Config/DataStorageConfig.cs
index a6f9def..612bba4 100644
--- a/source/LootDumpProcessor/Model/Config/DataStorageConfig.cs
+++ b/source/LootDumpProcessor/Model/Config/DataStorageConfig.cs
@@ -1,10 +1,12 @@
+using System.ComponentModel.DataAnnotations;
+using JetBrains.Annotations;
using LootDumpProcessor.Storage;
namespace LootDumpProcessor.Model.Config;
-public class DataStorageConfig
-{
- public DataStorageTypes DataStorageType { get; set; } = DataStorageTypes.File;
- public string? FileDataStorageTempLocation { get; set; }
-}
\ No newline at end of file
+[UsedImplicitly]
+public record DataStorageConfig(
+ [Required] string FileDataStorageTempLocation,
+ [Required] DataStorageTypes DataStorageType = DataStorageTypes.File
+);
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/DumpProcessorConfig.cs b/source/LootDumpProcessor/Model/Config/DumpProcessorConfig.cs
index 6dfe09a..dc10f48 100644
--- a/source/LootDumpProcessor/Model/Config/DumpProcessorConfig.cs
+++ b/source/LootDumpProcessor/Model/Config/DumpProcessorConfig.cs
@@ -1,10 +1,12 @@
-using System.Text.Json.Serialization;
+using System.ComponentModel.DataAnnotations;
+using System.Text.Json.Serialization;
+using JetBrains.Annotations;
using LootDumpProcessor.Serializers.Json.Converters;
namespace LootDumpProcessor.Model.Config;
-public class DumpProcessorConfig
-{
- [JsonConverter(typeof(NetDateTimeConverter))] public DateTime SpawnContainerChanceIncludeAfterDate { get; set; }
-}
\ No newline at end of file
+[UsedImplicitly]
+public record DumpProcessorConfig(
+ [Required] [property: JsonConverter(typeof(NetDateTimeConverter))] DateTime SpawnContainerChanceIncludeAfterDate
+);
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/ForcedStatic.cs b/source/LootDumpProcessor/Model/Config/ForcedStatic.cs
index ef10aff..da32f67 100644
--- a/source/LootDumpProcessor/Model/Config/ForcedStatic.cs
+++ b/source/LootDumpProcessor/Model/Config/ForcedStatic.cs
@@ -1,11 +1,14 @@
+using System.Collections.Frozen;
+using JetBrains.Annotations;
using LootDumpProcessor.Model.Output.StaticContainer;
-using YamlDotNet.Serialization;
namespace LootDumpProcessor.Model.Config;
-public class ForcedStatic
+[UsedImplicitly]
+public class ForcedStatic(
+ IReadOnlyList staticWeaponIds, FrozenDictionary> forcedItems
+)
{
- [YamlMember(Alias = "static_weapon_ids")] public List StaticWeaponIds { get; set; }
-
- [YamlMember(Alias = "forced_items")] public Dictionary> ForcedItems { get; set; }
+ public readonly IReadOnlyList StaticWeaponIds = staticWeaponIds;
+ public readonly FrozenDictionary> ForcedItems = forcedItems;
}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/ForcedStaticDto.cs b/source/LootDumpProcessor/Model/Config/ForcedStaticDto.cs
new file mode 100644
index 0000000..e5aa6b2
--- /dev/null
+++ b/source/LootDumpProcessor/Model/Config/ForcedStaticDto.cs
@@ -0,0 +1,13 @@
+using JetBrains.Annotations;
+using LootDumpProcessor.Model.Output.StaticContainer;
+using YamlDotNet.Serialization;
+
+namespace LootDumpProcessor.Model.Config;
+
+[UsedImplicitly]
+public class ForcedStaticDto
+{
+ [YamlMember(Alias = "static_weapon_ids")] public List StaticWeaponIds { get; set; }
+
+ [YamlMember(Alias = "forced_items")] public Dictionary> ForcedItems { get; set; }
+}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/IntakeReaderConfig.cs b/source/LootDumpProcessor/Model/Config/IntakeReaderConfig.cs
index 961f6e5..1db5aec 100644
--- a/source/LootDumpProcessor/Model/Config/IntakeReaderConfig.cs
+++ b/source/LootDumpProcessor/Model/Config/IntakeReaderConfig.cs
@@ -1,7 +1,6 @@
+using JetBrains.Annotations;
+
namespace LootDumpProcessor.Model.Config;
-public class IntakeReaderConfig
-{
- public int MaxDumpsPerMap { get; set; } = 1500;
- public List IgnoredDumpLocations { get; set; } = new();
-}
\ No newline at end of file
+[UsedImplicitly]
+public record IntakeReaderConfig(IReadOnlyList IgnoredDumpLocations, int MaxDumpsPerMap = 1500);
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/ProcessorConfig.cs b/source/LootDumpProcessor/Model/Config/ProcessorConfig.cs
index 0e89f98..ad1a018 100644
--- a/source/LootDumpProcessor/Model/Config/ProcessorConfig.cs
+++ b/source/LootDumpProcessor/Model/Config/ProcessorConfig.cs
@@ -1,13 +1,6 @@
-using System.Text.Json.Serialization;
-
+using JetBrains.Annotations;
namespace LootDumpProcessor.Model.Config;
-public class ProcessorConfig
-{
- [JsonPropertyName("spawnPointToleranceForForced")] public double SpawnPointToleranceForForced { get; set; } = 99D;
-
-
- [JsonPropertyName("looseLootCountTolerancePercentage")]
- public double LooseLootCountTolerancePercentage { get; set; } = 75D;
-}
\ No newline at end of file
+[UsedImplicitly]
+public record ProcessorConfig(double SpawnPointToleranceForForced = 99, double LooseLootCountTolerancePercentage = 75);
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/ReaderConfig.cs b/source/LootDumpProcessor/Model/Config/ReaderConfig.cs
index 0627b2e..ba4f7db 100644
--- a/source/LootDumpProcessor/Model/Config/ReaderConfig.cs
+++ b/source/LootDumpProcessor/Model/Config/ReaderConfig.cs
@@ -1,9 +1,12 @@
+using System.ComponentModel.DataAnnotations;
+using JetBrains.Annotations;
+
namespace LootDumpProcessor.Model.Config;
-public class ReaderConfig
-{
- public IntakeReaderConfig? IntakeReaderConfig { get; set; }
- public List? DumpFilesLocation { get; set; }
- public string? ThresholdDate { get; set; }
- public bool ProcessSubFolders { get; set; }
-}
\ No newline at end of file
+[UsedImplicitly]
+public record ReaderConfig(
+ [Required] IntakeReaderConfig IntakeReaderConfig,
+ [Required] IReadOnlyList DumpFilesLocation,
+ string? ThresholdDate,
+ bool ProcessSubFolders = true
+);
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Model/Config/WriterConfig.cs b/source/LootDumpProcessor/Model/Config/WriterConfig.cs
index bb19e8f..b12f69f 100644
--- a/source/LootDumpProcessor/Model/Config/WriterConfig.cs
+++ b/source/LootDumpProcessor/Model/Config/WriterConfig.cs
@@ -1,9 +1,8 @@
-using System.Text.Json.Serialization;
+using System.ComponentModel.DataAnnotations;
+using JetBrains.Annotations;
namespace LootDumpProcessor.Model.Config;
-public class WriterConfig
-{
- [JsonPropertyName("outputLocation")] public string? OutputLocation { get; set; }
-}
\ No newline at end of file
+[UsedImplicitly]
+public record WriterConfig([Required] string OutputLocation);
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Collector/CollectorFactory.cs b/source/LootDumpProcessor/Process/Collector/CollectorFactory.cs
deleted file mode 100644
index e5bdd09..0000000
--- a/source/LootDumpProcessor/Process/Collector/CollectorFactory.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace LootDumpProcessor.Process.Collector;
-
-public static class CollectorFactory
-{
- private static ICollector? _collector;
-
- public static ICollector GetInstance()
- {
- if (_collector == null)
- _collector = LootDumpProcessorContext.GetConfig().CollectorConfig.CollectorType switch
- {
- CollectorType.Memory => new HashSetCollector(),
- CollectorType.Dump => new DumpCollector(),
- _ => throw new ArgumentOutOfRangeException()
- };
- return _collector;
- }
-}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Collector/DumpCollector.cs b/source/LootDumpProcessor/Process/Collector/DumpCollector.cs
index d0a19f4..2895a76 100644
--- a/source/LootDumpProcessor/Process/Collector/DumpCollector.cs
+++ b/source/LootDumpProcessor/Process/Collector/DumpCollector.cs
@@ -1,16 +1,18 @@
using System.Text.Json;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Model.Processing;
using LootDumpProcessor.Serializers.Json;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Process.Collector;
-public class DumpCollector : ICollector
+public class DumpCollector(IOptions config) : ICollector
{
- private static readonly string DumpLocation =
- $"{LootDumpProcessorContext.GetConfig().CollectorConfig.DumpLocation}/collector/";
+ private readonly Config _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
- private readonly List processedDumps =
- new(LootDumpProcessorContext.GetConfig().CollectorConfig.MaxEntitiesBeforeDumping + 50);
+ private string DumpLocation => Path.Combine(_config.CollectorConfig.DumpLocation, "collector");
+
+ private List ProcessedDumps => new(_config.CollectorConfig.MaxEntitiesBeforeDumping + 50);
private readonly object lockObject = new();
@@ -25,13 +27,13 @@ public class DumpCollector : ICollector
{
lock (lockObject)
{
- processedDumps.Add(parsedDump);
- if (processedDumps.Count > LootDumpProcessorContext.GetConfig().CollectorConfig.MaxEntitiesBeforeDumping)
+ ProcessedDumps.Add(parsedDump);
+ if (ProcessedDumps.Count > _config.CollectorConfig.MaxEntitiesBeforeDumping)
{
var fileName = $"collector-{DateTime.Now.ToString("yyyyMMddHHmmssfffff")}.json";
File.WriteAllText($"{DumpLocation}{fileName}",
- JsonSerializer.Serialize(processedDumps, JsonSerializerSettings.Default));
- processedDumps.Clear();
+ JsonSerializer.Serialize(ProcessedDumps, JsonSerializerSettings.Default));
+ ProcessedDumps.Clear();
}
}
}
@@ -39,10 +41,10 @@ public class DumpCollector : ICollector
public List Retrieve()
{
foreach (var file in Directory.GetFiles(DumpLocation))
- processedDumps.AddRange(JsonSerializer
+ ProcessedDumps.AddRange(JsonSerializer
.Deserialize>(File.ReadAllText(file), JsonSerializerSettings.Default));
- return processedDumps;
+ return ProcessedDumps;
}
public void Clear()
@@ -51,7 +53,7 @@ public class DumpCollector : ICollector
{
foreach (var file in Directory.GetFiles(DumpLocation)) File.Delete(file);
- processedDumps.Clear();
+ ProcessedDumps.Clear();
}
}
}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/IKeyGenerator.cs b/source/LootDumpProcessor/Process/IKeyGenerator.cs
deleted file mode 100644
index 5bf967e..0000000
--- a/source/LootDumpProcessor/Process/IKeyGenerator.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace LootDumpProcessor.Process;
-
-public interface IKeyGenerator
-{
- string Generate();
-}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Processor/v2/AmmoProcessor/AmmoProcessor.cs b/source/LootDumpProcessor/Process/Processor/AmmoProcessor/AmmoProcessor.cs
similarity index 93%
rename from source/LootDumpProcessor/Process/Processor/v2/AmmoProcessor/AmmoProcessor.cs
rename to source/LootDumpProcessor/Process/Processor/AmmoProcessor/AmmoProcessor.cs
index fe65694..5994eb5 100644
--- a/source/LootDumpProcessor/Process/Processor/v2/AmmoProcessor/AmmoProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/AmmoProcessor/AmmoProcessor.cs
@@ -1,8 +1,9 @@
using LootDumpProcessor.Model.Output;
using LootDumpProcessor.Model.Processing;
+using LootDumpProcessor.Process.Services.TarkovItemsProvider;
using Microsoft.Extensions.Logging;
-namespace LootDumpProcessor.Process.Processor.v2.AmmoProcessor;
+namespace LootDumpProcessor.Process.Processor.AmmoProcessor;
public class AmmoProcessor(ILogger logger, ITarkovItemsProvider tarkovItemsProvider) : IAmmoProcessor
{
diff --git a/source/LootDumpProcessor/Process/Processor/v2/AmmoProcessor/IAmmoProcessor.cs b/source/LootDumpProcessor/Process/Processor/AmmoProcessor/IAmmoProcessor.cs
similarity index 80%
rename from source/LootDumpProcessor/Process/Processor/v2/AmmoProcessor/IAmmoProcessor.cs
rename to source/LootDumpProcessor/Process/Processor/AmmoProcessor/IAmmoProcessor.cs
index d7e703d..9547ace 100644
--- a/source/LootDumpProcessor/Process/Processor/v2/AmmoProcessor/IAmmoProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/AmmoProcessor/IAmmoProcessor.cs
@@ -1,7 +1,7 @@
using LootDumpProcessor.Model.Output;
using LootDumpProcessor.Model.Processing;
-namespace LootDumpProcessor.Process.Processor.v2.AmmoProcessor;
+namespace LootDumpProcessor.Process.Processor.AmmoProcessor;
public interface IAmmoProcessor
{
diff --git a/source/LootDumpProcessor/Process/Processor/DumpProcessor/MultithreadSteppedDumpProcessor.cs b/source/LootDumpProcessor/Process/Processor/DumpProcessor/MultithreadSteppedDumpProcessor.cs
index 1e5aaea..0fea688 100644
--- a/source/LootDumpProcessor/Process/Processor/DumpProcessor/MultithreadSteppedDumpProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/DumpProcessor/MultithreadSteppedDumpProcessor.cs
@@ -1,20 +1,23 @@
using System.Collections.Concurrent;
using System.Text.Json;
using LootDumpProcessor.Model;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Model.Input;
using LootDumpProcessor.Model.Output;
using LootDumpProcessor.Model.Output.LooseLoot;
using LootDumpProcessor.Model.Output.StaticContainer;
using LootDumpProcessor.Model.Processing;
-using LootDumpProcessor.Process.Processor.v2.AmmoProcessor;
-using LootDumpProcessor.Process.Processor.v2.LooseLootProcessor;
-using LootDumpProcessor.Process.Processor.v2.StaticContainersProcessor;
-using LootDumpProcessor.Process.Processor.v2.StaticLootProcessor;
+using LootDumpProcessor.Process.Processor.AmmoProcessor;
+using LootDumpProcessor.Process.Processor.LooseLootProcessor;
+using LootDumpProcessor.Process.Processor.StaticContainersProcessor;
+using LootDumpProcessor.Process.Processor.StaticLootProcessor;
+using LootDumpProcessor.Process.Services.KeyGenerator;
using LootDumpProcessor.Serializers.Json;
using LootDumpProcessor.Storage;
using LootDumpProcessor.Storage.Collections;
using LootDumpProcessor.Utils;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Process.Processor.DumpProcessor;
@@ -23,7 +26,8 @@ public class MultithreadSteppedDumpProcessor(
IStaticContainersProcessor staticContainersProcessor,
IAmmoProcessor ammoProcessor,
ILooseLootProcessor looseLootProcessor,
- ILogger logger, IKeyGenerator keyGenerator
+ ILogger logger, IKeyGenerator keyGenerator, IDataStorage dataStorage,
+ IOptions config
)
: IDumpProcessor
{
@@ -45,8 +49,10 @@ public class MultithreadSteppedDumpProcessor(
private readonly IKeyGenerator
_keyGenerator = keyGenerator ?? throw new ArgumentNullException(nameof(keyGenerator));
- private static readonly IDataStorage _dataStorage = DataStorageFactory.GetInstance();
+ private readonly IDataStorage _dataStorage = dataStorage ?? throw new ArgumentNullException(nameof(dataStorage));
+ private readonly Config _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
+
public async Task> ProcessDumps(List dumps)
{
_logger.LogInformation("Starting final dump processing");
@@ -111,12 +117,12 @@ public class MultithreadSteppedDumpProcessor(
_logger.LogInformation("Processing loose loot distribution");
var looseLoot = new ConcurrentDictionary();
- Parallel.ForEach(dumpProcessData.MapCounts.Keys, parallelOptions, mapId =>
+ await Parallel.ForEachAsync(dumpProcessData.MapCounts.Keys, parallelOptions, async (mapId, _) =>
{
var mapCount = dumpProcessData.MapCounts[mapId];
var looseLootCount = dumpProcessData.LooseLootCounts[mapId];
var looseLootDistribution =
- _looseLootProcessor.CreateLooseLootDistribution(mapId, mapCount, looseLootCount);
+ await _looseLootProcessor.CreateLooseLootDistribution(mapId, mapCount, looseLootCount);
looseLoot[mapId] = looseLootDistribution;
});
_logger.LogInformation("Collecting loose loot distribution information");
@@ -159,8 +165,7 @@ public class MultithreadSteppedDumpProcessor(
}
else
{
- var mapStaticContainers =
- _staticContainersProcessor.CreateStaticWeaponsAndForcedContainers(dataDump);
+ var mapStaticContainers = await _staticContainersProcessor.CreateStaticWeaponsAndForcedContainers(dataDump);
var newStaticWeapons = mapStaticContainers.StaticWeapons.Where(x =>
!mapStaticLoot.StaticWeapons.Exists(y => y.Id == x.Id));
@@ -172,7 +177,7 @@ public class MultithreadSteppedDumpProcessor(
}
if (!mapStaticContainersAggregated.TryGetValue(mapId,
- out ConcurrentDictionary mapAggregatedDataDict))
+ out var mapAggregatedDataDict))
{
mapAggregatedDataDict = new ConcurrentDictionary();
mapStaticContainersAggregated.TryAdd(mapId, mapAggregatedDataDict);
@@ -182,9 +187,9 @@ public class MultithreadSteppedDumpProcessor(
IncrementMapCounterDictionaryValue(mapDumpCounter, mapId);
- var containerIgnoreListExists = LootDumpProcessorContext.GetConfig().ContainerIgnoreList
+ var containerIgnoreListExists = _config.ContainerIgnoreList
.TryGetValue(mapId, out var ignoreListForMap);
- foreach (var dynamicStaticContainer in _staticContainersProcessor.CreateDynamicStaticContainers(
+ foreach (var dynamicStaticContainer in await _staticContainersProcessor.CreateDynamicStaticContainers(
dataDump))
{
if (containerIgnoreListExists && ignoreListForMap.Contains(dynamicStaticContainer.Id)) continue;
@@ -193,16 +198,17 @@ public class MultithreadSteppedDumpProcessor(
mapAggregatedDataDict[dynamicStaticContainer] += 1;
}
- GCHandler.Collect();
+ if (_config.ManualGarbageCollectionCalls) GC.Collect();
}
- private static bool DumpWasMadeAfterConfigThresholdDate(PartialData dataDump) =>
+ private bool DumpWasMadeAfterConfigThresholdDate(PartialData dataDump) =>
FileDateParser.TryParseFileDate(dataDump.BasicInfo.FileName, out var fileDate) &&
fileDate.HasValue &&
- fileDate.Value > LootDumpProcessorContext.GetConfig().DumpProcessorConfig
+ fileDate.Value > _config.DumpProcessorConfig
.SpawnContainerChanceIncludeAfterDate;
- private static void IncrementMapCounterDictionaryValue(ConcurrentDictionary mapDumpCounter, string mapName)
+ private static void IncrementMapCounterDictionaryValue(ConcurrentDictionary mapDumpCounter,
+ string mapName)
{
if (!mapDumpCounter.TryAdd(mapName, 1)) mapDumpCounter[mapName] += 1;
}
@@ -247,7 +253,7 @@ public class MultithreadSteppedDumpProcessor(
partialFileMetaData = null;
tuple = null;
- GCHandler.Collect();
+ if (_config.ManualGarbageCollectionCalls) GC.Collect();
var parallelOptions = new ParallelOptions
{
@@ -266,14 +272,14 @@ public class MultithreadSteppedDumpProcessor(
_dataStorage.Store(dictionaryCounts);
dictionaryCounts = null;
- GCHandler.Collect();
+ if (_config.ManualGarbageCollectionCalls) GC.Collect();
_dataStorage.Store(actualDictionaryItemProperties);
actualDictionaryItemProperties = null;
- GCHandler.Collect();
+ if (_config.ManualGarbageCollectionCalls) GC.Collect();
_dataStorage.Store(looseLootCounts);
looseLootCounts = null;
- GCHandler.Collect();
+ if (_config.ManualGarbageCollectionCalls) GC.Collect();
});
return dumpProcessData;
}
diff --git a/source/LootDumpProcessor/Process/Processor/FileProcessor/FileProcessor.cs b/source/LootDumpProcessor/Process/Processor/FileProcessor/FileProcessor.cs
index 428c01b..522d27e 100644
--- a/source/LootDumpProcessor/Process/Processor/FileProcessor/FileProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/FileProcessor/FileProcessor.cs
@@ -1,32 +1,33 @@
using LootDumpProcessor.Model;
using LootDumpProcessor.Model.Processing;
-using LootDumpProcessor.Process.Processor.v2.LooseLootProcessor;
-using LootDumpProcessor.Process.Processor.v2.StaticLootProcessor;
+using LootDumpProcessor.Process.Processor.LooseLootProcessor;
+using LootDumpProcessor.Process.Processor.StaticLootProcessor;
using LootDumpProcessor.Storage;
using Microsoft.Extensions.Logging;
namespace LootDumpProcessor.Process.Processor.FileProcessor;
-public class FileProcessor : IFileProcessor
+public class FileProcessor(
+ IStaticLootProcessor staticLootProcessor,
+ ILooseLootProcessor looseLootProcessor,
+ ILogger logger, IDataStorage dataStorage
+)
+ : IFileProcessor
{
- private readonly IStaticLootProcessor _staticLootProcessor;
- private readonly ILooseLootProcessor _looseLootProcessor;
- private readonly ILogger _logger;
+ private readonly IStaticLootProcessor _staticLootProcessor = staticLootProcessor
+ ?? throw new ArgumentNullException(
+ nameof(staticLootProcessor));
- public FileProcessor(
- IStaticLootProcessor staticLootProcessor,
- ILooseLootProcessor looseLootProcessor,
- ILogger logger)
- {
- _staticLootProcessor = staticLootProcessor
- ?? throw new ArgumentNullException(nameof(staticLootProcessor));
- _looseLootProcessor = looseLootProcessor
- ?? throw new ArgumentNullException(nameof(looseLootProcessor));
- _logger = logger
- ?? throw new ArgumentNullException(nameof(logger));
- }
+ private readonly ILooseLootProcessor _looseLootProcessor = looseLootProcessor
+ ?? throw new ArgumentNullException(
+ nameof(looseLootProcessor));
- public PartialData Process(BasicInfo parsedData)
+ private readonly ILogger _logger = logger
+ ?? throw new ArgumentNullException(nameof(logger));
+
+ private readonly IDataStorage _dataStorage = dataStorage ?? throw new ArgumentNullException(nameof(dataStorage));
+
+ public async Task Process(BasicInfo parsedData)
{
_logger.LogDebug("Processing file {FileName}...", parsedData.FileName);
@@ -50,16 +51,16 @@ public class FileProcessor : IFileProcessor
ParsedDumpKey = (AbstractKey)dumpData.GetKey()
};
- if (!DataStorageFactory.GetInstance().Exists(dumpData.GetKey()))
+ if (!_dataStorage.Exists(dumpData.GetKey()))
{
_logger.LogDebug(
"Cache not found for {LookupIndex} processing.",
string.Join("/", dumpData.GetKey().GetLookupIndex())
);
- dumpData.Containers = _staticLootProcessor.PreProcessStaticLoot(staticLoot);
+ dumpData.Containers = await _staticLootProcessor.PreProcessStaticLoot(staticLoot);
dumpData.LooseLoot = _looseLootProcessor.PreProcessLooseLoot(looseLoot);
- DataStorageFactory.GetInstance().Store(dumpData);
+ dataStorage.Store(dumpData);
}
_logger.LogDebug("File {FileName} finished processing!", parsedData.FileName);
diff --git a/source/LootDumpProcessor/Process/Processor/FileProcessor/IFileProcessor.cs b/source/LootDumpProcessor/Process/Processor/FileProcessor/IFileProcessor.cs
index 04e66d6..d096a90 100644
--- a/source/LootDumpProcessor/Process/Processor/FileProcessor/IFileProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/FileProcessor/IFileProcessor.cs
@@ -4,5 +4,5 @@ namespace LootDumpProcessor.Process.Processor.FileProcessor;
public interface IFileProcessor
{
- PartialData Process(BasicInfo parsedData);
+ Task Process(BasicInfo parsedData);
}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Processor/v2/LooseLootProcessor/ILooseLootProcessor.cs b/source/LootDumpProcessor/Process/Processor/LooseLootProcessor/ILooseLootProcessor.cs
similarity index 62%
rename from source/LootDumpProcessor/Process/Processor/v2/LooseLootProcessor/ILooseLootProcessor.cs
rename to source/LootDumpProcessor/Process/Processor/LooseLootProcessor/ILooseLootProcessor.cs
index 94bf430..dc9bb65 100644
--- a/source/LootDumpProcessor/Process/Processor/v2/LooseLootProcessor/ILooseLootProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/LooseLootProcessor/ILooseLootProcessor.cs
@@ -3,15 +3,13 @@ using LootDumpProcessor.Model.Output.LooseLoot;
using LootDumpProcessor.Model.Processing;
using LootDumpProcessor.Storage;
-namespace LootDumpProcessor.Process.Processor.v2.LooseLootProcessor;
+namespace LootDumpProcessor.Process.Processor.LooseLootProcessor;
public interface ILooseLootProcessor
{
PreProcessedLooseLoot PreProcessLooseLoot(List looseLoot);
- LooseLootRoot CreateLooseLootDistribution(
- string mapId,
+ Task CreateLooseLootDistribution(string mapId,
int mapCount,
- IKey looseLootCountKey
- );
+ IKey looseLootCountKey);
}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Processor/v2/LooseLootProcessor/LooseLootProcessor.cs b/source/LootDumpProcessor/Process/Processor/LooseLootProcessor/LooseLootProcessor.cs
similarity index 88%
rename from source/LootDumpProcessor/Process/Processor/v2/LooseLootProcessor/LooseLootProcessor.cs
rename to source/LootDumpProcessor/Process/Processor/LooseLootProcessor/LooseLootProcessor.cs
index 123bddf..6174fb6 100644
--- a/source/LootDumpProcessor/Process/Processor/v2/LooseLootProcessor/LooseLootProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/LooseLootProcessor/LooseLootProcessor.cs
@@ -1,17 +1,24 @@
using LootDumpProcessor.Model;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Model.Output;
using LootDumpProcessor.Model.Output.LooseLoot;
using LootDumpProcessor.Model.Processing;
+using LootDumpProcessor.Process.Services.ComposedKeyGenerator;
+using LootDumpProcessor.Process.Services.ForcedItemsProvider;
+using LootDumpProcessor.Process.Services.KeyGenerator;
+using LootDumpProcessor.Process.Services.TarkovItemsProvider;
using LootDumpProcessor.Storage;
using LootDumpProcessor.Storage.Collections;
using LootDumpProcessor.Utils;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
-namespace LootDumpProcessor.Process.Processor.v2.LooseLootProcessor;
+namespace LootDumpProcessor.Process.Processor.LooseLootProcessor;
public class LooseLootProcessor(
ILogger logger, IDataStorage dataStorage, ITarkovItemsProvider tarkovItemsProvider,
- IComposedKeyGenerator composedKeyGenerator, IKeyGenerator keyGenerator
+ IComposedKeyGenerator composedKeyGenerator, IKeyGenerator keyGenerator, IOptions config,
+ IForcedItemsProvider forcedItemsProvider
)
: ILooseLootProcessor
{
@@ -30,6 +37,11 @@ public class LooseLootProcessor(
private readonly IKeyGenerator
_keyGenerator = keyGenerator ?? throw new ArgumentNullException(nameof(keyGenerator));
+ private readonly Config _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
+
+ private readonly IForcedItemsProvider _forcedItemsProvider =
+ forcedItemsProvider ?? throw new ArgumentNullException(nameof(forcedItemsProvider));
+
public PreProcessedLooseLoot PreProcessLooseLoot(List looseLoot)
{
var preProcessedLoot = new PreProcessedLooseLoot
@@ -70,25 +82,23 @@ public class LooseLootProcessor(
return preProcessedLoot;
}
- public LooseLootRoot CreateLooseLootDistribution(
- string mapId,
+ public async Task CreateLooseLootDistribution(string mapId,
int mapCount,
- IKey looseLootCountKey
- )
+ IKey looseLootCountKey)
{
- var config = LootDumpProcessorContext.GetConfig();
- var spawnPointTolerance = config.ProcessorConfig.SpawnPointToleranceForForced / 100.0;
+ var spawnPointTolerance = _config.ProcessorConfig.SpawnPointToleranceForForced / 100.0;
var looseLootDistribution = new LooseLootRoot();
var probabilities = new Dictionary();
var looseLootCountsItem = _dataStorage.GetItem(looseLootCountKey);
+ var forcedLooseItems = await _forcedItemsProvider.GetForcedLooseItems();
var counts = _dataStorage.GetItem>(looseLootCountsItem.Counts);
foreach (var (itemId, count) in counts) probabilities[itemId] = (double)count / mapCount;
var spawnPointCount = looseLootCountsItem.MapSpawnpointCount.Select(Convert.ToDouble).ToList();
var initialMean = CalculateMean(spawnPointCount);
- var tolerancePercentage = config.ProcessorConfig.LooseLootCountTolerancePercentage / 100.0;
+ var tolerancePercentage = _config.ProcessorConfig.LooseLootCountTolerancePercentage / 100.0;
var highThreshold = initialMean * (1 + tolerancePercentage);
looseLootCountsItem.MapSpawnpointCount = looseLootCountsItem.MapSpawnpointCount
@@ -137,7 +147,7 @@ public class LooseLootProcessor(
if (itemDistributions.Count == 1 &&
(_tarkovItemsProvider.IsQuestItem(itemDistributions[0].ComposedKey?.FirstItem?.Tpl) ||
- LootDumpProcessorContext.GetForcedLooseItems()[mapId]
+ forcedLooseItems[mapId]
.Contains(itemDistributions[0].ComposedKey?.FirstItem?.Tpl)))
{
var forcedSpawnPoint = new SpawnPointsForced
@@ -160,7 +170,7 @@ public class LooseLootProcessor(
_logger.LogWarning(
"Item: {ItemId} has > {Tolerance}% spawn chance in spawn point: {LocationId} but isn't in forced loot, adding to forced",
templateCopy.Id,
- config.ProcessorConfig.SpawnPointToleranceForForced,
+ _config.ProcessorConfig.SpawnPointToleranceForForced,
forcedSpawnPoint.LocationId
);
}
@@ -210,7 +220,7 @@ public class LooseLootProcessor(
.ToList();
var configuredForcedTemplates =
- new HashSet(LootDumpProcessorContext.GetForcedLooseItems()[mapId].Select(item => item));
+ new HashSet(forcedLooseItems[mapId].Select(item => item));
var foundForcedTemplates =
new HashSet(looseLootDistribution.SpawnPointsForced.Select(fp => fp.Template.Items[0].Tpl));
diff --git a/source/LootDumpProcessor/Process/Processor/StaticContainersProcessor/IStaticContainersProcessor.cs b/source/LootDumpProcessor/Process/Processor/StaticContainersProcessor/IStaticContainersProcessor.cs
new file mode 100644
index 0000000..a0a82ef
--- /dev/null
+++ b/source/LootDumpProcessor/Process/Processor/StaticContainersProcessor/IStaticContainersProcessor.cs
@@ -0,0 +1,11 @@
+using LootDumpProcessor.Model;
+using LootDumpProcessor.Model.Input;
+using LootDumpProcessor.Model.Output.StaticContainer;
+
+namespace LootDumpProcessor.Process.Processor.StaticContainersProcessor;
+
+public interface IStaticContainersProcessor
+{
+ Task CreateStaticWeaponsAndForcedContainers(RootData rawMapDump);
+ Task> CreateDynamicStaticContainers(RootData rawMapDump);
+}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Processor/v2/StaticContainersProcessor/StaticContainerProcessor.cs b/source/LootDumpProcessor/Process/Processor/StaticContainersProcessor/StaticContainerProcessor.cs
similarity index 64%
rename from source/LootDumpProcessor/Process/Processor/v2/StaticContainersProcessor/StaticContainerProcessor.cs
rename to source/LootDumpProcessor/Process/Processor/StaticContainersProcessor/StaticContainerProcessor.cs
index afad205..72aa1f4 100644
--- a/source/LootDumpProcessor/Process/Processor/v2/StaticContainersProcessor/StaticContainerProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/StaticContainersProcessor/StaticContainerProcessor.cs
@@ -1,21 +1,24 @@
using LootDumpProcessor.Model;
using LootDumpProcessor.Model.Input;
using LootDumpProcessor.Model.Output.StaticContainer;
+using LootDumpProcessor.Process.Services.ForcedItemsProvider;
using LootDumpProcessor.Utils;
using Microsoft.Extensions.Logging;
-namespace LootDumpProcessor.Process.Processor.v2.StaticContainersProcessor;
+namespace LootDumpProcessor.Process.Processor.StaticContainersProcessor;
-public class StaticContainersProcessor : IStaticContainersProcessor
+public class StaticContainersProcessor(
+ ILogger logger, IForcedItemsProvider forcedItemsProvider
+)
+ : IStaticContainersProcessor
{
- private readonly ILogger _logger;
+ private readonly ILogger _logger =
+ logger ?? throw new ArgumentNullException(nameof(logger));
- public StaticContainersProcessor(ILogger logger)
- {
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- }
+ private readonly IForcedItemsProvider _forcedItemsProvider =
+ forcedItemsProvider ?? throw new ArgumentNullException(nameof(forcedItemsProvider));
- public MapStaticLoot CreateStaticWeaponsAndForcedContainers(RootData rawMapDump)
+ public async Task CreateStaticWeaponsAndForcedContainers(RootData rawMapDump)
{
var locationLoot = rawMapDump.Data.LocationLoot;
var mapId = locationLoot.Id.ToLower();
@@ -25,6 +28,7 @@ public class StaticContainersProcessor : IStaticContainersProcessor
.ToList();
var staticWeapons = new List();
+ var forcedStatic = await _forcedItemsProvider.GetForcedStatic();
foreach (var lootPosition in staticLootPositions)
{
@@ -36,7 +40,7 @@ public class StaticContainersProcessor : IStaticContainersProcessor
var firstItemTpl = lootPosition.Items.First().Tpl;
- if (!LootDumpProcessorContext.GetStaticWeaponIds().Contains(firstItemTpl))
+ if (!forcedStatic.StaticWeaponIds.Contains(firstItemTpl))
continue;
var copiedLoot = ProcessorUtil.Copy(lootPosition);
@@ -44,26 +48,28 @@ public class StaticContainersProcessor : IStaticContainersProcessor
_logger.LogDebug("Added static weapon with ID {WeaponId} to Map {MapId}.", copiedLoot.Id, mapId);
}
- var forcedStaticItems = LootDumpProcessorContext.GetForcedItems()
- .TryGetValue(mapId, out List? forcedItems)
+ var forcedStaticItems = forcedStatic.ForcedItems
+ .TryGetValue(mapId, out var forcedItems)
? forcedItems
: new List();
var mapStaticLoot = new MapStaticLoot
{
StaticWeapons = staticWeapons,
- StaticForced = forcedStaticItems
+ StaticForced = forcedStaticItems.ToList()
};
_logger.LogInformation("Created static weapons and forced containers for Map {MapId}.", mapId);
return mapStaticLoot;
}
- public IReadOnlyList CreateDynamicStaticContainers(RootData rawMapDump)
+ public async Task> CreateDynamicStaticContainers(RootData rawMapDump)
{
+ var forcedStatic = await _forcedItemsProvider.GetForcedStatic();
+
var dynamicContainers = rawMapDump.Data.LocationLoot.Loot
.Where(loot => loot.IsContainer &&
- !LootDumpProcessorContext.GetStaticWeaponIds().Contains(loot.Items.FirstOrDefault()?.Tpl))
+ !forcedStatic.StaticWeaponIds.Contains(loot.Items.FirstOrDefault()?.Tpl))
.ToList();
foreach (var container in dynamicContainers)
diff --git a/source/LootDumpProcessor/Process/Processor/v2/StaticLootProcessor/IStaticLootProcessor.cs b/source/LootDumpProcessor/Process/Processor/StaticLootProcessor/IStaticLootProcessor.cs
similarity index 65%
rename from source/LootDumpProcessor/Process/Processor/v2/StaticLootProcessor/IStaticLootProcessor.cs
rename to source/LootDumpProcessor/Process/Processor/StaticLootProcessor/IStaticLootProcessor.cs
index e58579b..6c8572c 100644
--- a/source/LootDumpProcessor/Process/Processor/v2/StaticLootProcessor/IStaticLootProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/StaticLootProcessor/IStaticLootProcessor.cs
@@ -2,11 +2,11 @@
using LootDumpProcessor.Model.Output;
using LootDumpProcessor.Model.Processing;
-namespace LootDumpProcessor.Process.Processor.v2.StaticLootProcessor;
+namespace LootDumpProcessor.Process.Processor.StaticLootProcessor;
public interface IStaticLootProcessor
{
- IReadOnlyList PreProcessStaticLoot(IReadOnlyList staticLoot);
+ Task> PreProcessStaticLoot(IReadOnlyList staticLoot);
IReadOnlyDictionary CreateStaticLootDistribution(
string mapName,
diff --git a/source/LootDumpProcessor/Process/Processor/v2/StaticLootProcessor/StaticLootProcessor.cs b/source/LootDumpProcessor/Process/Processor/StaticLootProcessor/StaticLootProcessor.cs
similarity index 85%
rename from source/LootDumpProcessor/Process/Processor/v2/StaticLootProcessor/StaticLootProcessor.cs
rename to source/LootDumpProcessor/Process/Processor/StaticLootProcessor/StaticLootProcessor.cs
index 72cdb67..0f28281 100644
--- a/source/LootDumpProcessor/Process/Processor/v2/StaticLootProcessor/StaticLootProcessor.cs
+++ b/source/LootDumpProcessor/Process/Processor/StaticLootProcessor/StaticLootProcessor.cs
@@ -1,16 +1,21 @@
using LootDumpProcessor.Model;
using LootDumpProcessor.Model.Output;
using LootDumpProcessor.Model.Processing;
+using LootDumpProcessor.Process.Services.ForcedItemsProvider;
using Microsoft.Extensions.Logging;
-namespace LootDumpProcessor.Process.Processor.v2.StaticLootProcessor;
+namespace LootDumpProcessor.Process.Processor.StaticLootProcessor;
-public class StaticLootProcessor(ILogger logger) : IStaticLootProcessor
+public class StaticLootProcessor(ILogger logger, IForcedItemsProvider forcedItemsProvider)
+ : IStaticLootProcessor
{
private readonly ILogger _logger =
logger ?? throw new ArgumentNullException(nameof(logger));
- public IReadOnlyList PreProcessStaticLoot(IReadOnlyList staticLoot)
+ private readonly IForcedItemsProvider _forcedItemsProvider =
+ forcedItemsProvider ?? throw new ArgumentNullException(nameof(forcedItemsProvider));
+
+ public async Task> PreProcessStaticLoot(IReadOnlyList staticLoot)
{
var nonWeaponContainers = new List();
@@ -24,7 +29,8 @@ public class StaticLootProcessor(ILogger logger) : IStaticL
var firstItemTpl = lootSpawn.Items[0].Tpl;
- if (!LootDumpProcessorContext.GetStaticWeaponIds().Contains(firstItemTpl))
+ var forcedStatic = await _forcedItemsProvider.GetForcedStatic();
+ if (!forcedStatic.StaticWeaponIds.Contains(firstItemTpl))
{
nonWeaponContainers.Add(new PreProcessedStaticLoot
{
diff --git a/source/LootDumpProcessor/Process/Processor/v2/StaticContainersProcessor/IStaticContainersProcessor.cs b/source/LootDumpProcessor/Process/Processor/v2/StaticContainersProcessor/IStaticContainersProcessor.cs
deleted file mode 100644
index ff151f2..0000000
--- a/source/LootDumpProcessor/Process/Processor/v2/StaticContainersProcessor/IStaticContainersProcessor.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using LootDumpProcessor.Model;
-using LootDumpProcessor.Model.Input;
-using LootDumpProcessor.Model.Output.StaticContainer;
-
-namespace LootDumpProcessor.Process.Processor.v2.StaticContainersProcessor;
-
-public interface IStaticContainersProcessor
-{
- MapStaticLoot CreateStaticWeaponsAndForcedContainers(RootData rawMapDump);
- IReadOnlyList CreateDynamicStaticContainers(RootData rawMapDump);
-}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/QueuePipeline.cs b/source/LootDumpProcessor/Process/QueuePipeline.cs
index db6de8f..2bb90b9 100644
--- a/source/LootDumpProcessor/Process/QueuePipeline.cs
+++ b/source/LootDumpProcessor/Process/QueuePipeline.cs
@@ -1,6 +1,7 @@
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text.Json;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Model.Input;
using LootDumpProcessor.Process.Collector;
using LootDumpProcessor.Process.Processor.DumpProcessor;
@@ -12,12 +13,13 @@ using LootDumpProcessor.Serializers.Json;
using LootDumpProcessor.Storage;
using LootDumpProcessor.Utils;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Process;
public class QueuePipeline(
IFileProcessor fileProcessor, IDumpProcessor dumpProcessor, ILogger logger, IFileFilter fileFilter,
- IIntakeReader intakeReader
+ IIntakeReader intakeReader, ICollector collector, IDataStorage dataStorage, IOptions config, IWriter writer
)
: IPipeline
{
@@ -34,25 +36,32 @@ public class QueuePipeline(
private readonly IIntakeReader
_intakeReader = intakeReader ?? throw new ArgumentNullException(nameof(intakeReader));
+ private readonly ICollector _collector = collector ?? throw new ArgumentNullException(nameof(collector));
+
+ private readonly IDataStorage _dataStorage = dataStorage ?? throw new ArgumentNullException(nameof(dataStorage));
+
+ private readonly IWriter _writer = writer ?? throw new ArgumentNullException(nameof(writer));
+
+ private readonly Config _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
+
private readonly List _filesToRename = new();
private readonly BlockingCollection _filesToProcess = new();
- private readonly List _mapNames = LootDumpProcessorContext.GetConfig().MapsToProcess;
+ private IReadOnlyList MapNames => _config.MapsToProcess;
public async Task Execute()
{
var stopwatch = Stopwatch.StartNew();
// Single collector instance to collect results
- var collector = CollectorFactory.GetInstance();
- collector.Setup();
+ _collector.Setup();
_logger.LogInformation("Gathering files to begin processing");
try
{
await FixFilesFromDumps();
- foreach (var mapName in _mapNames) await ProcessFilesFromDumpsPerMap(collector, mapName);
+ foreach (var mapName in MapNames) await ProcessFilesFromDumpsPerMap(_collector, mapName);
}
finally
{
@@ -64,7 +73,7 @@ public class QueuePipeline(
private List GatherFiles()
{
// Read locations
- var inputPath = LootDumpProcessorContext.GetConfig().ReaderConfig.DumpFilesLocation;
+ var inputPath = _config.ReaderConfig.DumpFilesLocation;
if (inputPath == null || inputPath.Count == 0)
throw new Exception("Reader dumpFilesLocations must be set to a valid value");
@@ -101,12 +110,12 @@ public class QueuePipeline(
return gatheredFiles;
}
- private Queue GetFileQueue(List inputPath)
+ private Queue GetFileQueue(IReadOnlyList inputPath)
{
var queuedPathsToProcess = new Queue();
var queuedFilesToProcess = new Queue();
- inputPath.ForEach(p => queuedPathsToProcess.Enqueue(p));
+ foreach (var path in inputPath) queuedPathsToProcess.Enqueue(path);
while (queuedPathsToProcess.TryDequeue(out var path))
{
@@ -114,7 +123,7 @@ public class QueuePipeline(
if (!Directory.Exists(path)) throw new Exception($"Input directory \"{path}\" could not be found");
// If we should process subfolder, queue them up as well
- if (LootDumpProcessorContext.GetConfig().ReaderConfig.ProcessSubFolders)
+ if (_config.ReaderConfig.ProcessSubFolders)
foreach (var directory in Directory.GetDirectories(path))
queuedPathsToProcess.Enqueue(directory);
@@ -138,13 +147,13 @@ public class QueuePipeline(
_logger.LogInformation("Files sorted and ready to begin pre-processing");
- Parallel.ForEach(_filesToProcess, file =>
+ await Parallel.ForEachAsync(_filesToProcess, async (file, _) =>
{
try
{
if (!_intakeReader.Read(file, out var basicInfo)) return;
- var partialData = _fileProcessor.Process(basicInfo);
+ var partialData = await _fileProcessor.Process(basicInfo);
collector.Hold(partialData);
}
catch (Exception e)
@@ -156,15 +165,14 @@ public class QueuePipeline(
_logger.LogInformation("Pre-processing finished");
// Single writer instance to collect results
- var writer = WriterFactory.GetInstance();
// Single collector instance to collect results
var partialData = collector.Retrieve();
var processedDumps = await _dumpProcessor.ProcessDumps(partialData);
- writer.WriteAll(processedDumps);
+ _writer.WriteAll(processedDumps);
// clear collector and datastorage as we process per map now
collector.Clear();
- DataStorageFactory.GetInstance().Clear();
+ _dataStorage.Clear();
}
///
@@ -172,7 +180,7 @@ public class QueuePipeline(
///
private async Task FixFilesFromDumps()
{
- var inputPath = LootDumpProcessorContext.GetConfig().ReaderConfig.DumpFilesLocation;
+ var inputPath = _config.ReaderConfig.DumpFilesLocation;
if (inputPath == null || inputPath.Count == 0)
throw new Exception("Reader dumpFilesLocations must be set to a valid value");
@@ -181,7 +189,7 @@ public class QueuePipeline(
await Parallel.ForEachAsync(_filesToRename, async (file, cancellationToken) =>
{
- if (_mapNames.Any(file.Contains)) return;
+ if (MapNames.Any(file.Contains)) return;
try
{
diff --git a/source/LootDumpProcessor/Process/Reader/Filters/JsonDumpFileFilter.cs b/source/LootDumpProcessor/Process/Reader/Filters/JsonDumpFileFilter.cs
index d13e43b..ebdc31d 100644
--- a/source/LootDumpProcessor/Process/Reader/Filters/JsonDumpFileFilter.cs
+++ b/source/LootDumpProcessor/Process/Reader/Filters/JsonDumpFileFilter.cs
@@ -1,6 +1,8 @@
using System.Globalization;
using System.Text.RegularExpressions;
+using LootDumpProcessor.Model.Config;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Process.Reader.Filters;
@@ -9,12 +11,14 @@ public class JsonDumpFileFilter : IFileFilter
private readonly ILogger _logger;
private readonly Regex _fileNameDateRegex = new("([0-9]{4}(-[0-9]{2}){2}_((-){0,1}[0-9]{2}){3})");
private readonly DateTime _parsedThresholdDate;
+ private readonly Config _config;
- public JsonDumpFileFilter(ILogger logger)
+ public JsonDumpFileFilter(ILogger logger, IOptions config)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
// Calculate parsed date from config threshold
- if (string.IsNullOrEmpty(LootDumpProcessorContext.GetConfig().ReaderConfig.ThresholdDate))
+ if (string.IsNullOrEmpty(_config.ReaderConfig.ThresholdDate))
{
_logger.LogWarning("ThresholdDate is null or empty in configs, defaulting to current day minus 30 days");
_parsedThresholdDate = DateTime.Now - TimeSpan.FromDays(30);
@@ -22,7 +26,7 @@ public class JsonDumpFileFilter : IFileFilter
else
{
_parsedThresholdDate = DateTime.ParseExact(
- LootDumpProcessorContext.GetConfig().ReaderConfig.ThresholdDate,
+ _config.ReaderConfig.ThresholdDate,
"yyyy-MM-dd",
CultureInfo.InvariantCulture
);
diff --git a/source/LootDumpProcessor/Process/Reader/Intake/JsonFileIntakeReader.cs b/source/LootDumpProcessor/Process/Reader/Intake/JsonFileIntakeReader.cs
index 683cab1..b0dc91d 100644
--- a/source/LootDumpProcessor/Process/Reader/Intake/JsonFileIntakeReader.cs
+++ b/source/LootDumpProcessor/Process/Reader/Intake/JsonFileIntakeReader.cs
@@ -1,19 +1,23 @@
using System.Collections.Concurrent;
using System.Text.Json;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Model.Input;
using LootDumpProcessor.Model.Processing;
using LootDumpProcessor.Serializers.Json;
using LootDumpProcessor.Utils;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Process.Reader.Intake;
-public class JsonFileIntakeReader(ILogger logger) : IIntakeReader
+public class JsonFileIntakeReader(ILogger logger, IOptions config) : IIntakeReader
{
private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- private readonly HashSet? _ignoredLocations = LootDumpProcessorContext.GetConfig()
- .ReaderConfig.IntakeReaderConfig?.IgnoredDumpLocations.ToHashSet();
+ private readonly Config _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
+
+ private HashSet IgnoredLocations => _config
+ .ReaderConfig.IntakeReaderConfig.IgnoredDumpLocations.ToHashSet();
private readonly ConcurrentDictionary _totalMapDumpsCounter = new();
@@ -43,14 +47,14 @@ public class JsonFileIntakeReader(ILogger logger) : IIntak
_logger.LogError("Could not parse date from file: {File}", file);
var fi = JsonSerializer.Deserialize(fileData, JsonSerializerSettings.Default);
- if (fi?.Data.LocationLoot.Name != null && (!_ignoredLocations?.Contains(fi.Data.LocationLoot.Name) ?? true))
+ if (fi?.Data.LocationLoot.Name != null && (!IgnoredLocations?.Contains(fi.Data.LocationLoot.Name) ?? true))
{
var mapName = fi.Data.LocationLoot.Name;
var mapId = fi.Data.LocationLoot.Id.ToLower();
var counter = _totalMapDumpsCounter.AddOrUpdate(mapName, 0, (_, current) => current);
- var maxDumpsPerMap = LootDumpProcessorContext.GetConfig()
+ var maxDumpsPerMap = _config
.ReaderConfig.IntakeReaderConfig?.MaxDumpsPerMap ?? 1500;
if (counter < maxDumpsPerMap)
diff --git a/source/LootDumpProcessor/Process/ComposedKeyGenerator.cs b/source/LootDumpProcessor/Process/Services/ComposedKeyGenerator/ComposedKeyGenerator.cs
similarity index 84%
rename from source/LootDumpProcessor/Process/ComposedKeyGenerator.cs
rename to source/LootDumpProcessor/Process/Services/ComposedKeyGenerator/ComposedKeyGenerator.cs
index d552d56..8e5d49c 100644
--- a/source/LootDumpProcessor/Process/ComposedKeyGenerator.cs
+++ b/source/LootDumpProcessor/Process/Services/ComposedKeyGenerator/ComposedKeyGenerator.cs
@@ -1,8 +1,10 @@
using System.Globalization;
using LootDumpProcessor.Model;
using LootDumpProcessor.Model.Processing;
+using LootDumpProcessor.Process.Services.KeyGenerator;
+using LootDumpProcessor.Process.Services.TarkovItemsProvider;
-namespace LootDumpProcessor.Process;
+namespace LootDumpProcessor.Process.Services.ComposedKeyGenerator;
public class ComposedKeyGenerator(ITarkovItemsProvider tarkovItemsProvider, IKeyGenerator keyGenerator)
: IComposedKeyGenerator
diff --git a/source/LootDumpProcessor/Process/IComposedKeyGenerator.cs b/source/LootDumpProcessor/Process/Services/ComposedKeyGenerator/IComposedKeyGenerator.cs
similarity index 66%
rename from source/LootDumpProcessor/Process/IComposedKeyGenerator.cs
rename to source/LootDumpProcessor/Process/Services/ComposedKeyGenerator/IComposedKeyGenerator.cs
index 09d974e..af1187d 100644
--- a/source/LootDumpProcessor/Process/IComposedKeyGenerator.cs
+++ b/source/LootDumpProcessor/Process/Services/ComposedKeyGenerator/IComposedKeyGenerator.cs
@@ -1,6 +1,6 @@
using LootDumpProcessor.Model;
-namespace LootDumpProcessor.Process;
+namespace LootDumpProcessor.Process.Services.ComposedKeyGenerator;
public interface IComposedKeyGenerator
{
diff --git a/source/LootDumpProcessor/Process/Services/ForcedItemsProvider/ForcedItemsProvider.cs b/source/LootDumpProcessor/Process/Services/ForcedItemsProvider/ForcedItemsProvider.cs
new file mode 100644
index 0000000..f06824f
--- /dev/null
+++ b/source/LootDumpProcessor/Process/Services/ForcedItemsProvider/ForcedItemsProvider.cs
@@ -0,0 +1,56 @@
+using System.Collections.Frozen;
+using System.Collections.Immutable;
+using LootDumpProcessor.Model.Config;
+using LootDumpProcessor.Model.Output.StaticContainer;
+using LootDumpProcessor.Serializers.Yaml;
+
+namespace LootDumpProcessor.Process.Services.ForcedItemsProvider;
+
+public class ForcedItemsProvider : IForcedItemsProvider
+{
+ private static readonly string ForcedStaticPath = Path.Combine("Config", "forced_static.yaml");
+ private static readonly string ForcedLooseLootPath = Path.Combine("Config", "forced_loose.yaml");
+
+ private ForcedStatic? _forcedStatic;
+ private FrozenDictionary>? _forcedLoose;
+
+ public async Task GetForcedStatic()
+ {
+ if (_forcedStatic is not null) return _forcedStatic;
+ _forcedStatic = await ReadForcedStatic();
+ return _forcedStatic;
+ }
+
+ private async Task ReadForcedStatic()
+ {
+ var forcedStaticContent = await File.ReadAllTextAsync(ForcedStaticPath);
+
+ // Workaround needed because YamlDotNet cannot deserialize properly
+ var forcedStaticDto = Yaml.Deserializer.Deserialize(forcedStaticContent);
+ var forcedStatic = new ForcedStatic(
+ forcedStaticDto.StaticWeaponIds.AsReadOnly(),
+ forcedStaticDto.ForcedItems.ToFrozenDictionary(
+ kvp => kvp.Key,
+ IReadOnlyList (kvp) => kvp.Value.AsReadOnly()
+ ));
+
+ return forcedStatic;
+ }
+
+ public async Task>> GetForcedLooseItems()
+ {
+ if (_forcedLoose is not null) return _forcedLoose;
+ _forcedLoose = await ReadForcedLooseItems();
+ return _forcedLoose;
+ }
+
+ private async Task>> ReadForcedLooseItems()
+ {
+ var forcedLooseContent = await File.ReadAllTextAsync(ForcedLooseLootPath);
+ var forcedLooseLoot = Yaml.Deserializer.Deserialize>>(forcedLooseContent);
+ return forcedLooseLoot.ToFrozenDictionary(
+ pair => pair.Key,
+ pair => ImmutableHashSet.CreateRange(pair.Value)
+ );
+ }
+}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Services/ForcedItemsProvider/IForcedItemsProvider.cs b/source/LootDumpProcessor/Process/Services/ForcedItemsProvider/IForcedItemsProvider.cs
new file mode 100644
index 0000000..50a9214
--- /dev/null
+++ b/source/LootDumpProcessor/Process/Services/ForcedItemsProvider/IForcedItemsProvider.cs
@@ -0,0 +1,11 @@
+using System.Collections.Frozen;
+using System.Collections.Immutable;
+using LootDumpProcessor.Model.Config;
+
+namespace LootDumpProcessor.Process.Services.ForcedItemsProvider;
+
+public interface IForcedItemsProvider
+{
+ Task GetForcedStatic();
+ Task>> GetForcedLooseItems();
+}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/Services/KeyGenerator/IKeyGenerator.cs b/source/LootDumpProcessor/Process/Services/KeyGenerator/IKeyGenerator.cs
new file mode 100644
index 0000000..0c951df
--- /dev/null
+++ b/source/LootDumpProcessor/Process/Services/KeyGenerator/IKeyGenerator.cs
@@ -0,0 +1,6 @@
+namespace LootDumpProcessor.Process.Services.KeyGenerator;
+
+public interface IKeyGenerator
+{
+ string Generate();
+}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Process/NumericKeyGenerator.cs b/source/LootDumpProcessor/Process/Services/KeyGenerator/NumericKeyGenerator.cs
similarity index 79%
rename from source/LootDumpProcessor/Process/NumericKeyGenerator.cs
rename to source/LootDumpProcessor/Process/Services/KeyGenerator/NumericKeyGenerator.cs
index a224509..947dc39 100644
--- a/source/LootDumpProcessor/Process/NumericKeyGenerator.cs
+++ b/source/LootDumpProcessor/Process/Services/KeyGenerator/NumericKeyGenerator.cs
@@ -1,4 +1,4 @@
-namespace LootDumpProcessor.Process;
+namespace LootDumpProcessor.Process.Services.KeyGenerator;
public class NumericKeyGenerator : IKeyGenerator
{
diff --git a/source/LootDumpProcessor/Process/ITarkovItemsProvider.cs b/source/LootDumpProcessor/Process/Services/TarkovItemsProvider/ITarkovItemsProvider.cs
similarity index 74%
rename from source/LootDumpProcessor/Process/ITarkovItemsProvider.cs
rename to source/LootDumpProcessor/Process/Services/TarkovItemsProvider/ITarkovItemsProvider.cs
index ca0c9fc..737fbfb 100644
--- a/source/LootDumpProcessor/Process/ITarkovItemsProvider.cs
+++ b/source/LootDumpProcessor/Process/Services/TarkovItemsProvider/ITarkovItemsProvider.cs
@@ -1,4 +1,4 @@
-namespace LootDumpProcessor.Process;
+namespace LootDumpProcessor.Process.Services.TarkovItemsProvider;
public interface ITarkovItemsProvider
{
diff --git a/source/LootDumpProcessor/Process/TarkovItemsProvider.cs b/source/LootDumpProcessor/Process/Services/TarkovItemsProvider/TarkovItemsProvider.cs
similarity index 91%
rename from source/LootDumpProcessor/Process/TarkovItemsProvider.cs
rename to source/LootDumpProcessor/Process/Services/TarkovItemsProvider/TarkovItemsProvider.cs
index 62dac1f..1d1479b 100644
--- a/source/LootDumpProcessor/Process/TarkovItemsProvider.cs
+++ b/source/LootDumpProcessor/Process/Services/TarkovItemsProvider/TarkovItemsProvider.cs
@@ -1,22 +1,26 @@
using System.Collections.Frozen;
using System.Text.Json;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Model.Tarkov;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
-namespace LootDumpProcessor.Process;
+namespace LootDumpProcessor.Process.Services.TarkovItemsProvider;
public class TarkovItemsProvider : ITarkovItemsProvider
{
private readonly ILogger _logger;
private readonly FrozenDictionary? _items;
+ private readonly Config _config;
- private static readonly string ItemsFilePath = Path.Combine(
- LootDumpProcessorContext.GetConfig().ServerLocation,
+ private string ItemsFilePath => Path.Combine(
+ _config.ServerLocation,
"project", "assets", "database", "templates", "items.json");
- public TarkovItemsProvider(ILogger logger)
+ public TarkovItemsProvider(ILogger logger, IOptions config)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
try
{
diff --git a/source/LootDumpProcessor/Process/Writer/FileWriter.cs b/source/LootDumpProcessor/Process/Writer/FileWriter.cs
index 8866f46..be769a8 100644
--- a/source/LootDumpProcessor/Process/Writer/FileWriter.cs
+++ b/source/LootDumpProcessor/Process/Writer/FileWriter.cs
@@ -1,18 +1,21 @@
using System.Text.Json;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Model.Output;
using LootDumpProcessor.Model.Output.LooseLoot;
using LootDumpProcessor.Model.Output.StaticContainer;
using LootDumpProcessor.Serializers.Json;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Process.Writer;
public class FileWriter : IWriter
{
- private static readonly string _outputPath;
+ private readonly string _outputPath;
- static FileWriter()
+ public FileWriter(IOptions config)
{
- var path = LootDumpProcessorContext.GetConfig().WriterConfig.OutputLocation;
+ var config1 = (config ?? throw new ArgumentNullException(nameof(config))).Value;
+ var path = config1.WriterConfig.OutputLocation;
if (string.IsNullOrEmpty(path))
throw new Exception("Output directory must be set in WriterConfigs");
diff --git a/source/LootDumpProcessor/Process/Writer/WriterFactory.cs b/source/LootDumpProcessor/Process/Writer/WriterFactory.cs
deleted file mode 100644
index 67e5eae..0000000
--- a/source/LootDumpProcessor/Process/Writer/WriterFactory.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace LootDumpProcessor.Process.Writer;
-
-public static class WriterFactory
-{
- public static IWriter GetInstance() =>
- // implement actual factory someday
- new FileWriter();
-}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Program.cs b/source/LootDumpProcessor/Program.cs
index 6df3a17..749ed2f 100644
--- a/source/LootDumpProcessor/Program.cs
+++ b/source/LootDumpProcessor/Program.cs
@@ -1,15 +1,5 @@
using LootDumpProcessor.Process;
-using LootDumpProcessor.Process.Processor.DumpProcessor;
-using LootDumpProcessor.Process.Processor.FileProcessor;
-using LootDumpProcessor.Process.Processor.v2.AmmoProcessor;
-using LootDumpProcessor.Process.Processor.v2.LooseLootProcessor;
-using LootDumpProcessor.Process.Processor.v2.StaticContainersProcessor;
-using LootDumpProcessor.Process.Processor.v2.StaticLootProcessor;
-using LootDumpProcessor.Process.Reader.Filters;
-using LootDumpProcessor.Process.Reader.Intake;
-using LootDumpProcessor.Storage;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
namespace LootDumpProcessor;
@@ -18,33 +8,11 @@ public static class Program
public static async Task Main()
{
var services = new ServiceCollection();
- RegisterServices(services);
+ services.AddLootDumpProcessor();
await using var serviceProvider = services.BuildServiceProvider();
- // startup the pipeline
var pipeline = serviceProvider.GetRequiredService();
await pipeline.Execute();
}
-
- private static void RegisterServices(ServiceCollection services)
- {
- services.AddLogging(configure => configure.AddConsole());
-
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
-
- services.AddSingleton();
- services.AddSingleton(_ => DataStorageFactory.GetInstance());
- services.AddSingleton();
- services.AddTransient();
-
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- }
}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/ServiceCollectionExtensions.cs b/source/LootDumpProcessor/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000..6f90459
--- /dev/null
+++ b/source/LootDumpProcessor/ServiceCollectionExtensions.cs
@@ -0,0 +1,103 @@
+using LootDumpProcessor.Model.Config;
+using LootDumpProcessor.Process;
+using LootDumpProcessor.Process.Collector;
+using LootDumpProcessor.Process.Processor.AmmoProcessor;
+using LootDumpProcessor.Process.Processor.DumpProcessor;
+using LootDumpProcessor.Process.Processor.FileProcessor;
+using LootDumpProcessor.Process.Processor.LooseLootProcessor;
+using LootDumpProcessor.Process.Processor.StaticContainersProcessor;
+using LootDumpProcessor.Process.Processor.StaticLootProcessor;
+using LootDumpProcessor.Process.Reader.Filters;
+using LootDumpProcessor.Process.Reader.Intake;
+using LootDumpProcessor.Process.Services.ComposedKeyGenerator;
+using LootDumpProcessor.Process.Services.ForcedItemsProvider;
+using LootDumpProcessor.Process.Services.KeyGenerator;
+using LootDumpProcessor.Process.Services.TarkovItemsProvider;
+using LootDumpProcessor.Process.Writer;
+using LootDumpProcessor.Storage;
+using LootDumpProcessor.Storage.Implementations.File;
+using LootDumpProcessor.Storage.Implementations.Memory;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace LootDumpProcessor;
+
+public static class ServiceCollectionExtensions
+{
+ public static void AddLootDumpProcessor(this ServiceCollection services)
+ {
+ services.AddLogging(configure => configure.AddConsole());
+ AddConfiguration(services);
+ AddCollector(services);
+ AddDataStorage(services);
+ RegisterProcessors(services);
+
+ services.AddSingleton();
+
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddTransient();
+
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ }
+
+ private static void AddConfiguration(IServiceCollection services)
+ {
+ const string configPath = "Config/config.json";
+ var configuration = new ConfigurationBuilder()
+ .AddJsonFile(configPath)
+ .AddEnvironmentVariables()
+ .Build();
+
+ services.AddOptions()
+ .Bind(configuration)
+ .ValidateDataAnnotations()
+ .ValidateOnStart();
+ }
+
+ private static void RegisterProcessors(IServiceCollection services)
+ {
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ }
+
+ private static void AddCollector(IServiceCollection services)
+ {
+ services.AddSingleton(provider =>
+ {
+ var config = provider.GetRequiredService>();
+ var collectorType = config.Value.CollectorConfig.CollectorType;
+ return collectorType switch
+ {
+ CollectorType.Memory => new HashSetCollector(),
+ CollectorType.Dump => new DumpCollector(config),
+ _ => throw new ArgumentOutOfRangeException($"CollectorType '{collectorType} is not supported'")
+ };
+ });
+ }
+
+ private static void AddDataStorage(IServiceCollection services)
+ {
+ services.AddSingleton(provider =>
+ {
+ var config = provider.GetRequiredService>().Value;
+ var dataStorageType = config.DataStorageConfig.DataStorageType;
+ return dataStorageType switch
+ {
+ DataStorageTypes.File => new FileDataStorage(provider.GetRequiredService()),
+ DataStorageTypes.Memory => new MemoryDataStorage(),
+ _ => throw new ArgumentOutOfRangeException($"DataStorageType '{dataStorageType} is not supported'")
+ };
+ });
+ }
+}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Storage/DataStorageFactory.cs b/source/LootDumpProcessor/Storage/DataStorageFactory.cs
deleted file mode 100644
index 6fb5ae0..0000000
--- a/source/LootDumpProcessor/Storage/DataStorageFactory.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.Collections.Concurrent;
-using LootDumpProcessor.Storage.Implementations.File;
-using LootDumpProcessor.Storage.Implementations.Memory;
-
-namespace LootDumpProcessor.Storage;
-
-public static class DataStorageFactory
-{
- private static readonly ConcurrentDictionary DataStorage = new();
-
- /**
- * Requires LootDumpProcessorContext to be initialized before using
- */
- public static IDataStorage GetInstance() =>
- GetInstance(LootDumpProcessorContext.GetConfig().DataStorageConfig.DataStorageType);
-
- private static IDataStorage GetInstance(DataStorageTypes type)
- {
- if (DataStorage.TryGetValue(type, out var dataStorage)) return dataStorage;
-
- dataStorage = type switch
- {
- DataStorageTypes.File => new FileDataStorage(),
- DataStorageTypes.Memory => new MemoryDataStorage(),
- _ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
- };
-
- DataStorage.TryAdd(type, dataStorage);
-
- return dataStorage;
- }
-}
\ No newline at end of file
diff --git a/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs b/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs
index c132999..a4a459e 100644
--- a/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs
+++ b/source/LootDumpProcessor/Storage/Implementations/File/FileDataStorage.cs
@@ -1,16 +1,19 @@
namespace LootDumpProcessor.Storage.Implementations.File;
-public class FileDataStorage : IDataStorage
+public class FileDataStorage(StoreHandlerFactory storeHandlerFactory) : IDataStorage
{
+ private readonly StoreHandlerFactory _storeHandlerFactory =
+ storeHandlerFactory ?? throw new ArgumentNullException(nameof(storeHandlerFactory));
+
public void Store(TEntity entity) where TEntity : IKeyable
{
- StoreHandlerFactory.GetInstance(entity.GetKey().GetKeyType()).Store(entity);
+ _storeHandlerFactory.GetInstance(entity.GetKey().GetKeyType()).Store(entity);
}
- public bool Exists(IKey key) => StoreHandlerFactory.GetInstance(key.GetKeyType()).Exists(key);
+ public bool Exists(IKey key) => _storeHandlerFactory.GetInstance(key.GetKeyType()).Exists(key);
public T GetItem(IKey key) where T : IKeyable =>
- StoreHandlerFactory.GetInstance(key.GetKeyType()).Retrieve(key);
+ _storeHandlerFactory.GetInstance(key.GetKeyType()).Retrieve(key);
public void Clear()
{
diff --git a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs
index 5793226..b1c4685 100644
--- a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs
+++ b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/AbstractStoreHandler.cs
@@ -1,10 +1,14 @@
using System.Text.Json;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Serializers.Json;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Storage.Implementations.File.Handlers;
-public abstract class AbstractStoreHandler : IStoreHandler
+public abstract class AbstractStoreHandler(IOptions config) : IStoreHandler
{
+ private readonly Config _config = (config ?? throw new ArgumentNullException(nameof(config))).Value;
+
public void Store(TEntity entity, bool failIfDuplicate = true) where TEntity : IKeyable
{
var locationWithFile = GetLocation(entity.GetKey());
@@ -34,8 +38,8 @@ public abstract class AbstractStoreHandler : IStoreHandler
protected virtual string GetBaseLocation()
{
var location =
- string.IsNullOrEmpty(LootDumpProcessorContext.GetConfig().DataStorageConfig.FileDataStorageTempLocation)
- ? LootDumpProcessorContext.GetConfig().DataStorageConfig.FileDataStorageTempLocation
+ string.IsNullOrEmpty(_config.DataStorageConfig.FileDataStorageTempLocation)
+ ? _config.DataStorageConfig.FileDataStorageTempLocation
: Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
return $"{location}/SPT/tmp/LootGen";
diff --git a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/FlatStoreHandler.cs b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/FlatStoreHandler.cs
index d8c9a9f..63f2eb8 100644
--- a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/FlatStoreHandler.cs
+++ b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/FlatStoreHandler.cs
@@ -1,6 +1,9 @@
+using LootDumpProcessor.Model.Config;
+using Microsoft.Extensions.Options;
+
namespace LootDumpProcessor.Storage.Implementations.File.Handlers;
-public class FlatStoreHandler : AbstractStoreHandler
+public class FlatStoreHandler(IOptions config) : AbstractStoreHandler(config)
{
protected override string GetLocation(IKey key)
{
diff --git a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/SubdivisionedStoreHandler.cs b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/SubdivisionedStoreHandler.cs
index e720d42..7dc3d81 100644
--- a/source/LootDumpProcessor/Storage/Implementations/File/Handlers/SubdivisionedStoreHandler.cs
+++ b/source/LootDumpProcessor/Storage/Implementations/File/Handlers/SubdivisionedStoreHandler.cs
@@ -1,6 +1,9 @@
+using LootDumpProcessor.Model.Config;
+using Microsoft.Extensions.Options;
+
namespace LootDumpProcessor.Storage.Implementations.File.Handlers;
-public class SubdivisionedStoreHandler : AbstractStoreHandler
+public class SubdivisionedStoreHandler(IOptions config) : AbstractStoreHandler(config)
{
protected override string GetLocation(IKey key)
{
diff --git a/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs b/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs
index c09a3aa..1ca698f 100644
--- a/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs
+++ b/source/LootDumpProcessor/Storage/Implementations/File/StoreHandlerFactory.cs
@@ -1,20 +1,27 @@
using System.Collections.Concurrent;
+using LootDumpProcessor.Model.Config;
using LootDumpProcessor.Storage.Implementations.File.Handlers;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
namespace LootDumpProcessor.Storage.Implementations.File;
-public class StoreHandlerFactory
+public class StoreHandlerFactory(IServiceProvider serviceProvider)
{
+ private readonly IServiceProvider _serviceProvider =
+ serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+
private static readonly ConcurrentDictionary Handlers = new();
- public static IStoreHandler GetInstance(KeyType type)
+ public IStoreHandler GetInstance(KeyType type)
{
if (Handlers.TryGetValue(type, out var handler)) return handler;
+ var config = _serviceProvider.GetRequiredService>();
handler = type switch
{
- KeyType.Unique => new FlatStoreHandler(),
- KeyType.Subdivisioned => new SubdivisionedStoreHandler(),
+ KeyType.Unique => new FlatStoreHandler(config),
+ KeyType.Subdivisioned => new SubdivisionedStoreHandler(config),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
Handlers.TryAdd(type, handler);