mirror of
https://github.com/sp-tarkov/loot-dump-processor.git
synced 2025-02-13 03:50:45 -05:00
Refactored key generation and improved type safety across storage components
This commit is contained in:
parent
02802ddc10
commit
9e9933bd32
@ -1,6 +1,3 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
||||
namespace LootDumpProcessor.Model.Config;
|
||||
|
||||
public class ReaderConfig
|
||||
|
@ -1,22 +1,24 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using LootDumpProcessor.Storage;
|
||||
using LootDumpProcessor.Utils;
|
||||
|
||||
|
||||
namespace LootDumpProcessor.Model.Processing;
|
||||
|
||||
public class LooseLootCounts : IKeyable
|
||||
{
|
||||
[JsonPropertyName("__id__")] public string __ID { get; set; } = KeyGenerator.GetNextKey();
|
||||
[JsonPropertyName("__id__")] private string Id { get; set; }
|
||||
|
||||
public IKey Counts { get; set; }
|
||||
|
||||
// public IKey Items { get; set; }
|
||||
public IKey ItemProperties { get; set; }
|
||||
public List<int> MapSpawnpointCount { get; set; } = new();
|
||||
|
||||
public IKey GetKey()
|
||||
public LooseLootCounts(string id, IKey counts, IKey itemProperties)
|
||||
{
|
||||
return new FlatUniqueKey(new[] { __ID });
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(id);
|
||||
Id = id;
|
||||
Counts = counts ?? throw new ArgumentNullException(nameof(counts));
|
||||
ItemProperties = itemProperties ?? throw new ArgumentNullException(nameof(itemProperties));
|
||||
}
|
||||
|
||||
public IKey GetKey() => new FlatUniqueKey([Id]);
|
||||
}
|
@ -7,70 +7,63 @@ namespace LootDumpProcessor.Model;
|
||||
|
||||
public class Template : IKeyable, ICloneable
|
||||
{
|
||||
[JsonIgnore] public string __ID { get; } = KeyGenerator.GetNextKey();
|
||||
[JsonIgnore] public string internalId { get; }
|
||||
public string Id { get; set; }
|
||||
public bool IsContainer { get; set; }
|
||||
public bool UseGravity { get; set; }
|
||||
public bool RandomRotation { get; set; }
|
||||
public Vector3 Position { get; set; }
|
||||
public Vector3 Rotation { get; set; }
|
||||
public bool IsGroupPosition { get; set; }
|
||||
public List<GroupPosition> GroupPositions { get; set; }
|
||||
public bool IsAlwaysSpawn { get; set; }
|
||||
public string Root { get; set; }
|
||||
public List<Item> Items { get; set; }
|
||||
|
||||
public Template(string internalId, string id, bool isContainer, bool useGravity, bool randomRotation,
|
||||
Vector3 position, Vector3 rotation, bool isGroupPosition, List<GroupPosition> groupPositions,
|
||||
bool isAlwaysSpawn, string root, List<Item> items)
|
||||
{
|
||||
this.internalId = internalId;
|
||||
Id = id;
|
||||
IsContainer = isContainer;
|
||||
UseGravity = useGravity;
|
||||
RandomRotation = randomRotation;
|
||||
Position = position;
|
||||
Rotation = rotation;
|
||||
IsGroupPosition = isGroupPosition;
|
||||
GroupPositions = groupPositions;
|
||||
IsAlwaysSpawn = isAlwaysSpawn;
|
||||
Root = root;
|
||||
Items = items;
|
||||
}
|
||||
|
||||
public string? Id { get; set; }
|
||||
|
||||
|
||||
public bool? IsContainer { get; set; }
|
||||
|
||||
|
||||
public bool? UseGravity { get; set; }
|
||||
|
||||
|
||||
public bool? RandomRotation { get; set; }
|
||||
|
||||
|
||||
public Vector3? Position { get; set; }
|
||||
|
||||
|
||||
public Vector3? Rotation { get; set; }
|
||||
|
||||
|
||||
public bool? IsGroupPosition { get; set; }
|
||||
|
||||
|
||||
public List<GroupPosition>? GroupPositions { get; set; }
|
||||
|
||||
|
||||
public bool? IsAlwaysSpawn { get; set; }
|
||||
|
||||
|
||||
public string? Root { get; set; }
|
||||
|
||||
|
||||
public required List<Item> Items { get; set; }
|
||||
|
||||
protected bool Equals(Template other) => Id == other.Id;
|
||||
private bool Equals(Template other) => Id == other.Id;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != GetType()) return false;
|
||||
return Equals((Template)obj);
|
||||
return obj.GetType() == GetType() && Equals((Template)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => Id != null ? Id.GetHashCode() : 0;
|
||||
|
||||
public IKey GetKey()
|
||||
{
|
||||
return new FlatUniqueKey(new[] { __ID });
|
||||
}
|
||||
public IKey GetKey() => new FlatUniqueKey([internalId]);
|
||||
|
||||
public object Clone() => new Template
|
||||
{
|
||||
Id = Id,
|
||||
IsContainer = IsContainer,
|
||||
UseGravity = UseGravity,
|
||||
RandomRotation = RandomRotation,
|
||||
Position = ProcessorUtil.Copy(Position),
|
||||
Rotation = ProcessorUtil.Copy(Rotation),
|
||||
IsGroupPosition = IsGroupPosition,
|
||||
GroupPositions = ProcessorUtil.Copy(GroupPositions),
|
||||
IsAlwaysSpawn = IsAlwaysSpawn,
|
||||
Root = Root,
|
||||
Items = ProcessorUtil.Copy(Items)
|
||||
};
|
||||
(
|
||||
internalId,
|
||||
Id,
|
||||
IsContainer,
|
||||
UseGravity,
|
||||
RandomRotation,
|
||||
ProcessorUtil.Copy(Position),
|
||||
ProcessorUtil.Copy(Rotation),
|
||||
IsGroupPosition,
|
||||
ProcessorUtil.Copy(GroupPositions),
|
||||
IsAlwaysSpawn,
|
||||
Root,
|
||||
ProcessorUtil.Copy(Items)
|
||||
);
|
||||
}
|
@ -1,15 +1,19 @@
|
||||
using LootDumpProcessor.Model;
|
||||
using System.Globalization;
|
||||
using LootDumpProcessor.Model;
|
||||
using LootDumpProcessor.Model.Processing;
|
||||
using LootDumpProcessor.Utils;
|
||||
|
||||
namespace LootDumpProcessor.Process;
|
||||
|
||||
public class ComposedKeyGenerator(ITarkovItemsProvider tarkovItemsProvider) : IComposedKeyGenerator
|
||||
public class ComposedKeyGenerator(ITarkovItemsProvider tarkovItemsProvider, IKeyGenerator keyGenerator)
|
||||
: IComposedKeyGenerator
|
||||
{
|
||||
private readonly ITarkovItemsProvider _tarkovItemsProvider =
|
||||
tarkovItemsProvider ?? throw new ArgumentNullException(nameof(tarkovItemsProvider));
|
||||
|
||||
public ComposedKey Generate(IEnumerable<Item> items)
|
||||
private readonly IKeyGenerator
|
||||
_keyGenerator = keyGenerator ?? throw new ArgumentNullException(nameof(keyGenerator));
|
||||
|
||||
public ComposedKey Generate(IReadOnlyList<Item>? items)
|
||||
{
|
||||
var key = items?.Select(i => i.Tpl)
|
||||
.Where(i => !string.IsNullOrEmpty(i) &&
|
||||
@ -17,8 +21,9 @@ public class ComposedKeyGenerator(ITarkovItemsProvider tarkovItemsProvider) : IC
|
||||
.Cast<string>()
|
||||
.Select(i => (double)i.GetHashCode())
|
||||
.Sum()
|
||||
.ToString() ?? KeyGenerator.GetNextKey();
|
||||
var firstItem = items?.FirstOrDefault();
|
||||
.ToString(CultureInfo.InvariantCulture) ?? _keyGenerator.Generate();
|
||||
var firstItem = items?[0];
|
||||
|
||||
return new ComposedKey(key, firstItem);
|
||||
}
|
||||
}
|
@ -4,5 +4,5 @@ namespace LootDumpProcessor.Process;
|
||||
|
||||
public interface IComposedKeyGenerator
|
||||
{
|
||||
ComposedKey Generate(IEnumerable<Item> items);
|
||||
ComposedKey Generate(IReadOnlyList<Item>? items);
|
||||
}
|
6
source/LootDumpProcessor/Process/IKeyGenerator.cs
Normal file
6
source/LootDumpProcessor/Process/IKeyGenerator.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace LootDumpProcessor.Process;
|
||||
|
||||
public interface IKeyGenerator
|
||||
{
|
||||
string Generate();
|
||||
}
|
13
source/LootDumpProcessor/Process/NumericKeyGenerator.cs
Normal file
13
source/LootDumpProcessor/Process/NumericKeyGenerator.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace LootDumpProcessor.Process;
|
||||
|
||||
public class NumericKeyGenerator : IKeyGenerator
|
||||
{
|
||||
private ulong _currentKey;
|
||||
|
||||
public string Generate()
|
||||
{
|
||||
var key = _currentKey;
|
||||
Interlocked.Increment(ref _currentKey);
|
||||
return key.ToString();
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ public class MultithreadSteppedDumpProcessor(
|
||||
IStaticContainersProcessor staticContainersProcessor,
|
||||
IAmmoProcessor ammoProcessor,
|
||||
ILooseLootProcessor looseLootProcessor,
|
||||
ILogger<MultithreadSteppedDumpProcessor> logger
|
||||
ILogger<MultithreadSteppedDumpProcessor> logger, IKeyGenerator keyGenerator
|
||||
)
|
||||
: IDumpProcessor
|
||||
{
|
||||
@ -43,6 +43,9 @@ public class MultithreadSteppedDumpProcessor(
|
||||
private readonly ILogger<MultithreadSteppedDumpProcessor> _logger =
|
||||
logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
private readonly IKeyGenerator
|
||||
_keyGenerator = keyGenerator ?? throw new ArgumentNullException(nameof(keyGenerator));
|
||||
|
||||
private static readonly IDataStorage _dataStorage = DataStorageFactory.GetInstance();
|
||||
|
||||
public Dictionary<OutputFileType, object> ProcessDumps(List<PartialData> dumps)
|
||||
@ -225,17 +228,17 @@ public class MultithreadSteppedDumpProcessor(
|
||||
|
||||
var lockObjectContainerCounts = new object();
|
||||
var lockObjectCounts = new object();
|
||||
var looseLootCounts = new LooseLootCounts();
|
||||
|
||||
var lockObjectDictionaryCounts = new object();
|
||||
var dictionaryCounts = new FlatKeyableDictionary<string, int>();
|
||||
looseLootCounts.Counts = dictionaryCounts.GetKey();
|
||||
var dictionaryCounts = new FlatKeyableDictionary<string, int>(_keyGenerator.Generate());
|
||||
|
||||
var lockObjectDictionaryItemProperties = new object();
|
||||
var dictionaryItemProperties = new FlatKeyableDictionary<string, FlatKeyableList<Template>>();
|
||||
var dictionaryItemProperties =
|
||||
new FlatKeyableDictionary<string, FlatKeyableList<Template>>(_keyGenerator.Generate());
|
||||
|
||||
var actualDictionaryItemProperties = new FlatKeyableDictionary<string, IKey>();
|
||||
looseLootCounts.ItemProperties = actualDictionaryItemProperties.GetKey();
|
||||
var actualDictionaryItemProperties = new FlatKeyableDictionary<string, IKey>(_keyGenerator.Generate());
|
||||
var looseLootCounts = new LooseLootCounts(_keyGenerator.Generate(), dictionaryCounts.GetKey(),
|
||||
actualDictionaryItemProperties.GetKey());
|
||||
|
||||
dumpProcessData.LooseLootCounts.Add(mapName, looseLootCounts.GetKey());
|
||||
|
||||
@ -316,7 +319,7 @@ public class MultithreadSteppedDumpProcessor(
|
||||
{
|
||||
if (!dictionaryItemProperties.TryGetValue(uniqueKey, out var values))
|
||||
{
|
||||
values = new FlatKeyableList<Template>();
|
||||
values = new FlatKeyableList<Template>(_keyGenerator.Generate());
|
||||
dictionaryItemProperties.Add(uniqueKey, values);
|
||||
actualDictionaryItemProperties.Add(uniqueKey, values.GetKey());
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class FileProcessor : IFileProcessor
|
||||
var staticLoot = new List<Template>();
|
||||
|
||||
foreach (var item in parsedData.Data.Data.LocationLoot.Loot)
|
||||
if (item.IsContainer ?? false) staticLoot.Add(item);
|
||||
if (item.IsContainer) staticLoot.Add(item);
|
||||
else looseLoot.Add(item);
|
||||
|
||||
parsedData.Data = null;
|
||||
|
@ -11,7 +11,7 @@ namespace LootDumpProcessor.Process.Processor.v2.LooseLootProcessor;
|
||||
|
||||
public class LooseLootProcessor(
|
||||
ILogger<LooseLootProcessor> logger, IDataStorage dataStorage, ITarkovItemsProvider tarkovItemsProvider,
|
||||
IComposedKeyGenerator composedKeyGenerator
|
||||
IComposedKeyGenerator composedKeyGenerator, IKeyGenerator keyGenerator
|
||||
)
|
||||
: ILooseLootProcessor
|
||||
{
|
||||
@ -27,6 +27,9 @@ public class LooseLootProcessor(
|
||||
private readonly IComposedKeyGenerator _composedKeyGenerator =
|
||||
composedKeyGenerator ?? throw new ArgumentNullException(nameof(composedKeyGenerator));
|
||||
|
||||
private readonly IKeyGenerator
|
||||
_keyGenerator = keyGenerator ?? throw new ArgumentNullException(nameof(keyGenerator));
|
||||
|
||||
public PreProcessedLooseLoot PreProcessLooseLoot(List<Template> looseLoot)
|
||||
{
|
||||
var preProcessedLoot = new PreProcessedLooseLoot
|
||||
@ -34,7 +37,8 @@ public class LooseLootProcessor(
|
||||
Counts = new Dictionary<string, int>()
|
||||
};
|
||||
|
||||
var itemPropertiesDictionary = new SubdivisionedKeyableDictionary<string, List<Template>>();
|
||||
var itemPropertiesDictionary =
|
||||
new SubdivisionedKeyableDictionary<string, List<Template>>(_keyGenerator.Generate());
|
||||
preProcessedLoot.ItemProperties = (AbstractKey)itemPropertiesDictionary.GetKey();
|
||||
preProcessedLoot.MapSpawnpointCount = looseLoot.Count;
|
||||
|
||||
@ -55,7 +59,7 @@ public class LooseLootProcessor(
|
||||
|
||||
if (!itemPropertiesDictionary.TryGetValue(sanitizedId, out var templates))
|
||||
{
|
||||
templates = new FlatKeyableList<Template>();
|
||||
templates = new FlatKeyableList<Template>(_keyGenerator.Generate());
|
||||
itemPropertiesDictionary.Add(sanitizedId, templates);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ public class StaticContainersProcessor : IStaticContainersProcessor
|
||||
var locationLoot = rawMapDump.Data.LocationLoot;
|
||||
var mapId = locationLoot.Id.ToLower();
|
||||
var staticLootPositions = locationLoot.Loot
|
||||
.Where(loot => loot.IsContainer.GetValueOrDefault())
|
||||
.Where(loot => loot.IsContainer)
|
||||
.OrderBy(loot => loot.Id)
|
||||
.ToList();
|
||||
|
||||
@ -44,7 +44,8 @@ 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 var forcedItems)
|
||||
var forcedStaticItems = LootDumpProcessorContext.GetForcedItems()
|
||||
.TryGetValue(mapId, out List<StaticForced>? forcedItems)
|
||||
? forcedItems
|
||||
: new List<StaticForced>();
|
||||
|
||||
@ -61,13 +62,13 @@ public class StaticContainersProcessor : IStaticContainersProcessor
|
||||
public IReadOnlyList<Template> CreateDynamicStaticContainers(RootData rawMapDump)
|
||||
{
|
||||
var dynamicContainers = rawMapDump.Data.LocationLoot.Loot
|
||||
.Where(loot => loot.IsContainer.GetValueOrDefault() &&
|
||||
.Where(loot => loot.IsContainer &&
|
||||
!LootDumpProcessorContext.GetStaticWeaponIds().Contains(loot.Items.FirstOrDefault()?.Tpl))
|
||||
.ToList();
|
||||
|
||||
foreach (var container in dynamicContainers)
|
||||
{
|
||||
if (container.Items == null || !container.Items.Any())
|
||||
if (container.Items == null || container.Items.Count == 0)
|
||||
{
|
||||
_logger.LogWarning("Dynamic container with ID {ContainerId} has no items.", container.Id);
|
||||
continue;
|
||||
|
@ -38,6 +38,7 @@ public static class Program
|
||||
|
||||
services.AddSingleton<ITarkovItemsProvider, TarkovItemsProvider>();
|
||||
services.AddSingleton<IDataStorage>(_ => DataStorageFactory.GetInstance());
|
||||
services.AddSingleton<IKeyGenerator, NumericKeyGenerator>();
|
||||
services.AddTransient<IComposedKeyGenerator, ComposedKeyGenerator>();
|
||||
|
||||
services.AddTransient<IIntakeReader, JsonFileIntakeReader>();
|
||||
|
@ -1,11 +1,16 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using LootDumpProcessor.Utils;
|
||||
|
||||
namespace LootDumpProcessor.Storage.Collections;
|
||||
|
||||
public class FlatKeyableDictionary<K, V> : Dictionary<K, V>, IKeyable
|
||||
{
|
||||
[JsonPropertyName("__id__")] public string __ID { get; set; } = KeyGenerator.GetNextKey();
|
||||
[JsonPropertyName("__id__")] private string Id { get; set; }
|
||||
|
||||
public IKey GetKey() => new FlatUniqueKey([__ID]);
|
||||
public FlatKeyableDictionary(string id)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(id);
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public IKey GetKey() => new FlatUniqueKey([Id]);
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
using LootDumpProcessor.Utils;
|
||||
|
||||
namespace LootDumpProcessor.Storage.Collections;
|
||||
|
||||
public class FlatKeyableList<T> : List<T>, IKeyable
|
||||
{
|
||||
public string __ID { get; } = KeyGenerator.GetNextKey();
|
||||
public string Id { get; }
|
||||
|
||||
public IKey GetKey() => new FlatUniqueKey([__ID]);
|
||||
public FlatKeyableList(string id)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(id);
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public IKey GetKey() => new FlatUniqueKey([Id]);
|
||||
}
|
@ -1,11 +1,16 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using LootDumpProcessor.Utils;
|
||||
|
||||
namespace LootDumpProcessor.Storage.Collections;
|
||||
|
||||
public class SubdivisionedKeyableDictionary<K, V> : Dictionary<K, V>, IKeyable
|
||||
{
|
||||
[JsonPropertyName("__id__")] public string __ID { get; set; } = KeyGenerator.GetNextKey();
|
||||
public SubdivisionedKeyableDictionary(string id)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(id);
|
||||
Id = id;
|
||||
}
|
||||
|
||||
[JsonPropertyName("__id__")] private string Id { get; set; }
|
||||
|
||||
public string? Extras
|
||||
{
|
||||
@ -24,10 +29,10 @@ public class SubdivisionedKeyableDictionary<K, V> : Dictionary<K, V>, IKeyable
|
||||
"dictionaries"
|
||||
};
|
||||
subdivisions.AddRange(ExtraSubdivisions);
|
||||
subdivisions.Add(__ID);
|
||||
subdivisions.Add(Id);
|
||||
return new SubdivisionedUniqueKey(subdivisions.ToArray());
|
||||
}
|
||||
|
||||
return new SubdivisionedUniqueKey(["dictionaries", __ID]);
|
||||
return new SubdivisionedUniqueKey(["dictionaries", Id]);
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ public static class DataStorageFactory
|
||||
private static IDataStorage GetInstance(DataStorageTypes type)
|
||||
{
|
||||
if (DataStorage.TryGetValue(type, out var dataStorage)) return dataStorage;
|
||||
|
||||
|
||||
dataStorage = type switch
|
||||
{
|
||||
DataStorageTypes.File => new FileDataStorage(),
|
||||
|
@ -9,7 +9,8 @@ public class FileDataStorage : IDataStorage
|
||||
|
||||
public bool Exists(IKey key) => StoreHandlerFactory.GetInstance(key.GetKeyType()).Exists(key);
|
||||
|
||||
public T GetItem<T>(IKey key) where T : IKeyable => StoreHandlerFactory.GetInstance(key.GetKeyType()).Retrieve<T>(key);
|
||||
public T GetItem<T>(IKey key) where T : IKeyable =>
|
||||
StoreHandlerFactory.GetInstance(key.GetKeyType()).Retrieve<T>(key);
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
|
@ -10,7 +10,7 @@ public class StoreHandlerFactory
|
||||
public static IStoreHandler GetInstance(KeyType type)
|
||||
{
|
||||
if (Handlers.TryGetValue(type, out var handler)) return handler;
|
||||
|
||||
|
||||
handler = type switch
|
||||
{
|
||||
KeyType.Unique => new FlatStoreHandler(),
|
||||
|
@ -2,31 +2,33 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace LootDumpProcessor.Utils;
|
||||
|
||||
public static class FileDateParser
|
||||
public static partial class FileDateParser
|
||||
{
|
||||
private static readonly Regex _fileDateRegex =
|
||||
new(".*([0-9]{4})[-]([0-9]{2})[-]([0-9]{2})[_]([0-9]{2})[-]([0-9]{2})[-]([0-9]{2}).*");
|
||||
private static readonly Regex FileDateRegex = GetRegex();
|
||||
|
||||
public static bool TryParseFileDate(string fileName, out DateTime? date)
|
||||
{
|
||||
date = null;
|
||||
if (!_fileDateRegex.IsMatch(fileName))
|
||||
return false;
|
||||
var match = _fileDateRegex.Match(fileName);
|
||||
if (!FileDateRegex.IsMatch(fileName)) return false;
|
||||
|
||||
var match = FileDateRegex.Match(fileName);
|
||||
var year = match.Groups[1].Value;
|
||||
var month = match.Groups[2].Value;
|
||||
var day = match.Groups[3].Value;
|
||||
var hour = match.Groups[4].Value;
|
||||
var mins = match.Groups[5].Value;
|
||||
var secs = match.Groups[6].Value;
|
||||
var minutes = match.Groups[5].Value;
|
||||
var seconds = match.Groups[6].Value;
|
||||
date = new DateTime(
|
||||
int.Parse(year),
|
||||
int.Parse(month),
|
||||
int.Parse(day),
|
||||
int.Parse(hour),
|
||||
int.Parse(mins),
|
||||
int.Parse(secs)
|
||||
int.Parse(minutes),
|
||||
int.Parse(seconds)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
[GeneratedRegex(".*([0-9]{4})[-]([0-9]{2})[-]([0-9]{2})[_]([0-9]{2})[-]([0-9]{2})[-]([0-9]{2}).*")]
|
||||
private static partial Regex GetRegex();
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
namespace LootDumpProcessor.Utils;
|
||||
|
||||
public class KeyGenerator
|
||||
{
|
||||
private static long currentKey = 0L;
|
||||
private static object lockObject = new();
|
||||
|
||||
public static string GetNextKey()
|
||||
{
|
||||
lock (lockObject)
|
||||
{
|
||||
return $"{++currentKey}";
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user