From 2bc3a60af84fa7d6b752f3b09b3c39a1cc1d7854 Mon Sep 17 00:00:00 2001 From: leMicin Date: Tue, 24 Dec 2024 14:22:22 -0500 Subject: [PATCH 01/12] Demo class of what a property refactor could look like --- .../ItemProperties/GemLevelProperty.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/Sidekick.Apis.Poe/ItemProperties/GemLevelProperty.cs diff --git a/src/Sidekick.Apis.Poe/ItemProperties/GemLevelProperty.cs b/src/Sidekick.Apis.Poe/ItemProperties/GemLevelProperty.cs new file mode 100644 index 00000000..4f04cf60 --- /dev/null +++ b/src/Sidekick.Apis.Poe/ItemProperties/GemLevelProperty.cs @@ -0,0 +1,56 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Trade.Models; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.ItemProperties; + +public class GemLevelProperty(IGameLanguageProvider gameLanguageProvider) +{ + private Regex? Pattern { get; set; } + + public Task Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionLevel.ToRegexIntCapture(); + return Task.CompletedTask; + } + + public void Parse(Item item, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + item.Properties.GemLevel = GetInt(Pattern, propertyBlock); + } + + public PropertyFilter? GetFilter(Item item) + { + if (item.Properties.GemLevel <= 0) + { + return null; + } + + var filter = new PropertyFilter(true, PropertyFilterType.Misc_GemLevel, gameLanguageProvider.Language.DescriptionLevel, item.Properties.GemLevel, null); + + return filter; + } + + public void SetTradeRequest(SearchFilters searchFilters, PropertyFilter filter, Item item) + { + if (filter.Type != PropertyFilterType.Misc_GemLevel || filter.Checked != true) + { + return; + } + + if (item.Metadata.Game == GameType.PathOfExile) + { + searchFilters.MiscFilters.Filters.GemLevel = filter.Value; + } + else if (item.Metadata.Game == GameType.PathOfExile2) + { + searchFilters.TypeFilters.Filters.ItemLevel = filter.Value; + } + } +} From 47a54d9a13ca16756a7f7941e95bbec6124b76da Mon Sep 17 00:00:00 2001 From: leMicin Date: Tue, 31 Dec 2024 17:18:52 -0500 Subject: [PATCH 02/12] Refactor item headers and properties to improve clarity Renamed `Header` to `ItemHeader` and `Properties` to `ItemProperties` for better code clarity and maintainability. Updated corresponding method signatures, variable names, and related logic across the codebase to reflect these changes. Introduced `PropertyDefinition` to standardize property parsing logic. --- .../IItemStaticDataProvider.cs | 2 +- src/Sidekick.Apis.Poe/Items/Models/ApiItem.cs | 8 +- .../Parser/Headers/HeaderParser.cs | 4 +- .../Parser/Headers/IHeaderParser.cs | 2 +- src/Sidekick.Apis.Poe/Parser/ItemParser.cs | 6 +- src/Sidekick.Apis.Poe/Parser/ParsingItem.cs | 2 +- .../Definitions}/GemLevelProperty.cs | 31 ++++--- .../Parser/Properties/IPropertyParser.cs | 2 +- .../Parser/Properties/PropertyDefinition.cs | 84 +++++++++++++++++++ .../Parser/Properties/PropertyParser.cs | 48 +++++------ .../Sidekick.Apis.Poe.csproj | 5 -- .../Static/ItemStaticDataProvider.cs | 4 +- .../Trade/Models/TradeItem.cs | 8 +- .../Trade/Requests/Filters/SearchFilters.cs | 2 + .../Trade/TradeSearchService.cs | 10 +-- src/Sidekick.Common/Game/Items/Item.cs | 12 +-- .../Game/Items/{Header.cs => ItemHeader.cs} | 2 +- .../{Properties.cs => ItemProperties.cs} | 40 ++++----- src/Sidekick.Modules.Maps/MapOverlay.razor | 1 + .../Components/Filters/FiltersComponent.razor | 1 + .../Components/Items/ItemComponent.razor | 1 + 21 files changed, 184 insertions(+), 91 deletions(-) rename src/Sidekick.Apis.Poe/{ItemProperties => Parser/Properties/Definitions}/GemLevelProperty.cs (59%) create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs rename src/Sidekick.Common/Game/Items/{Header.cs => ItemHeader.cs} (97%) rename src/Sidekick.Common/Game/Items/{Properties.cs => ItemProperties.cs} (78%) diff --git a/src/Sidekick.Apis.Poe/IItemStaticDataProvider.cs b/src/Sidekick.Apis.Poe/IItemStaticDataProvider.cs index 83088329..ed58d983 100644 --- a/src/Sidekick.Apis.Poe/IItemStaticDataProvider.cs +++ b/src/Sidekick.Apis.Poe/IItemStaticDataProvider.cs @@ -7,6 +7,6 @@ public interface IItemStaticDataProvider : IInitializableService { string? GetImage(string id); - string? GetId(Header header); + string? GetId(ItemHeader itemHeader); } } diff --git a/src/Sidekick.Apis.Poe/Items/Models/ApiItem.cs b/src/Sidekick.Apis.Poe/Items/Models/ApiItem.cs index abd0e60e..597b2d35 100644 --- a/src/Sidekick.Apis.Poe/Items/Models/ApiItem.cs +++ b/src/Sidekick.Apis.Poe/Items/Models/ApiItem.cs @@ -29,7 +29,7 @@ public class ApiItem [JsonIgnore] public bool IsUnique => Flags?.Unique ?? false; - public Header ToHeader() + public ItemHeader ToHeader() { var categoryRarity = Category switch { @@ -39,15 +39,15 @@ public Header ToHeader() _ => Rarity.Unknown }; - return new Header() + return new ItemHeader() { Name = Name, - Type = Text ?? Type, + Type = Type, ApiItemId = Id ?? string.Empty, ApiName = Name, ApiType = Type, - ApiText = Text, ApiDiscriminator = Discriminator, + ApiText = Text, Game = Game, Category = Category ?? Common.Game.Items.Category.Unknown, Rarity = IsUnique ? Rarity.Unique : categoryRarity, diff --git a/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs b/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs index 36a00d85..4e27e809 100644 --- a/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs @@ -205,7 +205,7 @@ private void InitializeRarityPatterns() }; } - public Header Parse(ParsingItem parsingItem) + public ItemHeader Parse(ParsingItem parsingItem) { var rarity = ParseRarity(parsingItem); @@ -231,7 +231,7 @@ public Header Parse(ParsingItem parsingItem) } var apiItem = ParseApiItem(rarity, name, type); - var header = apiItem?.ToHeader() ?? new Header(); + var header = apiItem?.ToHeader() ?? new ItemHeader(); header.Name = name; header.Type = type; header.ItemCategory = ParseItemCategory(parsingItem); diff --git a/src/Sidekick.Apis.Poe/Parser/Headers/IHeaderParser.cs b/src/Sidekick.Apis.Poe/Parser/Headers/IHeaderParser.cs index f3f57197..042fd21e 100644 --- a/src/Sidekick.Apis.Poe/Parser/Headers/IHeaderParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Headers/IHeaderParser.cs @@ -5,5 +5,5 @@ namespace Sidekick.Apis.Poe.Parser.Headers; public interface IHeaderParser : IInitializableService { - Header Parse(ParsingItem parsingItem); + ItemHeader Parse(ParsingItem parsingItem); } diff --git a/src/Sidekick.Apis.Poe/Parser/ItemParser.cs b/src/Sidekick.Apis.Poe/Parser/ItemParser.cs index 30f08eb5..25c76a91 100644 --- a/src/Sidekick.Apis.Poe/Parser/ItemParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/ItemParser.cs @@ -47,7 +47,7 @@ public Item ParseItem(string itemText) throw new UnparsableException(); } - Header? invariant = null; + ItemHeader? invariant = null; if (parsingItem.Header.ApiItemId != null && apiInvariantItemProvider.IdDictionary.TryGetValue(parsingItem.Header.ApiItemId, out var invariantMetadata)) { invariant = invariantMetadata.ToHeader(); @@ -62,8 +62,8 @@ public Item ParseItem(string itemText) var properties = propertyParser.Parse(parsingItem, modifierLines); var pseudoModifiers = pseudoParser.Parse(modifierLines); var item = new Item(invariant: invariant, - header: parsingItem.Header, - properties: properties, + itemHeader: parsingItem.Header, + itemProperties: properties, influences: influences, sockets: sockets, modifierLines: modifierLines, diff --git a/src/Sidekick.Apis.Poe/Parser/ParsingItem.cs b/src/Sidekick.Apis.Poe/Parser/ParsingItem.cs index 22b3a8b3..cc7c090f 100644 --- a/src/Sidekick.Apis.Poe/Parser/ParsingItem.cs +++ b/src/Sidekick.Apis.Poe/Parser/ParsingItem.cs @@ -26,7 +26,7 @@ public ParsingItem(string text) .ToList(); } - public Header? Header { get; set; } + public ItemHeader? Header { get; set; } /// /// Item sections seperated by dashes when copying an item in-game. diff --git a/src/Sidekick.Apis.Poe/ItemProperties/GemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs similarity index 59% rename from src/Sidekick.Apis.Poe/ItemProperties/GemLevelProperty.cs rename to src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs index 4f04cf60..c57726ed 100644 --- a/src/Sidekick.Apis.Poe/ItemProperties/GemLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser; using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Trade.Models; using Sidekick.Apis.Poe.Trade.Requests.Filters; @@ -7,22 +6,29 @@ using Sidekick.Common.Game.Items; using Sidekick.Common.Game.Languages; -namespace Sidekick.Apis.Poe.ItemProperties; +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; -public class GemLevelProperty(IGameLanguageProvider gameLanguageProvider) +public class GemLevelProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : PropertyDefinition { private Regex? Pattern { get; set; } - public Task Initialize() + public override bool Enabled => true; + + public override void Initialize() { Pattern = gameLanguageProvider.Language.DescriptionLevel.ToRegexIntCapture(); - return Task.CompletedTask; } - public void Parse(Item item, ParsingItem parsingItem) + public override void ParseBeforeModifiers(ItemProperties itemProperties, ParsingItem parsingItem) { + if (parsingItem.Header?.Category != Category.Gem) return; + var propertyBlock = parsingItem.Blocks[1]; - item.Properties.GemLevel = GetInt(Pattern, propertyBlock); + itemProperties.GemLevel = GetInt(Pattern, propertyBlock); + } + + public override void ParseAfterModifiers(ItemProperties itemProperties, ParsingItem parsingItem, List modifierLines) + { } public PropertyFilter? GetFilter(Item item) @@ -33,7 +39,6 @@ public void Parse(Item item, ParsingItem parsingItem) } var filter = new PropertyFilter(true, PropertyFilterType.Misc_GemLevel, gameLanguageProvider.Language.DescriptionLevel, item.Properties.GemLevel, null); - return filter; } @@ -44,11 +49,15 @@ public void SetTradeRequest(SearchFilters searchFilters, PropertyFilter filter, return; } - if (item.Metadata.Game == GameType.PathOfExile) + if (item.Header.Game == GameType.PathOfExile) { - searchFilters.MiscFilters.Filters.GemLevel = filter.Value; + searchFilters.GetOrCreateMiscFilters().Filters.GemLevel = new StatFilterValue() + { + Min = filter.Value, + + } } - else if (item.Metadata.Game == GameType.PathOfExile2) + else if (item.Header.Game == GameType.PathOfExile2) { searchFilters.TypeFilters.Filters.ItemLevel = filter.Value; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs b/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs index c2486c61..f965c8fa 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs @@ -5,5 +5,5 @@ namespace Sidekick.Apis.Poe.Parser.Properties; public interface IPropertyParser: IInitializableService { - Common.Game.Items.Properties Parse(ParsingItem parsingItem, List modifierLines); + ItemProperties Parse(ParsingItem parsingItem, List modifierLines); } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs new file mode 100644 index 00000000..e716fc21 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs @@ -0,0 +1,84 @@ +using System.Globalization; +using System.Text.RegularExpressions; +using Sidekick.Common.Game.Items; + +namespace Sidekick.Apis.Poe.Parser.Properties; + +public abstract class PropertyDefinition +{ + private static readonly Regex parseHashPattern = new("\\#"); + + public abstract bool Enabled { get; } + + public abstract void Initialize(); + + public abstract void ParseBeforeModifiers(ItemProperties itemProperties, ParsingItem parsingItem); + + public abstract void ParseAfterModifiers(ItemProperties itemProperties, ParsingItem parsingItem, List modifierLines); + + protected static bool GetBool(Regex? pattern, ParsingItem parsingItem) + { + if (pattern == null) + { + return false; + } + + return parsingItem.TryParseRegex(pattern, out _); + } + + protected static int GetInt(Regex? pattern, ParsingItem parsingItem) + { + if (pattern == null) + { + return 0; + } + + if (parsingItem.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) + { + return result; + } + + return 0; + } + + protected static int GetInt(Regex? pattern, ParsingBlock parsingBlock) + { + if (pattern == null) + { + return 0; + } + + if (parsingBlock.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) + { + return result; + } + + return 0; + } + + protected static double GetDouble(Regex? pattern, ParsingBlock parsingBlock) + { + if (pattern == null) + { + return 0; + } + + if (!parsingBlock.TryParseRegex(pattern, out var match)) + { + return 0; + } + + var value = match.Groups[1].Value.Replace(",", "."); + if (value.EndsWith("%")) + { + value = value.TrimEnd('%'); + } + + if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) + { + return result; + } + + return 0; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs index d37c0ad6..a3ecc35d 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs @@ -87,7 +87,7 @@ public Task Initialize() return Task.CompletedTask; } - public Common.Game.Items.Properties Parse(ParsingItem parsingItem, List modifierLines) + public ItemProperties Parse(ParsingItem parsingItem, List modifierLines) { return parsingItem.Header?.Category switch { @@ -100,17 +100,17 @@ public Common.Game.Items.Properties Parse(ParsingItem parsingItem, List ParseFlaskProperties(parsingItem), Category.Sanctum => ParseSanctumProperties(parsingItem), Category.Logbook => ParseLogbookProperties(parsingItem), - _ => new Common.Game.Items.Properties(), + _ => new ItemProperties(), }; } - private Common.Game.Items.Properties ParseWeaponProperties(ParsingItem parsingItem, List modifierLines) + private ItemProperties ParseWeaponProperties(ParsingItem parsingItem, List modifierLines) { var propertyBlock = parsingItem.Blocks[1]; var attacksPerSecond = GetDouble(AttacksPerSecond, propertyBlock); var criticalStrikeChance = GetDouble(CriticalStrikeChance, propertyBlock); - var properties = new Common.Game.Items.Properties + var properties = new ItemProperties { ItemLevel = GetInt(ItemLevel, parsingItem), Identified = !GetBool(Unidentified, parsingItem), @@ -161,7 +161,7 @@ private Common.Game.Items.Properties ParseWeaponProperties(ParsingItem parsingIt return properties; } - private void ParseElementalDamage(ParsingLine line, Common.Game.Items.Properties properties, List modifierLines) + private void ParseElementalDamage(ParsingLine line, ItemProperties itemProperties, List modifierLines) { var damageMods = invariantModifierProvider.FireWeaponDamageIds.ToList(); damageMods.AddRange(invariantModifierProvider.ColdWeaponDamageIds); @@ -186,7 +186,7 @@ private void ParseElementalDamage(ParsingLine line, Common.Game.Items.Properties var isFire = invariantModifierProvider.FireWeaponDamageIds.Any(x => ids.Contains(x)); if (isFire) { - properties.FireDamage = range; + itemProperties.FireDamage = range; matchIndex++; continue; } @@ -194,7 +194,7 @@ private void ParseElementalDamage(ParsingLine line, Common.Game.Items.Properties var isCold = invariantModifierProvider.ColdWeaponDamageIds.Any(x => ids.Contains(x)); if (isCold) { - properties.ColdDamage = range; + itemProperties.ColdDamage = range; matchIndex++; continue; } @@ -202,7 +202,7 @@ private void ParseElementalDamage(ParsingLine line, Common.Game.Items.Properties var isLightning = invariantModifierProvider.LightningWeaponDamageIds.Any(x => ids.Contains(x)); if (isLightning) { - properties.LightningDamage = range; + itemProperties.LightningDamage = range; matchIndex++; continue; } @@ -211,11 +211,11 @@ private void ParseElementalDamage(ParsingLine line, Common.Game.Items.Properties } } - private Common.Game.Items.Properties ParseArmourProperties(ParsingItem parsingItem) + private ItemProperties ParseArmourProperties(ParsingItem parsingItem) { var propertyBlock = parsingItem.Blocks[1]; - return new Common.Game.Items.Properties() + return new ItemProperties() { ItemLevel = GetInt(ItemLevel, parsingItem), Identified = !GetBool(Unidentified, parsingItem), @@ -228,9 +228,9 @@ private Common.Game.Items.Properties ParseArmourProperties(ParsingItem parsingIt }; } - private Common.Game.Items.Properties ParseAccessoryProperties(ParsingItem parsingItem) + private ItemProperties ParseAccessoryProperties(ParsingItem parsingItem) { - return new Common.Game.Items.Properties() + return new ItemProperties() { ItemLevel = GetInt(ItemLevel, parsingItem), Identified = !GetBool(Unidentified, parsingItem), @@ -238,11 +238,11 @@ private Common.Game.Items.Properties ParseAccessoryProperties(ParsingItem parsin }; } - private Common.Game.Items.Properties ParseMapProperties(ParsingItem parsingItem) + private ItemProperties ParseMapProperties(ParsingItem parsingItem) { var propertyBlock = parsingItem.Blocks[1]; - return new Common.Game.Items.Properties() + return new ItemProperties() { ItemLevel = GetInt(ItemLevel, parsingItem), Identified = !GetBool(Unidentified, parsingItem), @@ -257,11 +257,11 @@ private Common.Game.Items.Properties ParseMapProperties(ParsingItem parsingItem) }; } - private Common.Game.Items.Properties ParseGemProperties(ParsingItem parsingItem) + private ItemProperties ParseGemProperties(ParsingItem parsingItem) { var propertyBlock = parsingItem.Blocks[1]; - return new Common.Game.Items.Properties() + return new ItemProperties() { Corrupted = GetBool(Corrupted, parsingItem), GemLevel = GetInt(Level, propertyBlock), @@ -270,9 +270,9 @@ private Common.Game.Items.Properties ParseGemProperties(ParsingItem parsingItem) }; } - private Common.Game.Items.Properties ParseJewelProperties(ParsingItem parsingItem) + private ItemProperties ParseJewelProperties(ParsingItem parsingItem) { - return new Common.Game.Items.Properties() + return new ItemProperties() { ItemLevel = GetInt(ItemLevel, parsingItem), Identified = !GetBool(Unidentified, parsingItem), @@ -280,9 +280,9 @@ private Common.Game.Items.Properties ParseJewelProperties(ParsingItem parsingIte }; } - private Common.Game.Items.Properties ParseFlaskProperties(ParsingItem parsingItem) + private ItemProperties ParseFlaskProperties(ParsingItem parsingItem) { - return new Common.Game.Items.Properties() + return new ItemProperties() { ItemLevel = GetInt(ItemLevel, parsingItem), Identified = !GetBool(Unidentified, parsingItem), @@ -291,17 +291,17 @@ private Common.Game.Items.Properties ParseFlaskProperties(ParsingItem parsingIte }; } - private Common.Game.Items.Properties ParseSanctumProperties(ParsingItem parsingItem) + private ItemProperties ParseSanctumProperties(ParsingItem parsingItem) { - return new Common.Game.Items.Properties + return new ItemProperties { AreaLevel = GetInt(AreaLevel, parsingItem), }; } - private Common.Game.Items.Properties ParseLogbookProperties(ParsingItem parsingItem) + private ItemProperties ParseLogbookProperties(ParsingItem parsingItem) { - return new Common.Game.Items.Properties + return new ItemProperties { AreaLevel = GetInt(AreaLevel, parsingItem), }; diff --git a/src/Sidekick.Apis.Poe/Sidekick.Apis.Poe.csproj b/src/Sidekick.Apis.Poe/Sidekick.Apis.Poe.csproj index 11337fff..4981e80b 100644 --- a/src/Sidekick.Apis.Poe/Sidekick.Apis.Poe.csproj +++ b/src/Sidekick.Apis.Poe/Sidekick.Apis.Poe.csproj @@ -6,11 +6,6 @@ enable - - - - - diff --git a/src/Sidekick.Apis.Poe/Static/ItemStaticDataProvider.cs b/src/Sidekick.Apis.Poe/Static/ItemStaticDataProvider.cs index 65c84dca..b95d6a3d 100644 --- a/src/Sidekick.Apis.Poe/Static/ItemStaticDataProvider.cs +++ b/src/Sidekick.Apis.Poe/Static/ItemStaticDataProvider.cs @@ -68,9 +68,9 @@ public async Task Initialize() return $"{gameLanguageProvider.Language.PoeCdnBaseUrl}{result.Trim('/')}"; } - public string? GetId(Header header) + public string? GetId(ItemHeader itemHeader) { - var text = header.Name ?? header.Type ?? header.ApiType; + var text = itemHeader.Name ?? itemHeader.Type ?? itemHeader.ApiType; if (text != null && Ids.TryGetValue(text, out var result)) { return result; diff --git a/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs b/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs index 84722be5..729e56ba 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs @@ -4,16 +4,16 @@ namespace Sidekick.Apis.Poe.Trade.Models { public class TradeItem ( - Header header, - Properties properties, + ItemHeader itemHeader, + ItemProperties itemProperties, Influences influences, List sockets, List modifierLines, List pseudoModifiers, string text ) : Item(null, - header, - properties, + itemHeader, + itemProperties, influences, sockets, modifierLines, diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs index 09676f63..15c9cd81 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs @@ -13,6 +13,8 @@ internal class SearchFilters [JsonPropertyName("misc_filters")] public MiscFilterGroup? MiscFilters { get; set; } + public MiscFilterGroup GetOrCreateMiscFilters() => MiscFilters ??= new(); + [JsonPropertyName("weapon_filters")] public WeaponFilterGroup? WeaponFilters { get; set; } diff --git a/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs b/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs index c1af4bf1..5d5978fa 100644 --- a/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs +++ b/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs @@ -699,7 +699,7 @@ public async Task> GetResults(GameType game, string queryId, Lis private TradeItem GetItem(GameType game, Result result) { - var header = new Header() + var header = new ItemHeader() { Name = result.Item?.Name, Type = result.Item?.TypeLine, @@ -711,7 +711,7 @@ private TradeItem GetItem(GameType game, Result result) Rarity = result.Item?.Rarity ?? Rarity.Unknown, }; - var properties = new Properties() + var properties = new ItemProperties() { ItemLevel = result.Item?.ItemLevel ?? 0, Corrupted = result.Item?.Corrupted ?? false, @@ -727,8 +727,8 @@ private TradeItem GetItem(GameType game, Result result) var influences = result.Item?.Influences ?? new(); - var item = new TradeItem(header: header, - properties: properties, + var item = new TradeItem(itemHeader: header, + itemProperties: properties, influences: influences, sockets: ParseSockets(result.Item?.Sockets).ToList(), modifierLines: new(), @@ -963,7 +963,7 @@ private async Task GetBaseUrl(GameType game) return useInvariant ? gameLanguageProvider.InvariantLanguage.GetTradeBaseUrl(game) : gameLanguageProvider.Language.GetTradeBaseUrl(game); } - private async Task
GetHeader(Item item) + private async Task GetHeader(Item item) { var useInvariant = await settingsService.GetBool(SettingKeys.UseInvariantTradeResults); return useInvariant ? item.Invariant ?? item.Header : item.Header; diff --git a/src/Sidekick.Common/Game/Items/Item.cs b/src/Sidekick.Common/Game/Items/Item.cs index fb7ba256..86d373ba 100644 --- a/src/Sidekick.Common/Game/Items/Item.cs +++ b/src/Sidekick.Common/Game/Items/Item.cs @@ -1,20 +1,20 @@ namespace Sidekick.Common.Game.Items; public class Item( - Header? invariant, - Header header, - Properties properties, + ItemHeader? invariant, + ItemHeader itemHeader, + ItemProperties itemProperties, Influences influences, List sockets, List modifierLines, List pseudoModifiers, string text) { - public Header? Invariant { get; set; } = invariant; + public ItemHeader? Invariant { get; set; } = invariant; - public Header Header { get; init; } = header; + public ItemHeader Header { get; init; } = itemHeader; - public Properties Properties { get; init; } = properties; + public ItemProperties Properties { get; init; } = itemProperties; public Influences Influences { get; init; } = influences; diff --git a/src/Sidekick.Common/Game/Items/Header.cs b/src/Sidekick.Common/Game/Items/ItemHeader.cs similarity index 97% rename from src/Sidekick.Common/Game/Items/Header.cs rename to src/Sidekick.Common/Game/Items/ItemHeader.cs index 18df01da..335c34ae 100644 --- a/src/Sidekick.Common/Game/Items/Header.cs +++ b/src/Sidekick.Common/Game/Items/ItemHeader.cs @@ -1,6 +1,6 @@ namespace Sidekick.Common.Game.Items; -public class Header +public class ItemHeader { public string? Name { get; set; } diff --git a/src/Sidekick.Common/Game/Items/Properties.cs b/src/Sidekick.Common/Game/Items/ItemProperties.cs similarity index 78% rename from src/Sidekick.Common/Game/Items/Properties.cs rename to src/Sidekick.Common/Game/Items/ItemProperties.cs index 3ac7048b..84aab0dc 100644 --- a/src/Sidekick.Common/Game/Items/Properties.cs +++ b/src/Sidekick.Common/Game/Items/ItemProperties.cs @@ -1,44 +1,44 @@ namespace Sidekick.Common.Game.Items; -public class Properties +public class ItemProperties { - public bool Identified { get; init; } + public bool Identified { get; set; } - public int ItemLevel { get; init; } + public int ItemLevel { get; set; } - public bool Corrupted { get; init; } + public bool Corrupted { get; set; } - public int Armor { get; init; } + public int Armor { get; set; } - public int EnergyShield { get; init; } + public int EnergyShield { get; set; } - public int Evasion { get; init; } + public int Evasion { get; set; } - public int ChanceToBlock { get; init; } + public int ChanceToBlock { get; set; } - public int Quality { get; init; } + public int Quality { get; set; } - public bool AlternateQuality { get; init; } + public bool AlternateQuality { get; set; } - public int GemLevel { get; init; } + public int GemLevel { get; set; } - public int MapTier { get; init; } + public int MapTier { get; set; } - public int AreaLevel { get; init; } + public int AreaLevel { get; set; } - public int ItemQuantity { get; init; } + public int ItemQuantity { get; set; } - public int ItemRarity { get; init; } + public int ItemRarity { get; set; } - public int MonsterPackSize { get; init; } + public int MonsterPackSize { get; set; } - public bool Blighted { get; init; } + public bool Blighted { get; set; } - public bool BlightRavaged { get; init; } + public bool BlightRavaged { get; set; } - public double CriticalStrikeChance { get; init; } + public double CriticalStrikeChance { get; set; } - public double AttacksPerSecond { get; init; } + public double AttacksPerSecond { get; set; } public DamageRange? PhysicalDamage { get; set; } diff --git a/src/Sidekick.Modules.Maps/MapOverlay.razor b/src/Sidekick.Modules.Maps/MapOverlay.razor index 56485f07..4680a1ae 100644 --- a/src/Sidekick.Modules.Maps/MapOverlay.razor +++ b/src/Sidekick.Modules.Maps/MapOverlay.razor @@ -8,6 +8,7 @@ @using Sidekick.Modules.Maps.Localization @using Sidekick.Common.Extensions +@using ItemHeader = Sidekick.Common.Ui.Poe.Items.ItemHeader @using Sidekick.Modules.Maps.Settings @inherits Sidekick.Common.Ui.Views.SidekickView diff --git a/src/Sidekick.Modules.Trade/Components/Filters/FiltersComponent.razor b/src/Sidekick.Modules.Trade/Components/Filters/FiltersComponent.razor index fa179eba..e8ce472c 100644 --- a/src/Sidekick.Modules.Trade/Components/Filters/FiltersComponent.razor +++ b/src/Sidekick.Modules.Trade/Components/Filters/FiltersComponent.razor @@ -4,6 +4,7 @@ @using Sidekick.Common.Settings @using Sidekick.Modules.Trade.Localization @using Sidekick.Modules.Trade.Components.Prices +@using ItemHeader = Sidekick.Common.Ui.Poe.Items.ItemHeader @if (PriceCheckService.Item == null) { diff --git a/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor b/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor index 87043b0e..77997c2f 100644 --- a/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor +++ b/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor @@ -2,6 +2,7 @@ @using Sidekick.Common.Game.Items @using Sidekick.Modules.Trade.Localization @using Sidekick.Modules.Trade.Components.Prices +@using ItemHeader = Sidekick.Common.Ui.Poe.Items.ItemHeader @if (!IsCompact && (Item.CanHaveModifiers || PriceCheckService.Item?.Header.Category == Category.Gem)) { From 73f297afee7210735726e4dc7bf4957a62cf9a4e Mon Sep 17 00:00:00 2001 From: leMicin Date: Tue, 31 Dec 2024 18:26:21 -0500 Subject: [PATCH 03/12] Prevent static asset deletion during debugging --- src/Sidekick.Wpf/App.xaml.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Sidekick.Wpf/App.xaml.cs b/src/Sidekick.Wpf/App.xaml.cs index 85a83400..bd472d28 100644 --- a/src/Sidekick.Wpf/App.xaml.cs +++ b/src/Sidekick.Wpf/App.xaml.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using System.IO; using System.Windows; using System.Windows.Interop; @@ -200,6 +201,12 @@ private void AttachErrorHandlers() private void DeleteStaticAssets() { + // While debugging, we do not want to delete static assets as the environment is different than when deployed. + if (Debugger.IsAttached) + { + return; + } + try { var directory = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly()?.Location); From 7bccefa450514016bc663b2c20a8e416081f3da8 Mon Sep 17 00:00:00 2001 From: leMicin Date: Thu, 2 Jan 2025 19:48:16 -0500 Subject: [PATCH 04/12] Progress on property refactor --- .../Authentication/IAuthenticationService.cs | 2 - .../Clients/States/ApiState.cs | 2 - .../Filters/FilterProvider.cs | 1 - .../Items/ApiItemConstants.cs | 4 +- src/Sidekick.Apis.Poe/Parser/ItemParser.cs | 3 +- .../Parser/Patterns/ParserPatterns.cs | 1 - .../Parser/Patterns/RegexExtensions.cs | 2 +- .../Properties/Definitions/ArmourProperty.cs | 50 +++ .../Definitions/BlockChanceProperty.cs | 59 ++++ .../Definitions/CorruptedProperty.cs | 46 +++ .../Definitions/EnergyShieldProperty.cs | 50 +++ .../Definitions/EvasionRatingProperty.cs | 50 +++ .../Definitions/GemLevelProperty.cs | 57 ++-- .../Definitions/ItemLevelProperty.cs | 58 ++++ .../Properties/Definitions/QualityProperty.cs | 50 +++ .../Definitions/UnidentifiedProperty.cs | 50 +++ .../Definitions/WeaponDamageProperty.cs | 140 ++++++++ .../Filters/BooleanPropertyFilter.cs | 17 + .../Filters/DoublePropertyFilter.cs | 74 ++++ .../Properties/Filters/IntPropertyFilter.cs | 74 ++++ .../Filters/TriStatePropertyFilter.cs | 11 + .../Parser/Properties/IPropertyParser.cs | 4 +- .../Parser/Properties/PropertyDefinition.cs | 14 +- .../Parser/Properties/PropertyParser.cs | 321 +++--------------- .../Trade/Models/PropertyFilter.cs | 8 - .../Trade/Models/PropertyFilterType.cs | 41 --- .../Trade/Models/PropertyFilters.cs | 7 +- .../Trade/Requests/Filters/ArmourFilters.cs | 6 +- .../Requests/Filters/SearchFilterOption.cs | 6 + .../Trade/Requests/Filters/SearchFilters.cs | 47 +-- .../Trade/Requests/Filters/StatFilterValue.cs | 8 + .../Trade/TradeFilterService.cs | 11 - .../Trade/TradeSearchService.cs | 19 +- src/Sidekick.Common/Game/Items/Category.cs | 41 ++- .../Game/Items/ItemProperties.cs | 10 +- .../Components/Items/ItemComponent.razor | 2 +- .../Poe1/Parser/BodyArmourParsing.cs | 2 +- .../Poe1/Parser/HelmetParsing.cs | 4 +- .../Poe1/Parser/RingParsing.cs | 4 +- .../Poe1/Parser/WeaponParsing.cs | 2 +- .../Poe2/Parser/ArmourParsing.cs | 2 +- 41 files changed, 900 insertions(+), 460 deletions(-) create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Filters/DoublePropertyFilter.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Filters/IntPropertyFilter.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Filters/TriStatePropertyFilter.cs delete mode 100644 src/Sidekick.Apis.Poe/Trade/Models/PropertyFilterType.cs diff --git a/src/Sidekick.Apis.Poe/Authentication/IAuthenticationService.cs b/src/Sidekick.Apis.Poe/Authentication/IAuthenticationService.cs index 0151649a..10d63d58 100644 --- a/src/Sidekick.Apis.Poe/Authentication/IAuthenticationService.cs +++ b/src/Sidekick.Apis.Poe/Authentication/IAuthenticationService.cs @@ -1,5 +1,3 @@ -using Sidekick.Common.Initialization; - namespace Sidekick.Apis.Poe.Authentication { public interface IAuthenticationService diff --git a/src/Sidekick.Apis.Poe/Clients/States/ApiState.cs b/src/Sidekick.Apis.Poe/Clients/States/ApiState.cs index b61304d6..8e38c33d 100644 --- a/src/Sidekick.Apis.Poe/Clients/States/ApiState.cs +++ b/src/Sidekick.Apis.Poe/Clients/States/ApiState.cs @@ -1,5 +1,3 @@ -using Sidekick.Common.Enums; - namespace Sidekick.Apis.Poe.Clients.States { public enum ApiState diff --git a/src/Sidekick.Apis.Poe/Filters/FilterProvider.cs b/src/Sidekick.Apis.Poe/Filters/FilterProvider.cs index b6f1d30e..cb5fa6a2 100644 --- a/src/Sidekick.Apis.Poe/Filters/FilterProvider.cs +++ b/src/Sidekick.Apis.Poe/Filters/FilterProvider.cs @@ -1,6 +1,5 @@ using Sidekick.Apis.Poe.Clients; using Sidekick.Apis.Poe.Filters.Models; -using Sidekick.Apis.Poe.Items.Models; using Sidekick.Common.Cache; using Sidekick.Common.Enums; using Sidekick.Common.Extensions; diff --git a/src/Sidekick.Apis.Poe/Items/ApiItemConstants.cs b/src/Sidekick.Apis.Poe/Items/ApiItemConstants.cs index 9e7d2482..ae2a7ddc 100644 --- a/src/Sidekick.Apis.Poe/Items/ApiItemConstants.cs +++ b/src/Sidekick.Apis.Poe/Items/ApiItemConstants.cs @@ -4,7 +4,7 @@ namespace Sidekick.Apis.Poe.Items; public class ApiItemConstants { - public static Dictionary Poe1Categories = new() + public static readonly Dictionary Poe1Categories = new() { { "accessory", (Category.Accessory, true) }, { "armour", (Category.Armour, true) }, @@ -26,7 +26,7 @@ public class ApiItemConstants { "corpse", (Category.Corpse, true) }, }; - public static Dictionary Poe2Categories = new() + public static readonly Dictionary Poe2Categories = new() { { "accessory", (Category.Accessory, true) }, { "armour", (Category.Armour, true) }, diff --git a/src/Sidekick.Apis.Poe/Parser/ItemParser.cs b/src/Sidekick.Apis.Poe/Parser/ItemParser.cs index 25c76a91..adbd698e 100644 --- a/src/Sidekick.Apis.Poe/Parser/ItemParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/ItemParser.cs @@ -58,8 +58,9 @@ public Item ParseItem(string itemText) var influences = ParseInfluences(parsingItem); var sockets = socketParser.Parse(parsingItem); + var properties = propertyParser.Parse(parsingItem); var modifierLines = ParseModifiers(parsingItem); - var properties = propertyParser.Parse(parsingItem, modifierLines); + propertyParser.ParseAfterModifiers(parsingItem, properties, modifierLines); var pseudoModifiers = pseudoParser.Parse(modifierLines); var item = new Item(invariant: invariant, itemHeader: parsingItem.Header, diff --git a/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs b/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs index 6b7f3bdd..61276e1e 100644 --- a/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs +++ b/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Common.Game.Items; using Sidekick.Common.Game.Languages; namespace Sidekick.Apis.Poe.Parser.Patterns diff --git a/src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs b/src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs index 542ea4dd..13254184 100644 --- a/src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs +++ b/src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs @@ -6,7 +6,7 @@ public static class RegexExtensions { public static Regex ToRegexIntCapture(this string input) => new($"^{Regex.Escape(input)}[^\\d]*(\\d+)"); - public static Regex ToRegexDecimalCapture(this string input) => new($"^{Regex.Escape(input)}[^\\d]*([\\d,\\.]+)"); + public static Regex ToRegexDoubleCapture(this string input) => new($"^{Regex.Escape(input)}[^\\d]*([\\d,\\.]+)"); public static Regex ToRegexAffix(this string input, string superior) { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs new file mode 100644 index 00000000..0d3386b0 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs @@ -0,0 +1,50 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class ArmourProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionArmour.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.Armour = GetInt(Pattern, propertyBlock); + if (itemProperties.Armour > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.Armour <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionArmour, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.Armour, + Checked = false, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateArmourFilters().Filters.Armour = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs new file mode 100644 index 00000000..26da6f5c --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs @@ -0,0 +1,59 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class BlockChanceProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour]; + + public override void Initialize() + { + if (game == GameType.PathOfExile) + { + Pattern = gameLanguageProvider.Language.DescriptionChanceToBlock.ToRegexIntCapture(); + } + else + { + Pattern = gameLanguageProvider.Language.DescriptionBlockChance.ToRegexIntCapture(); + } + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.BlockChance = GetInt(Pattern, propertyBlock); + if (itemProperties.BlockChance > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.BlockChance <= 0) return null; + + var text = game == GameType.PathOfExile ? gameLanguageProvider.Language.DescriptionChanceToBlock : gameLanguageProvider.Language.DescriptionBlockChance; + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = text, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.BlockChance, + Checked = false, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateArmourFilters().Filters.BlockChance = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs new file mode 100644 index 00000000..f7ec8534 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs @@ -0,0 +1,46 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class CorruptedProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Map, Category.Contract, Category.Jewel, Category.Flask]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionCorrupted.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Corrupted = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + var filter = new TriStatePropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionLevel, + Checked = null, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not TriStatePropertyFilter triStateFilter) + { + return; + } + + searchFilters.GetOrCreateMiscFilters().Filters.Corrupted = triStateFilter.Checked.HasValue ? new SearchFilterOption(triStateFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs new file mode 100644 index 00000000..debca175 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs @@ -0,0 +1,50 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class EnergyShieldProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionEnergyShield.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.EnergyShield = GetInt(Pattern, propertyBlock); + if (itemProperties.EnergyShield > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.EnergyShield <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionEnergyShield, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.EnergyShield, + Checked = false, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateArmourFilters().Filters.EnergyShield = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs new file mode 100644 index 00000000..79a3a51d --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs @@ -0,0 +1,50 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class EvasionRatingProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionEvasion.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.EvasionRating = GetInt(Pattern, propertyBlock); + if (itemProperties.EvasionRating > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.EvasionRating <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionEvasion, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.EvasionRating, + Checked = false, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateArmourFilters().Filters.EvasionRating = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs index c57726ed..1b708f1f 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs @@ -1,6 +1,7 @@ using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Items; using Sidekick.Apis.Poe.Parser.Patterns; -using Sidekick.Apis.Poe.Trade.Models; +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game; using Sidekick.Common.Game.Items; @@ -8,58 +9,56 @@ namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; -public class GemLevelProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : PropertyDefinition +public class GemLevelProperty +( + IGameLanguageProvider gameLanguageProvider, + GameType game, + IApiInvariantItemProvider apiInvariantItemProvider +) : PropertyDefinition { private Regex? Pattern { get; set; } - public override bool Enabled => true; + public override List ValidCategories { get; } = [Category.Gem]; public override void Initialize() { Pattern = gameLanguageProvider.Language.DescriptionLevel.ToRegexIntCapture(); } - public override void ParseBeforeModifiers(ItemProperties itemProperties, ParsingItem parsingItem) + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) { - if (parsingItem.Header?.Category != Category.Gem) return; - var propertyBlock = parsingItem.Blocks[1]; itemProperties.GemLevel = GetInt(Pattern, propertyBlock); + if (itemProperties.GemLevel > 0) propertyBlock.Parsed = true; } - public override void ParseAfterModifiers(ItemProperties itemProperties, ParsingItem parsingItem, List modifierLines) + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) { - } + if (item.Properties.GemLevel <= 0) return null; - public PropertyFilter? GetFilter(Item item) - { - if (item.Properties.GemLevel <= 0) + var filter = new IntPropertyFilter(this) { - return null; - } - - var filter = new PropertyFilter(true, PropertyFilterType.Misc_GemLevel, gameLanguageProvider.Language.DescriptionLevel, item.Properties.GemLevel, null); + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionLevel, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.GemLevel, + Checked = true, + }; return filter; } - public void SetTradeRequest(SearchFilters searchFilters, PropertyFilter filter, Item item) + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { - if (filter.Type != PropertyFilterType.Misc_GemLevel || filter.Checked != true) - { - return; - } + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; - if (item.Header.Game == GameType.PathOfExile) + switch (game) { - searchFilters.GetOrCreateMiscFilters().Filters.GemLevel = new StatFilterValue() - { - Min = filter.Value, + case GameType.PathOfExile: searchFilters.GetOrCreateMiscFilters().Filters.GemLevel = new StatFilterValue(intFilter); break; - } - } - else if (item.Header.Game == GameType.PathOfExile2) - { - searchFilters.TypeFilters.Filters.ItemLevel = filter.Value; + case GameType.PathOfExile2 when apiInvariantItemProvider.UncutGemIds.Contains(item.Header.ApiItemId ?? string.Empty): searchFilters.TypeFilters.Filters.ItemLevel = new StatFilterValue(intFilter); break; + + case GameType.PathOfExile2: searchFilters.GetOrCreateMiscFilters().Filters.GemLevel = new StatFilterValue(intFilter); break; } } } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs new file mode 100644 index 00000000..93fbce7c --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs @@ -0,0 +1,58 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class ItemLevelProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Flask, Category.Jewel, Category.Accessory]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionItemLevel.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + if (parsingItem.Header?.Category != Category.Armour && parsingItem.Header?.Category != Category.Accessory && parsingItem.Header?.Category != Category.Map && parsingItem.Header?.Category != Category.Contract) return; + + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.ItemLevel = GetInt(Pattern, propertyBlock); + if (itemProperties.ItemLevel > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.ItemLevel <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionItemLevel, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.ItemLevel, + Checked = item.Properties.ItemLevel >= 80 && item.Properties.MapTier == 0 && item.Header.Rarity != Rarity.Unique, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateMiscFilters().Filters.ItemLevel = new StatFilterValue(intFilter); break; + + case GameType.PathOfExile2: searchFilters.TypeFilters.Filters.ItemLevel = new StatFilterValue(intFilter); break; + } + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs new file mode 100644 index 00000000..5f83152f --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs @@ -0,0 +1,50 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class QualityProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Flask, Category.Gem, Category.Map]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionQuality.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.Quality = GetInt(Pattern, propertyBlock); + if (itemProperties.Quality > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.GemLevel <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionQuality, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.Quality, + Checked = item.Header.Rarity == Rarity.Gem, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMiscFilters().Filters.Quality = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs new file mode 100644 index 00000000..acb54d8b --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs @@ -0,0 +1,50 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class UnidentifiedProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Flask, Category.Map, Category.Contract, Category.Accessory, Category.Jewel]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionUnidentified.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + if (parsingItem.Header?.Category != Category.Armour) return; + + itemProperties.Unidentified = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.GemLevel <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionQuality, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.Quality, + Checked = item.Header.Rarity == Rarity.Gem, + }; + return filter; + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMiscFilters().Filters.Quality = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs new file mode 100644 index 00000000..df04f7b7 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs @@ -0,0 +1,140 @@ +using System.Globalization; +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Modifiers; +using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class WeaponDamageProperty +( + IGameLanguageProvider gameLanguageProvider, + IInvariantModifierProvider invariantModifierProvider +) : PropertyDefinition +{ + private Regex? PhysicalDamagePattern { get; set; } + + private Regex? ElementalDamagePattern { get; set; } + + public override List ValidCategories { get; } = [Category.Weapon]; + + public override void Initialize() + { + PhysicalDamagePattern = gameLanguageProvider.Language.DescriptionPhysicalDamage.ToRegexStartOfLine(); + ElementalDamagePattern = gameLanguageProvider.Language.DescriptionElementalDamage.ToRegexStartOfLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + } + + public override void ParseAfterModifiers(ItemProperties properties, ParsingItem parsingItem, List modifierLines) + { + var propertyBlock = parsingItem.Blocks[1]; + + // Parse damage ranges + foreach (var line in propertyBlock.Lines) + { + var isElemental = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionElementalDamage); + if (isElemental) + { + ParseElementalDamage(line, properties, modifierLines); + continue; + } + + var isPhysical = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionPhysicalDamage); + var isChaos = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionChaosDamage); + var isFire = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionFireDamage); + var isCold = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionColdDamage); + var isLightning = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionLightningDamage); + + if (!isPhysical && !isChaos && !isFire && !isCold && !isLightning) + { + continue; + } + + var matches = new Regex("(\\d+)-(\\d+)").Matches(line.Text); + if (matches.Count <= 0 || matches[0].Groups.Count < 3) + { + continue; + } + + double.TryParse(matches[0].Groups[1].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var min); + double.TryParse(matches[0].Groups[2].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var max); + + var range = new DamageRange(min, max); + if (isPhysical) properties.PhysicalDamage = range; + if (isChaos) properties.ChaosDamage = range; + if (isFire) properties.FireDamage = range; + if (isCold) properties.ColdDamage = range; + if (isLightning) properties.LightningDamage = range; + } + } + + private void ParseElementalDamage(ParsingLine line, ItemProperties itemProperties, List modifierLines) + { + var damageMods = invariantModifierProvider.FireWeaponDamageIds.ToList(); + damageMods.AddRange(invariantModifierProvider.ColdWeaponDamageIds); + damageMods.AddRange(invariantModifierProvider.LightningWeaponDamageIds); + + var itemMods = modifierLines.Where(x => x.Modifiers.Any(y => damageMods.Contains(y.Id ?? string.Empty))).ToList(); + + var matches = new Regex("(\\d+)-(\\d+)").Matches(line.Text); + var matchIndex = 0; + foreach (Match match in matches) + { + if (match.Groups.Count < 3 || itemMods.Count <= matchIndex) + { + continue; + } + + double.TryParse(match.Groups[1].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var min); + double.TryParse(match.Groups[2].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var max); + var range = new DamageRange(min, max); + + var ids = itemMods[matchIndex].Modifiers.Where(x => x.Id != null).Select(x => x.Id!).ToList(); + var isFire = invariantModifierProvider.FireWeaponDamageIds.Any(x => ids.Contains(x)); + if (isFire) + { + itemProperties.FireDamage = range; + matchIndex++; + continue; + } + + var isCold = invariantModifierProvider.ColdWeaponDamageIds.Any(x => ids.Contains(x)); + if (isCold) + { + itemProperties.ColdDamage = range; + matchIndex++; + continue; + } + + var isLightning = invariantModifierProvider.LightningWeaponDamageIds.Any(x => ids.Contains(x)); + if (isLightning) + { + itemProperties.LightningDamage = range; + matchIndex++; + continue; + } + + matchIndex++; + } + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_Damage, resources.Filters_Damage, item.Properties.TotalDamage, @checked: false, normalizeValue); + InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_PhysicalDps, resources.Filters_PDps, item.Properties.PhysicalDps, @checked: false, normalizeValue); + InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_ElementalDps, resources.Filters_EDps, item.Properties.ElementalDps, @checked: false, normalizeValue); + InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_ChaosDps, resources.Filters_ChaosDps, item.Properties.ChaosDps, @checked: false, normalizeValue); + InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_Dps, resources.Filters_Dps, item.Properties.TotalDps, @checked: false, normalizeValue); + + } + + internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs new file mode 100644 index 00000000..1988a200 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs @@ -0,0 +1,17 @@ +namespace Sidekick.Apis.Poe.Parser.Properties.Filters; + +public class BooleanPropertyFilter +{ + internal BooleanPropertyFilter(PropertyDefinition definition) + { + Definition = definition; + } + + public required bool ShowCheckbox { get; init; } + + public bool Checked { get; set; } + + public required string Text { get; init; } + + internal PropertyDefinition Definition { get; } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/DoublePropertyFilter.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/DoublePropertyFilter.cs new file mode 100644 index 00000000..8226b01e --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/DoublePropertyFilter.cs @@ -0,0 +1,74 @@ +namespace Sidekick.Apis.Poe.Parser.Properties.Filters; + +public class DoublePropertyFilter : BooleanPropertyFilter +{ + internal DoublePropertyFilter( + PropertyDefinition definition) : base(definition) + { + } + + public required bool NormalizeEnabled { get; init; } + + public required double NormalizeValue { get; set; } + + public required double Value { get; set; } + + public double? Min { get; set; } + + public double? Max { get; set;} + + /// + /// Normalize the Min value with NormalizeValue. + /// + public void NormalizeMinValue() + { + if (!decimal.TryParse(Value.ToString(), out var value) || value == 0) + { + return; + } + + if (value > 0) + { + Min = (int)Math.Max((1 - (decimal)NormalizeValue) * value, 0); + } + else + { + Min = (int)Math.Min((1 + (decimal)NormalizeValue) * value, 0); + } + } + + /// + /// Normalize the Max value, +1 and/or NormalizeValue. + /// + public void NormalizeMaxValue() + { + if (!double.TryParse(Value.ToString(), out var value) || value == 0) + { + return; + } + + if (value > 0) + { + Max = Math.Max(Math.Max(value + 1, (1 + (double)NormalizeValue) * value), 0); + } + else + { + Max = Math.Min(Math.Max(value + 1, (1 - (double)NormalizeValue) * value), 0); + } + } + + /// + /// Sets the filter to be the exact value. + /// + public void SetExactValue() + { + if (!double.TryParse(Value.ToString(), out var value)) + { + return; + } + + Min = value; + Max = value; + } + +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/IntPropertyFilter.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/IntPropertyFilter.cs new file mode 100644 index 00000000..06a5df5f --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/IntPropertyFilter.cs @@ -0,0 +1,74 @@ +namespace Sidekick.Apis.Poe.Parser.Properties.Filters; + +public class IntPropertyFilter : BooleanPropertyFilter +{ + internal IntPropertyFilter( + PropertyDefinition definition) : base(definition) + { + } + + public required bool NormalizeEnabled { get; init; } + + public required double NormalizeValue { get; set; } + + public required int Value { get; set; } + + public int? Min { get; set; } + + public int? Max { get; set;} + + /// + /// Normalize the Min value with NormalizeValue. + /// + public void NormalizeMinValue() + { + if (!int.TryParse(Value.ToString(), out var value) || value == 0) + { + return; + } + + if (value > 0) + { + Min = (int)Math.Max((1 - (decimal)NormalizeValue) * value, 0); + } + else + { + Min = (int)Math.Min((1 + (decimal)NormalizeValue) * value, 0); + } + } + + /// + /// Normalize the Max value, +1 and/or NormalizeValue. + /// + public void NormalizeMaxValue() + { + if (!int.TryParse(Value.ToString(), out var value) || value == 0) + { + return; + } + + if (value > 0) + { + Max = (int)Math.Max(Math.Max(value + 1, (1 + NormalizeValue) * value), 0); + } + else + { + Max = (int)Math.Min(Math.Max(value + 1, (1 - NormalizeValue) * value), 0); + } + } + + /// + /// Sets the filter to be the exact value. + /// + public void SetExactValue() + { + if (!int.TryParse(Value.ToString(), out var value)) + { + return; + } + + Min = value; + Max = value; + } + +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/TriStatePropertyFilter.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/TriStatePropertyFilter.cs new file mode 100644 index 00000000..906ca5d7 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/TriStatePropertyFilter.cs @@ -0,0 +1,11 @@ +namespace Sidekick.Apis.Poe.Parser.Properties.Filters; + +public class TriStatePropertyFilter : BooleanPropertyFilter +{ + internal TriStatePropertyFilter( + PropertyDefinition definition) : base(definition) + { + } + + public new bool? Checked { get; set; } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs b/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs index f965c8fa..8268a224 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs @@ -5,5 +5,7 @@ namespace Sidekick.Apis.Poe.Parser.Properties; public interface IPropertyParser: IInitializableService { - ItemProperties Parse(ParsingItem parsingItem, List modifierLines); + ItemProperties Parse(ParsingItem parsingItem); + + void ParseAfterModifiers(ParsingItem parsingItem, ItemProperties properties, List modifierLines); } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs index e716fc21..3cd30089 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs @@ -1,20 +1,24 @@ using System.Globalization; using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; namespace Sidekick.Apis.Poe.Parser.Properties; public abstract class PropertyDefinition { - private static readonly Regex parseHashPattern = new("\\#"); - - public abstract bool Enabled { get; } + public abstract List ValidCategories { get; } public abstract void Initialize(); - public abstract void ParseBeforeModifiers(ItemProperties itemProperties, ParsingItem parsingItem); + public abstract void Parse(ItemProperties itemProperties, ParsingItem parsingItem); + + public virtual void ParseAfterModifiers(ItemProperties itemProperties, ParsingItem parsingItem, List modifierLines) {} + + public abstract BooleanPropertyFilter? GetFilter(Item item, double normalizeValue); - public abstract void ParseAfterModifiers(ItemProperties itemProperties, ParsingItem parsingItem, List modifierLines); + internal abstract void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter); protected static bool GetBool(Regex? pattern, ParsingItem parsingItem) { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs index a3ecc35d..ec006dd1 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs @@ -1,35 +1,27 @@ using System.Globalization; using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Items; using Sidekick.Apis.Poe.Modifiers; using Sidekick.Apis.Poe.Parser.Patterns; +using Sidekick.Apis.Poe.Parser.Properties.Definitions; +using Sidekick.Common.Extensions; using Sidekick.Common.Game.Items; using Sidekick.Common.Game.Languages; +using Sidekick.Common.Settings; namespace Sidekick.Apis.Poe.Parser.Properties; public class PropertyParser ( IGameLanguageProvider gameLanguageProvider, - IInvariantModifierProvider invariantModifierProvider + IInvariantModifierProvider invariantModifierProvider, + IApiInvariantItemProvider apiInvariantItemProvider, + ISettingsService settingsService ) : IPropertyParser { public int Priority => 200; - private Regex? Armor { get; set; } - - private Regex? EnergyShield { get; set; } - - private Regex? Evasion { get; set; } - - private Regex? ChanceToBlock { get; set; } - - private Regex? Quality { get; set; } - - private Regex? AlternateQuality { get; set; } - - private Regex? Level { get; set; } - - private Regex? ItemLevel { get; set; } + private List Definitions { get; set; } = new(); private Regex? MapTier { get; set; } @@ -43,35 +35,38 @@ IInvariantModifierProvider invariantModifierProvider private Regex? CriticalStrikeChance { get; set; } - private Regex? ElementalDamage { get; set; } - - private Regex? PhysicalDamage { get; set; } - private Regex? Blighted { get; set; } private Regex? BlightRavaged { get; set; } private Regex? AreaLevel { get; set; } - private Regex? Unidentified { get; set; } + public async Task Initialize() + { + var leagueId = await settingsService.GetString(SettingKeys.LeagueId); + var game = leagueId.GetGameFromLeagueId(); - private Regex? Corrupted { get; set; } + Definitions.Clear(); + Definitions.AddRange([ + new ArmourProperty(gameLanguageProvider), + new BlockChanceProperty(gameLanguageProvider, game), + new EvasionRatingProperty(gameLanguageProvider), + new EnergyShieldProperty(gameLanguageProvider), + new GemLevelProperty(gameLanguageProvider, game, apiInvariantItemProvider), + new CorruptedProperty(gameLanguageProvider), + new ItemLevelProperty(gameLanguageProvider, game), + new QualityProperty(gameLanguageProvider), + new UnidentifiedProperty(gameLanguageProvider), + new WeaponDamageProperty(gameLanguageProvider, invariantModifierProvider), + ]); + + foreach (var definition in Definitions) + { + definition.Initialize(); + } - public Task Initialize() - { - Armor = gameLanguageProvider.Language.DescriptionArmour.ToRegexIntCapture(); - EnergyShield = gameLanguageProvider.Language.DescriptionEnergyShield.ToRegexIntCapture(); - Evasion = gameLanguageProvider.Language.DescriptionEvasion.ToRegexIntCapture(); - ChanceToBlock = gameLanguageProvider.Language.DescriptionChanceToBlock.ToRegexIntCapture(); - Level = gameLanguageProvider.Language.DescriptionLevel.ToRegexIntCapture(); - ItemLevel = gameLanguageProvider.Language.DescriptionItemLevel.ToRegexIntCapture(); AttacksPerSecond = gameLanguageProvider.Language.DescriptionAttacksPerSecond.ToRegexDecimalCapture(); CriticalStrikeChance = gameLanguageProvider.Language.DescriptionCriticalStrikeChance.ToRegexDecimalCapture(); - ElementalDamage = gameLanguageProvider.Language.DescriptionElementalDamage.ToRegexStartOfLine(); - PhysicalDamage = gameLanguageProvider.Language.DescriptionPhysicalDamage.ToRegexStartOfLine(); - - Quality = gameLanguageProvider.Language.DescriptionQuality.ToRegexIntCapture(); - AlternateQuality = gameLanguageProvider.Language.DescriptionAlternateQuality.ToRegexLine(); MapTier = gameLanguageProvider.Language.DescriptionMapTier.ToRegexIntCapture(); AreaLevel = gameLanguageProvider.Language.DescriptionAreaLevel.ToRegexIntCapture(); @@ -80,214 +75,52 @@ public Task Initialize() MonsterPackSize = gameLanguageProvider.Language.DescriptionMonsterPackSize.ToRegexIntCapture(); Blighted = gameLanguageProvider.Language.AffixBlighted.ToRegexAffix(gameLanguageProvider.Language.AffixSuperior); BlightRavaged = gameLanguageProvider.Language.AffixBlightRavaged.ToRegexAffix(gameLanguageProvider.Language.AffixSuperior); - - Unidentified = gameLanguageProvider.Language.DescriptionUnidentified.ToRegexLine(); - Corrupted = gameLanguageProvider.Language.DescriptionCorrupted.ToRegexLine(); - - return Task.CompletedTask; } - public ItemProperties Parse(ParsingItem parsingItem, List modifierLines) + public ItemProperties Parse(ParsingItem parsingItem) { + var properties = new ItemProperties(); + foreach (var definition in Definitions) + { + if (!definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; + + definition.Parse(properties, parsingItem); + } + + return properties; return parsingItem.Header?.Category switch { - Category.Gem => ParseGemProperties(parsingItem), Category.Map or Category.Contract => ParseMapProperties(parsingItem), - Category.Accessory => ParseAccessoryProperties(parsingItem), - Category.Armour => ParseArmourProperties(parsingItem), Category.Weapon => ParseWeaponProperties(parsingItem, modifierLines), - Category.Jewel => ParseJewelProperties(parsingItem), - Category.Flask => ParseFlaskProperties(parsingItem), Category.Sanctum => ParseSanctumProperties(parsingItem), Category.Logbook => ParseLogbookProperties(parsingItem), _ => new ItemProperties(), }; } - private ItemProperties ParseWeaponProperties(ParsingItem parsingItem, List modifierLines) - { - var propertyBlock = parsingItem.Blocks[1]; - var attacksPerSecond = GetDouble(AttacksPerSecond, propertyBlock); - var criticalStrikeChance = GetDouble(CriticalStrikeChance, propertyBlock); - - var properties = new ItemProperties - { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - Quality = GetInt(Quality, propertyBlock), - AttacksPerSecond = attacksPerSecond, - CriticalStrikeChance = criticalStrikeChance, - }; - - // Parse damage ranges - foreach (var line in propertyBlock.Lines) - { - var isElemental = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionElementalDamage); - if (isElemental) - { - ParseElementalDamage(line, properties, modifierLines); - continue; - } - - var isPhysical = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionPhysicalDamage); - var isChaos = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionChaosDamage); - var isFire = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionFireDamage); - var isCold = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionColdDamage); - var isLightning = line.Text.StartsWith(gameLanguageProvider.Language.DescriptionLightningDamage); - if (!isPhysical && !isChaos && !isFire && !isCold && !isLightning) - { - continue; - } - - var matches = new Regex("(\\d+)-(\\d+)").Matches(line.Text); - if (matches.Count <= 0 || matches[0].Groups.Count < 3) - { - continue; - } - - double.TryParse(matches[0].Groups[1].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var min); - double.TryParse(matches[0].Groups[2].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var max); - - var range = new DamageRange(min, max); - if (isPhysical) properties.PhysicalDamage = range; - if (isChaos) properties.ChaosDamage = range; - if (isFire) properties.FireDamage = range; - if (isCold) properties.ColdDamage = range; - if (isLightning) properties.LightningDamage = range; - } - - return properties; - } - - private void ParseElementalDamage(ParsingLine line, ItemProperties itemProperties, List modifierLines) + public void ParseAfterModifiers(ParsingItem parsingItem, ItemProperties properties, List modifierLines) { - var damageMods = invariantModifierProvider.FireWeaponDamageIds.ToList(); - damageMods.AddRange(invariantModifierProvider.ColdWeaponDamageIds); - damageMods.AddRange(invariantModifierProvider.LightningWeaponDamageIds); - - var itemMods = modifierLines.Where(x => x.Modifiers.Any(y => damageMods.Contains(y.Id ?? string.Empty))).ToList(); - - var matches = new Regex("(\\d+)-(\\d+)").Matches(line.Text); - var matchIndex = 0; - foreach (Match match in matches) + foreach (var definition in Definitions) { - if (match.Groups.Count < 3 || itemMods.Count <= matchIndex) - { - continue; - } - - double.TryParse(match.Groups[1].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var min); - double.TryParse(match.Groups[2].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var max); - var range = new DamageRange(min, max); - - var ids = itemMods[matchIndex].Modifiers.Where(x => x.Id != null).Select(x => x.Id!).ToList(); - var isFire = invariantModifierProvider.FireWeaponDamageIds.Any(x => ids.Contains(x)); - if (isFire) - { - itemProperties.FireDamage = range; - matchIndex++; - continue; - } + if (!definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; - var isCold = invariantModifierProvider.ColdWeaponDamageIds.Any(x => ids.Contains(x)); - if (isCold) - { - itemProperties.ColdDamage = range; - matchIndex++; - continue; - } - - var isLightning = invariantModifierProvider.LightningWeaponDamageIds.Any(x => ids.Contains(x)); - if (isLightning) - { - itemProperties.LightningDamage = range; - matchIndex++; - continue; - } - - matchIndex++; + definition.ParseAfterModifiers(properties, parsingItem, modifierLines); } } - private ItemProperties ParseArmourProperties(ParsingItem parsingItem) - { - var propertyBlock = parsingItem.Blocks[1]; - - return new ItemProperties() - { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - Quality = GetInt(Quality, propertyBlock), - Armor = GetInt(Armor, propertyBlock), - EnergyShield = GetInt(EnergyShield, propertyBlock), - Evasion = GetInt(Evasion, propertyBlock), - ChanceToBlock = GetInt(ChanceToBlock, propertyBlock), - }; - } - - private ItemProperties ParseAccessoryProperties(ParsingItem parsingItem) - { - return new ItemProperties() - { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - }; - } - private ItemProperties ParseMapProperties(ParsingItem parsingItem) { var propertyBlock = parsingItem.Blocks[1]; return new ItemProperties() { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), Blighted = Blighted?.IsMatch(parsingItem.Blocks[0].Lines[^1].Text) ?? false, BlightRavaged = BlightRavaged?.IsMatch(parsingItem.Blocks[0].Lines[^1].Text) ?? false, ItemQuantity = GetInt(ItemQuantity, propertyBlock), ItemRarity = GetInt(ItemRarity, propertyBlock), MonsterPackSize = GetInt(MonsterPackSize, propertyBlock), MapTier = GetInt(MapTier, propertyBlock), - Quality = GetInt(Quality, propertyBlock), - }; - } - - private ItemProperties ParseGemProperties(ParsingItem parsingItem) - { - var propertyBlock = parsingItem.Blocks[1]; - - return new ItemProperties() - { - Corrupted = GetBool(Corrupted, parsingItem), - GemLevel = GetInt(Level, propertyBlock), - Quality = GetInt(Quality, propertyBlock), - AlternateQuality = GetBool(AlternateQuality, parsingItem), - }; - } - - private ItemProperties ParseJewelProperties(ParsingItem parsingItem) - { - return new ItemProperties() - { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - }; - } - - private ItemProperties ParseFlaskProperties(ParsingItem parsingItem) - { - return new ItemProperties() - { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - Quality = GetInt(Quality, parsingItem), }; } @@ -306,70 +139,4 @@ private ItemProperties ParseLogbookProperties(ParsingItem parsingItem) AreaLevel = GetInt(AreaLevel, parsingItem), }; } - - private static bool GetBool(Regex? pattern, ParsingItem parsingItem) - { - if (pattern == null) - { - return false; - } - - return parsingItem.TryParseRegex(pattern, out _); - } - - private static int GetInt(Regex? pattern, ParsingItem parsingItem) - { - if (pattern == null) - { - return 0; - } - - if (parsingItem.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) - { - return result; - } - - return 0; - } - - private static int GetInt(Regex? pattern, ParsingBlock parsingBlock) - { - if (pattern == null) - { - return 0; - } - - if (parsingBlock.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) - { - return result; - } - - return 0; - } - - private static double GetDouble(Regex? pattern, ParsingBlock parsingBlock) - { - if (pattern == null) - { - return 0; - } - - if (!parsingBlock.TryParseRegex(pattern, out var match)) - { - return 0; - } - - var value = match.Groups[1].Value.Replace(",", "."); - if (value.EndsWith("%")) - { - value = value.TrimEnd('%'); - } - - if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) - { - return result; - } - - return 0; - } } diff --git a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs index 9c132998..93f14293 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs @@ -68,14 +68,6 @@ public FilterValueType ValueType } } - public bool ShowCheckbox - { - get - { - return Type != PropertyFilterType.Weapon_ChaosDps; - } - } - /// /// Normalize the Min value with NormalizeValue. /// diff --git a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilterType.cs b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilterType.cs deleted file mode 100644 index 0d6e79f5..00000000 --- a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilterType.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Sidekick.Apis.Poe.Trade.Models; - -public enum PropertyFilterType -{ - Armour_Armour, - Armour_Evasion, - Armour_EnergyShield, - Armour_Block, - - Category, - - Socket_Links, - - Map_AreaLevel, - Map_ItemQuantity, - Map_ItemRarity, - Map_MonsterPackSize, - Map_Blighted, - Map_BlightRavaged, - Map_Tier, - - Misc_Quality, - Misc_GemLevel, - Misc_ItemLevel, - Misc_Corrupted, - Misc_Scourged, - Misc_Influence_Crusader, - Misc_Influence_Elder, - Misc_Influence_Hunter, - Misc_Influence_Redeemer, - Misc_Influence_Shaper, - Misc_Influence_Warlord, - - Weapon_Damage, - Weapon_PhysicalDps, - Weapon_ElementalDps, - Weapon_ChaosDps, - Weapon_Dps, - Weapon_AttacksPerSecond, - Weapon_CriticalStrikeChance, -} diff --git a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs index 6b561112..5abc368c 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs @@ -1,3 +1,5 @@ +using Sidekick.Apis.Poe.Parser.Properties.Filters; + namespace Sidekick.Apis.Poe.Trade.Models { public class PropertyFilters @@ -5,9 +7,6 @@ public class PropertyFilters public bool BaseTypeFilterApplied { get; set; } = true; public bool ClassFilterApplied { get; set; } public bool RarityFilterApplied { get; set; } - public List Weapon { get; set; } = new(); - public List Armour { get; set; } = new(); - public List Map { get; set; } = new(); - public List Misc { get; set; } = new(); + public List Filters { get; set; } = new(); } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs index cb18a8de..69264de6 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs @@ -5,15 +5,15 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters internal class ArmourFilters { [JsonPropertyName("ar")] - public StatFilterValue? Armor { get; set; } + public StatFilterValue? Armour { get; set; } [JsonPropertyName("es")] public StatFilterValue? EnergyShield { get; set; } [JsonPropertyName("ev")] - public StatFilterValue? Evasion { get; set; } + public StatFilterValue? EvasionRating { get; set; } [JsonPropertyName("block")] - public StatFilterValue? Block { get; set; } + public StatFilterValue? BlockChance { get; set; } } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs index 6785c1cd..7f36fb4f 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs @@ -1,3 +1,4 @@ +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; namespace Sidekick.Apis.Poe.Trade.Requests.Filters @@ -14,6 +15,11 @@ public SearchFilterOption(PropertyFilter filter) Option = filter.Checked == true ? "true" : "false"; } + public SearchFilterOption(TriStatePropertyFilter filter) + { + Option = filter.Checked == true ? "true" : "false"; + } + public string Option { get; set; } } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs index 15c9cd81..56f3fc54 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs @@ -1,36 +1,37 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +internal class SearchFilters { - internal class SearchFilters - { - [JsonPropertyName("type_filters")] - public TypeFilterGroup TypeFilters { get; set; } = new(); + [JsonPropertyName("type_filters")] + public TypeFilterGroup TypeFilters { get; set; } = new(); + + [JsonPropertyName("trade_filters")] + public TradeFilterGroup? TradeFilters { get; set; } - [JsonPropertyName("trade_filters")] - public TradeFilterGroup? TradeFilters { get; set; } + [JsonPropertyName("misc_filters")] + public MiscFilterGroup? MiscFilters { get; set; } - [JsonPropertyName("misc_filters")] - public MiscFilterGroup? MiscFilters { get; set; } + public MiscFilterGroup GetOrCreateMiscFilters() => MiscFilters ??= new(); - public MiscFilterGroup GetOrCreateMiscFilters() => MiscFilters ??= new(); + [JsonPropertyName("weapon_filters")] + public WeaponFilterGroup? WeaponFilters { get; set; } - [JsonPropertyName("weapon_filters")] - public WeaponFilterGroup? WeaponFilters { get; set; } + [JsonPropertyName("armour_filters")] + public ArmourFilterGroup? ArmourFilters { get; set; } - [JsonPropertyName("armour_filters")] - public ArmourFilterGroup? ArmourFilters { get; set; } + public ArmourFilterGroup GetOrCreateArmourFilters() => ArmourFilters ??= new(); - [JsonPropertyName("equipment_filters")] - public EquipmentFilterGroup? EquipmentFilters { get; set; } + [JsonPropertyName("equipment_filters")] + public EquipmentFilterGroup? EquipmentFilters { get; set; } - [JsonPropertyName("socket_filters")] - public SocketFilterGroup? SocketFilters { get; set; } + [JsonPropertyName("socket_filters")] + public SocketFilterGroup? SocketFilters { get; set; } - [JsonPropertyName("req_filters")] - public RequirementFilterGroup? RequirementFilters { get; set; } + [JsonPropertyName("req_filters")] + public RequirementFilterGroup? RequirementFilters { get; set; } - [JsonPropertyName("map_filters")] - public MapFilterGroup? MapFilters { get; set; } - } + [JsonPropertyName("map_filters")] + public MapFilterGroup? MapFilters { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs index 8b724154..184575bc 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs @@ -1,3 +1,4 @@ +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; namespace Sidekick.Apis.Poe.Trade.Requests.Filters; @@ -20,6 +21,13 @@ public StatFilterValue(PropertyFilter filter) Max = filter.Max; } + public StatFilterValue(IntPropertyFilter filter) + { + Option = filter.Checked ? "true" : "false"; + Min = filter.Min; + Max = filter.Max; + } + public StatFilterValue(ModifierFilter filter) { Option = filter.Line.OptionValue; diff --git a/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs b/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs index 5e61fba9..c27e3c79 100644 --- a/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs +++ b/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs @@ -56,18 +56,7 @@ public async Task GetPropertyFilters(Item item) var normalizeValue = await settingsService.GetObject(SettingKeys.PriceCheckNormalizeValue); var result = new PropertyFilters(); - // Armour properties - InitializeNumericFilter(result.Armour, PropertyFilterType.Armour_Armour, gameLanguageProvider.Language.DescriptionArmour, item.Properties.Armor, false, normalizeValue); - InitializeNumericFilter(result.Armour, PropertyFilterType.Armour_Evasion, gameLanguageProvider.Language.DescriptionEvasion, item.Properties.Evasion, false, normalizeValue); - InitializeNumericFilter(result.Armour, PropertyFilterType.Armour_EnergyShield, gameLanguageProvider.Language.DescriptionEnergyShield, item.Properties.EnergyShield, false, normalizeValue); - InitializeNumericFilter(result.Armour, PropertyFilterType.Armour_Block, gameLanguageProvider.Language.DescriptionChanceToBlock, item.Properties.ChanceToBlock, false, normalizeValue); - // Weapon properties - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_Damage, resources.Filters_Damage, item.Properties.TotalDamage, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_PhysicalDps, resources.Filters_PDps, item.Properties.PhysicalDps, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_ElementalDps, resources.Filters_EDps, item.Properties.ElementalDps, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_ChaosDps, resources.Filters_ChaosDps, item.Properties.ChaosDps, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_Dps, resources.Filters_Dps, item.Properties.TotalDps, @checked: false, normalizeValue); InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_AttacksPerSecond, gameLanguageProvider.Language.DescriptionAttacksPerSecond, item.Properties.AttacksPerSecond, false, normalizeValue); InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_CriticalStrikeChance, gameLanguageProvider.Language.DescriptionCriticalStrikeChance, item.Properties.CriticalStrikeChance, false, normalizeValue); diff --git a/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs b/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs index 5d5978fa..293d1723 100644 --- a/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs +++ b/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs @@ -251,12 +251,12 @@ public async Task> Search(Item item, PropertyFilters? switch (propertyFilter.Type) { case PropertyFilterType.Armour_Armour: - filters.Filters.Armor = new StatFilterValue(propertyFilter); + filters.Filters.Armour = new StatFilterValue(propertyFilter); hasValue = true; break; case PropertyFilterType.Armour_Block: - filters.Filters.Block = new StatFilterValue(propertyFilter); + filters.Filters.BlockChance = new StatFilterValue(propertyFilter); hasValue = true; break; @@ -266,7 +266,7 @@ public async Task> Search(Item item, PropertyFilters? break; case PropertyFilterType.Armour_Evasion: - filters.Filters.Evasion = new StatFilterValue(propertyFilter); + filters.Filters.EvasionRating = new StatFilterValue(propertyFilter); hasValue = true; break; } @@ -410,13 +410,6 @@ public async Task> Search(Item item, PropertyFilters? foreach (var propertyFilter in propertyFilters) { - if (propertyFilter.Type == PropertyFilterType.Misc_Corrupted) - { - filters.Filters.Corrupted = propertyFilter.Checked.HasValue ? new SearchFilterOption(propertyFilter) : null; - hasValue = filters.Filters.Corrupted != null; - break; - } - if (propertyFilter.Checked != true) { continue; @@ -715,10 +708,10 @@ private TradeItem GetItem(GameType game, Result result) { ItemLevel = result.Item?.ItemLevel ?? 0, Corrupted = result.Item?.Corrupted ?? false, - Identified = result.Item?.Identified ?? false, - Armor = result.Item?.Extended?.ArmourAtMax ?? 0, + Unidentified = result.Item?.Identified ?? false, + Armour = result.Item?.Extended?.ArmourAtMax ?? 0, EnergyShield = result.Item?.Extended?.EnergyShieldAtMax ?? 0, - Evasion = result.Item?.Extended?.EvasionAtMax ?? 0, + EvasionRating = result.Item?.Extended?.EvasionAtMax ?? 0, TotalDps = result.Item?.Extended?.DamagePerSecond ?? 0, ElementalDps = result.Item?.Extended?.ElementalDps ?? 0, PhysicalDps = result.Item?.Extended?.PhysicalDps ?? 0, diff --git a/src/Sidekick.Common/Game/Items/Category.cs b/src/Sidekick.Common/Game/Items/Category.cs index 03ecba35..7d8dd9bf 100644 --- a/src/Sidekick.Common/Game/Items/Category.cs +++ b/src/Sidekick.Common/Game/Items/Category.cs @@ -2,25 +2,24 @@ namespace Sidekick.Common.Game.Items; public enum Category { - Unknown = 0, - Accessory = 1, - Armour = 2, - DivinationCard = 3, - Currency = 4, - Flask = 5, - Gem = 6, - Jewel = 7, - Map = 8, - Weapon = 9, - Leaguestone = 10, - ItemisedMonster = 11, - HeistEquipment = 12, - Contract = 13, - Logbook = 14, - Sanctum = 15, - MemoryLine = 16, - Affliction = 17, - EmbersOfTheAllflame = 18, - Tincture = 19, - Corpse = 20, + Unknown, + Accessory, + Armour, + DivinationCard, + Currency, + Flask, + Gem, + Jewel, + Map, + Weapon, + Leaguestone, + ItemisedMonster, + HeistEquipment, + Contract, + Logbook, + Sanctum, + MemoryLine, + Affliction, + Tincture, + Corpse, } diff --git a/src/Sidekick.Common/Game/Items/ItemProperties.cs b/src/Sidekick.Common/Game/Items/ItemProperties.cs index 84aab0dc..b7f94eca 100644 --- a/src/Sidekick.Common/Game/Items/ItemProperties.cs +++ b/src/Sidekick.Common/Game/Items/ItemProperties.cs @@ -2,24 +2,22 @@ namespace Sidekick.Common.Game.Items; public class ItemProperties { - public bool Identified { get; set; } + public bool Unidentified { get; set; } public int ItemLevel { get; set; } public bool Corrupted { get; set; } - public int Armor { get; set; } + public int Armour { get; set; } public int EnergyShield { get; set; } - public int Evasion { get; set; } + public int EvasionRating { get; set; } - public int ChanceToBlock { get; set; } + public int BlockChance { get; set; } public int Quality { get; set; } - public bool AlternateQuality { get; set; } - public int GemLevel { get; set; } public int MapTier { get; set; } diff --git a/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor b/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor index 77997c2f..587aa7d7 100644 --- a/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor +++ b/src/Sidekick.Modules.Trade/Components/Items/ItemComponent.razor @@ -29,7 +29,7 @@ } } - @if (!Item.Properties.Identified) + @if (!Item.Properties.Unidentified) { @Resources["Unidentified"] diff --git a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/BodyArmourParsing.cs b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/BodyArmourParsing.cs index 831dad09..35645781 100644 --- a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/BodyArmourParsing.cs +++ b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/BodyArmourParsing.cs @@ -47,7 +47,7 @@ can deny that my work has made quite the splash..."" Assert.Equal("Carcass Jack", actual.Header.ApiName); Assert.Equal("Varnished Coat", actual.Header.ApiType); Assert.Equal(20, actual.Properties.Quality); - Assert.Equal(960, actual.Properties.Evasion); + Assert.Equal(960, actual.Properties.EvasionRating); Assert.Equal(186, actual.Properties.EnergyShield); Assert.Equal(6, actual.Sockets.Count(x => x.Group == 0)); diff --git a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/HelmetParsing.cs b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/HelmetParsing.cs index c461fb4a..3a401ecd 100644 --- a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/HelmetParsing.cs +++ b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/HelmetParsing.cs @@ -80,9 +80,9 @@ but merely a long sleep made eternal. Assert.Equal("Starkonja's Head", actual.Header.ApiName); Assert.Equal("Silken Hood", actual.Header.ApiType); - Assert.True(actual.Properties.Identified); + Assert.True(actual.Properties.Unidentified); Assert.Equal(63, actual.Properties.ItemLevel); - Assert.Equal(793, actual.Properties.Evasion); + Assert.Equal(793, actual.Properties.EvasionRating); actual.AssertHasModifier(ModifierCategory.Explicit, "+# to Dexterity", 53); actual.AssertHasModifier(ModifierCategory.Explicit, "#% increased Damage when on Low Life", 50); diff --git a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/RingParsing.cs b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/RingParsing.cs index 020a7b1f..cf8aefd5 100644 --- a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/RingParsing.cs +++ b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/RingParsing.cs @@ -37,7 +37,7 @@ Adds 8 to 13 Physical Damage to Attacks Assert.Equal("Ruby Ring", actual.Header.ApiType); Assert.Equal(76, actual.Properties.ItemLevel); - Assert.True(actual.Properties.Identified); + Assert.True(actual.Properties.Unidentified); Assert.True(actual.Properties.Corrupted); actual.AssertHasModifier(ModifierCategory.Implicit, "Anger has #% increased Aura Effect", 18); @@ -76,7 +76,7 @@ While Berek slept."" - Berek and the Untamed "); - Assert.True(actual.Properties.Identified); + Assert.True(actual.Properties.Unidentified); } } } diff --git a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/WeaponParsing.cs b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/WeaponParsing.cs index 957a18e3..728d2e11 100644 --- a/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/WeaponParsing.cs +++ b/tests/Sidekick.Apis.Poe.Tests/Poe1/Parser/WeaponParsing.cs @@ -34,7 +34,7 @@ One Handed Axe Assert.Equal(Category.Weapon, actual.Header.Category); Assert.Equal(Rarity.Unique, actual.Header.Rarity); Assert.Equal("Jade Hatchet", actual.Header.ApiType); - Assert.False(actual.Properties.Identified); + Assert.False(actual.Properties.Unidentified); } [Fact] diff --git a/tests/Sidekick.Apis.Poe.Tests/Poe2/Parser/ArmourParsing.cs b/tests/Sidekick.Apis.Poe.Tests/Poe2/Parser/ArmourParsing.cs index 3e12ad6d..67d992d5 100644 --- a/tests/Sidekick.Apis.Poe.Tests/Poe2/Parser/ArmourParsing.cs +++ b/tests/Sidekick.Apis.Poe.Tests/Poe2/Parser/ArmourParsing.cs @@ -48,7 +48,7 @@ the world hearkens. Assert.Equal("Steeltoe Boots", actual.Header.ApiType); Assert.Equal("Thunderstep", actual.Header.ApiName); - Assert.Equal(129, actual.Properties.Evasion); + Assert.Equal(129, actual.Properties.EvasionRating); Assert.Single(actual.Sockets); From 05604a9eacecc05653d33b71b9c7e51727846b6f Mon Sep 17 00:00:00 2001 From: leMicin Date: Fri, 3 Jan 2025 19:56:51 -0500 Subject: [PATCH 05/12] "Refactor property filter handling and remove obsolete code Replaced manual property filter logic with a modular approach using new `PropertyParser` and filter components for better maintainability. Removed outdated filter management code and introduced components for double and int property filters. Streamlined property handling in `TradeFilterService` and improved flexibility for parsing trade requests." --- src/Sidekick.Apis.Poe/ITradeFilterService.cs | 1 + src/Sidekick.Apis.Poe/ITradeSearchService.cs | 1 + .../Localization/FilterResources.cs | 13 - .../Parser/Headers/HeaderParser.cs | 1 - src/Sidekick.Apis.Poe/Parser/ItemParser.cs | 61 +--- .../Parser/Modifiers/ModifierParser.cs | 5 + .../Parser/Patterns/IParserPatterns.cs | 16 - .../Parser/Patterns/ParserPatterns.cs | 53 --- .../Definitions/AreaLevelProperty.cs | 52 +++ .../Properties/Definitions/ArmourProperty.cs | 3 +- .../Definitions/AttacksPerSecondProperty.cs | 49 +++ .../Definitions/BlightRavagedProperty.cs | 45 +++ .../Definitions/BlightedProperty.cs | 45 +++ .../Definitions/BlockChanceProperty.cs | 3 +- .../Definitions/CorruptedProperty.cs | 7 +- .../Definitions/CriticalHitChanceProperty.cs | 58 ++++ .../Definitions/CrusaderProperty.cs | 44 +++ .../Properties/Definitions/ElderProperty.cs | 44 +++ .../Definitions/EnergyShieldProperty.cs | 3 +- .../Definitions/EvasionRatingProperty.cs | 3 +- .../Definitions/GemLevelProperty.cs | 3 +- .../Properties/Definitions/HunterProperty.cs | 44 +++ .../Definitions/ItemLevelProperty.cs | 11 +- .../Definitions/ItemQuantityProperty.cs | 49 +++ .../Definitions/ItemRarityProperty.cs | 49 +++ .../Properties/Definitions/MapTierProperty.cs | 49 +++ .../Definitions/MonsterPackSizeProperty.cs | 49 +++ .../Properties/Definitions/QualityProperty.cs | 3 +- .../Definitions/RedeemerProperty.cs | 44 +++ .../Definitions/SeparatorProperty.cs | 30 ++ .../Properties/Definitions/ShaperProperty.cs | 44 +++ .../Definitions/UnidentifiedProperty.cs | 5 +- .../Properties/Definitions/WarlordProperty.cs | 44 +++ .../Definitions/WeaponDamageProperty.cs | 85 ++++- .../Filters/BooleanPropertyFilter.cs | 11 +- .../Properties/Filters/FilterResources.cs | 13 + .../Properties/Filters}/FilterResources.resx | 12 +- .../Properties/Filters/PropertyFilters.cs | 9 + .../Parser/Properties/IPropertyParser.cs | 11 +- .../Parser/Properties/PropertyDefinition.cs | 29 +- .../Parser/Properties/PropertyParser.cs | 123 ++++--- .../Parser/{Patterns => }/RegexExtensions.cs | 2 +- .../Requirements/IRequirementsParser.cs | 8 + .../Parser/Requirements/RequirementsParser.cs | 35 ++ src/Sidekick.Apis.Poe/StartupExtensions.cs | 6 +- .../Trade/Models/ITradeFilter.cs | 4 +- .../Trade/Models/ModifierFilter.cs | 4 +- .../Trade/Models/PropertyFilter.cs | 124 ------- .../Trade/Models/PropertyFilters.cs | 12 - .../Trade/Models/PseudoModifierFilter.cs | 4 +- .../Trade/Models/TradeItem.cs | 2 - .../Requests/Filters/ArmourFilterGroup.cs | 2 +- .../Trade/Requests/Filters/ArmourFilters.cs | 23 +- .../Requests/Filters/EquipmentFilterGroup.cs | 2 +- .../Requests/Filters/EquipmentFilters.cs | 47 ++- .../Trade/Requests/Filters/MapFilterGroup.cs | 2 +- .../Trade/Requests/Filters/MapFilters.cs | 43 ++- .../Trade/Requests/Filters/MiscFilterGroup.cs | 2 +- .../Trade/Requests/Filters/MiscFilters.cs | 57 ++-- .../Filters/RequirementFilterGroup.cs | 2 +- .../Requests/Filters/RequirementFilters.cs | 23 +- .../Requests/Filters/SearchFilterOption.cs | 31 +- .../Trade/Requests/Filters/SearchFilters.cs | 7 +- .../Requests/Filters/SocketFilterGroup.cs | 2 +- .../Requests/Filters/SocketFilterOption.cs | 23 +- .../Trade/Requests/Filters/SocketFilters.cs | 11 +- .../Trade/Requests/Filters/StatFilterGroup.cs | 2 +- .../Trade/Requests/Filters/StatFilterValue.cs | 12 +- .../Trade/Requests/Filters/StatFilters.cs | 13 +- .../Trade/Requests/Filters/StatType.cs | 2 +- .../Requests/Filters/TradeFilterGroup.cs | 2 +- .../Trade/Requests/Filters/TradeFilters.cs | 9 +- .../Trade/Requests/Filters/TypeFilterGroup.cs | 2 +- .../Trade/Requests/Filters/TypeFilters.cs | 21 +- .../Requests/Filters/WeaponFilterGroup.cs | 2 +- .../Trade/Requests/Filters/WeaponFilters.cs | 31 +- .../Trade/TradeFilterService.cs | 81 +---- .../Trade/TradeSearchService.cs | 320 +----------------- .../Forms/FormNumberSmall.razor | 8 +- .../Forms/FormTriStateCheckbox.razor | 13 +- src/Sidekick.Common/Game/Items/Influences.cs | 14 +- src/Sidekick.Common/Game/Items/Item.cs | 3 - .../Game/Items/ItemProperties.cs | 4 +- src/Sidekick.Modules.Maps/MapOverlay.razor | 2 +- .../BooleanPropertyFilterComponent.razor | 23 ++ ...or => DoublePropertyFilterComponent.razor} | 76 ++--- .../Components/Filters/FilterRange.razor | 12 +- .../Components/Filters/FiltersComponent.razor | 50 ++- .../Filters/IntPropertyFilterComponent.razor | 120 +++++++ .../TriStatePropertyFilterComponent.razor | 36 ++ .../Components/Items/ItemComponent.razor | 4 +- .../Localization/TradeResources.fr.resx | 6 + .../Localization/TradeResources.resx | 6 + .../PriceCheckService.cs | 1 + .../PriceCheckNormalizeValueEditor.razor | 1 - .../Poe1/Parser/DivinationCardParsing.cs | 12 +- .../Poe1/Parser/GemParsing.cs | 1 - .../Poe1/Parser/HelmetParsing.cs | 2 +- .../Poe1/Parser/RingParsing.cs | 4 +- .../Poe1/Parser/SanctumParsing.cs | 1 + .../Poe1/Parser/WeaponParsing.cs | 6 +- 101 files changed, 1505 insertions(+), 1099 deletions(-) delete mode 100644 src/Sidekick.Apis.Poe/Localization/FilterResources.cs delete mode 100644 src/Sidekick.Apis.Poe/Parser/Patterns/IParserPatterns.cs delete mode 100644 src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightRavagedProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightedProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/SeparatorProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.cs rename src/Sidekick.Apis.Poe/{Localization => Parser/Properties/Filters}/FilterResources.resx (95%) create mode 100644 src/Sidekick.Apis.Poe/Parser/Properties/Filters/PropertyFilters.cs rename src/Sidekick.Apis.Poe/Parser/{Patterns => }/RegexExtensions.cs (95%) create mode 100644 src/Sidekick.Apis.Poe/Parser/Requirements/IRequirementsParser.cs create mode 100644 src/Sidekick.Apis.Poe/Parser/Requirements/RequirementsParser.cs delete mode 100644 src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs delete mode 100644 src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs create mode 100644 src/Sidekick.Modules.Trade/Components/Filters/BooleanPropertyFilterComponent.razor rename src/Sidekick.Modules.Trade/Components/Filters/{PropertyFilterComponent.razor => DoublePropertyFilterComponent.razor} (65%) create mode 100644 src/Sidekick.Modules.Trade/Components/Filters/IntPropertyFilterComponent.razor create mode 100644 src/Sidekick.Modules.Trade/Components/Filters/TriStatePropertyFilterComponent.razor diff --git a/src/Sidekick.Apis.Poe/ITradeFilterService.cs b/src/Sidekick.Apis.Poe/ITradeFilterService.cs index b2e65f8e..b97f9319 100644 --- a/src/Sidekick.Apis.Poe/ITradeFilterService.cs +++ b/src/Sidekick.Apis.Poe/ITradeFilterService.cs @@ -1,3 +1,4 @@ +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; using Sidekick.Common.Game.Items; diff --git a/src/Sidekick.Apis.Poe/ITradeSearchService.cs b/src/Sidekick.Apis.Poe/ITradeSearchService.cs index 67163f53..f9c157d2 100644 --- a/src/Sidekick.Apis.Poe/ITradeSearchService.cs +++ b/src/Sidekick.Apis.Poe/ITradeSearchService.cs @@ -1,3 +1,4 @@ +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; using Sidekick.Apis.Poe.Trade.Results; using Sidekick.Common.Game; diff --git a/src/Sidekick.Apis.Poe/Localization/FilterResources.cs b/src/Sidekick.Apis.Poe/Localization/FilterResources.cs deleted file mode 100644 index 510142fd..00000000 --- a/src/Sidekick.Apis.Poe/Localization/FilterResources.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.Extensions.Localization; - -namespace Sidekick.Apis.Poe.Localization -{ - public class FilterResources(IStringLocalizer localizer) - { - public string Filters_Damage => localizer["Filters_Damage"]; - public string Filters_Dps => localizer["Filters_Dps"]; - public string Filters_EDps => localizer["Filters_EDps"]; - public string Filters_PDps => localizer["Filters_PDps"]; - public string Filters_ChaosDps => localizer["Filters_ChaosDps"]; - } -} diff --git a/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs b/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs index 2333b07f..0a91d440 100644 --- a/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Headers/HeaderParser.cs @@ -7,7 +7,6 @@ using Sidekick.Apis.Poe.Items; using Sidekick.Apis.Poe.Items.Models; using Sidekick.Apis.Poe.Parser.Headers.Models; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Common.Extensions; using Sidekick.Common.Game; using Sidekick.Common.Game.Items; diff --git a/src/Sidekick.Apis.Poe/Parser/ItemParser.cs b/src/Sidekick.Apis.Poe/Parser/ItemParser.cs index adbd698e..395b0bb7 100644 --- a/src/Sidekick.Apis.Poe/Parser/ItemParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/ItemParser.cs @@ -1,12 +1,11 @@ -using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; using Sidekick.Apis.Poe.Items; using Sidekick.Apis.Poe.Parser.AdditionalInformation; using Sidekick.Apis.Poe.Parser.Headers; using Sidekick.Apis.Poe.Parser.Modifiers; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties; using Sidekick.Apis.Poe.Parser.Pseudo; +using Sidekick.Apis.Poe.Parser.Requirements; using Sidekick.Apis.Poe.Parser.Sockets; using Sidekick.Common.Exceptions; using Sidekick.Common.Game.Items; @@ -18,7 +17,7 @@ public class ItemParser ILogger logger, IModifierParser modifierParser, IPseudoParser pseudoParser, - IParserPatterns patterns, + IRequirementsParser requirementsParser, ClusterJewelParser clusterJewelParser, IApiInvariantItemProvider apiInvariantItemProvider, ISocketParser socketParser, @@ -54,18 +53,15 @@ public Item ParseItem(string itemText) } // Order of parsing is important - ParseRequirements(parsingItem); - - var influences = ParseInfluences(parsingItem); + requirementsParser.Parse(parsingItem); var sockets = socketParser.Parse(parsingItem); var properties = propertyParser.Parse(parsingItem); - var modifierLines = ParseModifiers(parsingItem); + var modifierLines = modifierParser.Parse(parsingItem); propertyParser.ParseAfterModifiers(parsingItem, properties, modifierLines); var pseudoModifiers = pseudoParser.Parse(modifierLines); var item = new Item(invariant: invariant, itemHeader: parsingItem.Header, itemProperties: properties, - influences: influences, sockets: sockets, modifierLines: modifierLines, pseudoModifiers: pseudoModifiers, @@ -84,53 +80,4 @@ public Item ParseItem(string itemText) throw; } } - - private void ParseRequirements(ParsingItem parsingItem) - { - foreach (var block in parsingItem.Blocks.Where(x => !x.Parsed)) - { - if (!block.TryParseRegex(patterns.Requirements, out _)) - { - continue; - } - - block.Parsed = true; - return; - } - } - - private Influences ParseInfluences(ParsingItem parsingItem) - { - return parsingItem.Header?.Category switch - { - Category.Accessory or Category.Armour or Category.Weapon => new Influences() - { - Crusader = GetBool(patterns.Crusader, parsingItem), - Elder = GetBool(patterns.Elder, parsingItem), - Hunter = GetBool(patterns.Hunter, parsingItem), - Redeemer = GetBool(patterns.Redeemer, parsingItem), - Shaper = GetBool(patterns.Shaper, parsingItem), - Warlord = GetBool(patterns.Warlord, parsingItem), - }, - _ => new Influences(), - }; - } - - private List ParseModifiers(ParsingItem parsingItem) - { - return parsingItem.Header?.Category switch - { - Category.DivinationCard or Category.Gem => new(), - _ => modifierParser.Parse(parsingItem), - }; - } - - #region Helpers - - private static bool GetBool(Regex pattern, ParsingItem parsingItem) - { - return parsingItem.TryParseRegex(pattern, out _); - } - - #endregion Helpers } diff --git a/src/Sidekick.Apis.Poe/Parser/Modifiers/ModifierParser.cs b/src/Sidekick.Apis.Poe/Parser/Modifiers/ModifierParser.cs index 7a6f559f..1836d4da 100644 --- a/src/Sidekick.Apis.Poe/Parser/Modifiers/ModifierParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Modifiers/ModifierParser.cs @@ -20,6 +20,11 @@ IFuzzyService fuzzyService /// public List Parse(ParsingItem parsingItem) { + if (parsingItem.Header?.Category is Category.DivinationCard or Category.Gem) + { + return []; + } + var modifierLines = new List(); foreach (var match in MatchModifiers(parsingItem)) diff --git a/src/Sidekick.Apis.Poe/Parser/Patterns/IParserPatterns.cs b/src/Sidekick.Apis.Poe/Parser/Patterns/IParserPatterns.cs deleted file mode 100644 index 6050f996..00000000 --- a/src/Sidekick.Apis.Poe/Parser/Patterns/IParserPatterns.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Text.RegularExpressions; -using Sidekick.Common.Initialization; - -namespace Sidekick.Apis.Poe.Parser.Patterns -{ - public interface IParserPatterns : IInitializableService - { - Regex Crusader { get; } - Regex Elder { get; } - Regex Hunter { get; } - Regex Requirements { get; } - Regex Redeemer { get; } - Regex Shaper { get; } - Regex Warlord { get; } - } -} diff --git a/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs b/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs deleted file mode 100644 index 61276e1e..00000000 --- a/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Text.RegularExpressions; -using Sidekick.Common.Game.Languages; - -namespace Sidekick.Apis.Poe.Parser.Patterns -{ - public class ParserPatterns(IGameLanguageProvider gameLanguageProvider) : IParserPatterns - { - /// - public int Priority => 100; - - /// - public Task Initialize() - { - InitInfluences(); - - Requirements = gameLanguageProvider.Language.DescriptionRequirements.ToRegexLine(); - - return Task.CompletedTask; - } - - #region Header (Rarity, Name, Type) - - public Regex Requirements { get; private set; } = null!; - - #endregion Header (Rarity, Name, Type) - - #region Influences - - private void InitInfluences() - { - Crusader = gameLanguageProvider.Language.InfluenceCrusader.ToRegexLine(); - Elder = gameLanguageProvider.Language.InfluenceElder.ToRegexLine(); - Hunter = gameLanguageProvider.Language.InfluenceHunter.ToRegexLine(); - Redeemer = gameLanguageProvider.Language.InfluenceRedeemer.ToRegexLine(); - Shaper = gameLanguageProvider.Language.InfluenceShaper.ToRegexLine(); - Warlord = gameLanguageProvider.Language.InfluenceWarlord.ToRegexLine(); - } - - public Regex Crusader { get; private set; } = null!; - - public Regex Elder { get; private set; } = null!; - - public Regex Hunter { get; private set; } = null!; - - public Regex Redeemer { get; private set; } = null!; - - public Regex Shaper { get; private set; } = null!; - - public Regex Warlord { get; private set; } = null!; - - #endregion Influences - } -} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs new file mode 100644 index 00000000..f1105fe6 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs @@ -0,0 +1,52 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class AreaLevelProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Sanctum, Category.Logbook]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionAreaLevel.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + if (parsingItem.Header?.Category != Category.Armour && parsingItem.Header?.Category != Category.Accessory && parsingItem.Header?.Category != Category.Map && parsingItem.Header?.Category != Category.Contract) return; + + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.AreaLevel = GetInt(Pattern, propertyBlock); + if (itemProperties.AreaLevel > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.AreaLevel <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionAreaLevel, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.AreaLevel, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMapFilters().Filters.AreaLevel = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs index 0d3386b0..f7de4ed9 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; @@ -41,7 +40,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs new file mode 100644 index 00000000..a23c3cfe --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs @@ -0,0 +1,49 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class AttacksPerSecondProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Weapon]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionAttacksPerSecond.ToRegexDoubleCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.AttacksPerSecond = GetDouble(Pattern, propertyBlock); + if (itemProperties.AttacksPerSecond > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.AttacksPerSecond <= 0) return null; + + var filter = new DoublePropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionAttacksPerSecond, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.AttacksPerSecond, + Checked = false, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not DoublePropertyFilter doubleFilter) return; + + searchFilters.GetOrCreateWeaponFilters().Filters.AttacksPerSecond = doubleFilter.Checked ? new StatFilterValue(doubleFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightRavagedProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightRavagedProperty.cs new file mode 100644 index 00000000..a40e3699 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightRavagedProperty.cs @@ -0,0 +1,45 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class BlightRavagedProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Map]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.AffixBlightRavaged.ToRegexAffix(gameLanguageProvider.Language.AffixSuperior); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.BlightRavaged = Pattern?.IsMatch(parsingItem.Blocks[0].Lines[^1].Text) ?? false; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.BlightRavaged) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + ShowRow = false, + Text = gameLanguageProvider.Language.AffixBlightRavaged, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMapFilters().Filters.BlightRavavaged = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightedProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightedProperty.cs new file mode 100644 index 00000000..ba1d392e --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightedProperty.cs @@ -0,0 +1,45 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class BlightedProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Map]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.AffixBlighted.ToRegexAffix(gameLanguageProvider.Language.AffixSuperior); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Blighted = Pattern?.IsMatch(parsingItem.Blocks[0].Lines[^1].Text) ?? false; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.Blighted) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + ShowRow = false, + Text = gameLanguageProvider.Language.AffixBlighted, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMapFilters().Filters.Blighted = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs index 26da6f5c..cdf449ea 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game; @@ -50,7 +49,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs index f7ec8534..f1b87caf 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; @@ -11,7 +10,7 @@ public class CorruptedProperty(IGameLanguageProvider gameLanguageProvider) : Pro { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Map, Category.Contract, Category.Jewel, Category.Flask]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Map, Category.Contract, Category.Jewel, Category.Flask, Category.Gem]; public override void Initialize() { @@ -28,13 +27,13 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte var filter = new TriStatePropertyFilter(this) { ShowCheckbox = true, - Text = gameLanguageProvider.Language.DescriptionLevel, + Text = gameLanguageProvider.Language.DescriptionCorrupted, Checked = null, }; return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not TriStatePropertyFilter triStateFilter) { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs new file mode 100644 index 00000000..1f0c77e3 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs @@ -0,0 +1,58 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class CriticalHitChanceProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Weapon]; + + public override void Initialize() + { + if (game == GameType.PathOfExile) + { + Pattern = gameLanguageProvider.Language.DescriptionCriticalStrikeChance.ToRegexDoubleCapture(); + } + else + { + Pattern = gameLanguageProvider.Language.DescriptionCriticalHitChance.ToRegexDoubleCapture(); + } + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.CriticalHitChance = GetDouble(Pattern, propertyBlock); + if (itemProperties.CriticalHitChance > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.CriticalHitChance <= 0) return null; + + var text = game == GameType.PathOfExile ? gameLanguageProvider.Language.DescriptionCriticalStrikeChance : gameLanguageProvider.Language.DescriptionCriticalHitChance; + var filter = new DoublePropertyFilter(this) + { + ShowCheckbox = true, + Text = text, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.CriticalHitChance, + Checked = false, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not DoublePropertyFilter doubleFilter) return; + + searchFilters.GetOrCreateWeaponFilters().Filters.CriticalHitChance = doubleFilter.Checked ? new StatFilterValue(doubleFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs new file mode 100644 index 00000000..0d6f9ed1 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class CrusaderProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.InfluenceCrusader.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Influences.Crusader = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.Influences.Crusader) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.InfluenceCrusader, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMiscFilters().Filters.CrusaderItem = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs new file mode 100644 index 00000000..74be147d --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class ElderProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.InfluenceElder.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Influences.Elder = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.Influences.Elder) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.InfluenceElder, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMiscFilters().Filters.ElderItem = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs index debca175..3d32a22a 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; @@ -41,7 +40,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs index 79a3a51d..698b4d7e 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; @@ -41,7 +40,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs index 1b708f1f..83f3d29a 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs @@ -1,6 +1,5 @@ using System.Text.RegularExpressions; using Sidekick.Apis.Poe.Items; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game; @@ -48,7 +47,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs new file mode 100644 index 00000000..10a58ffd --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class HunterProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.InfluenceHunter.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Influences.Hunter = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.Influences.Hunter) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.InfluenceHunter, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMiscFilters().Filters.HunterItem = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs index 93fbce7c..e226b15f 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game; @@ -12,7 +11,7 @@ public class ItemLevelProperty(IGameLanguageProvider gameLanguageProvider, GameT { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Flask, Category.Jewel, Category.Accessory]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Flask, Category.Jewel, Category.Accessory, Category.Map, Category.Contract]; public override void Initialize() { @@ -21,11 +20,7 @@ public override void Initialize() public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) { - if (parsingItem.Header?.Category != Category.Armour && parsingItem.Header?.Category != Category.Accessory && parsingItem.Header?.Category != Category.Map && parsingItem.Header?.Category != Category.Contract) return; - - var propertyBlock = parsingItem.Blocks[1]; - itemProperties.ItemLevel = GetInt(Pattern, propertyBlock); - if (itemProperties.ItemLevel > 0) propertyBlock.Parsed = true; + itemProperties.ItemLevel = GetInt(Pattern, parsingItem); } public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) @@ -44,7 +39,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs new file mode 100644 index 00000000..4bb78a0b --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs @@ -0,0 +1,49 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class ItemQuantityProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Map, Category.Contract]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionItemQuantity.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.ItemQuantity = GetInt(Pattern, propertyBlock); + if (itemProperties.ItemQuantity > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.ItemQuantity <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionItemQuantity, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.ItemQuantity, + Checked = false, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMapFilters().Filters.ItemQuantity = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs new file mode 100644 index 00000000..a479784c --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs @@ -0,0 +1,49 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class ItemRarityProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Map, Category.Contract]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionItemRarity.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.ItemRarity = GetInt(Pattern, propertyBlock); + if (itemProperties.ItemRarity > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.ItemRarity <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionItemRarity, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.ItemRarity, + Checked = false, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMapFilters().Filters.ItemRarity = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs new file mode 100644 index 00000000..0231b9fa --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs @@ -0,0 +1,49 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class MapTierProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Map, Category.Contract]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionMapTier.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.MapTier = GetInt(Pattern, propertyBlock); + if (itemProperties.MapTier > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.MapTier <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionMapTier, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.MapTier, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMapFilters().Filters.MapTier = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs new file mode 100644 index 00000000..d487fb91 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs @@ -0,0 +1,49 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class MonsterPackSizeProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Map, Category.Contract]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionMonsterPackSize.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.MonsterPackSize = GetInt(Pattern, propertyBlock); + if (itemProperties.MonsterPackSize > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.MonsterPackSize <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.DescriptionMonsterPackSize, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.MonsterPackSize, + Checked = false, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMapFilters().Filters.MonsterPackSize = intFilter.Checked ? new StatFilterValue(intFilter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs index 5f83152f..1a739fd1 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; @@ -41,7 +40,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs new file mode 100644 index 00000000..d2d421ea --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class RedeemerProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.InfluenceRedeemer.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Influences.Redeemer = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.Influences.Redeemer) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.InfluenceRedeemer, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMiscFilters().Filters.RedeemerItem = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/SeparatorProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/SeparatorProperty.cs new file mode 100644 index 00000000..cb513453 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/SeparatorProperty.cs @@ -0,0 +1,30 @@ +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class SeparatorProperty() : PropertyDefinition +{ + public const string Text = "---"; + + public override List ValidCategories { get; } = []; + + public override void Initialize() + { + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + return new BooleanPropertyFilter(this) + { + ShowCheckbox = false, + Text = Text, + Checked = true, + }; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs new file mode 100644 index 00000000..8c46aebc --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class ShaperProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.InfluenceShaper.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Influences.Shaper = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.Influences.Shaper) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.InfluenceShaper, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMiscFilters().Filters.ShaperItem = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs index acb54d8b..185a2a3b 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs @@ -1,5 +1,4 @@ using System.Text.RegularExpressions; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; @@ -20,8 +19,6 @@ public override void Initialize() public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) { - if (parsingItem.Header?.Category != Category.Armour) return; - itemProperties.Unidentified = GetBool(Pattern, parsingItem); } @@ -41,7 +38,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte return filter; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs new file mode 100644 index 00000000..6714d993 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; + +public class WarlordProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.InfluenceWarlord.ToRegexLine(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.Influences.Warlord = GetBool(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (!item.Properties.Influences.Warlord) return null; + + var filter = new BooleanPropertyFilter(this) + { + ShowCheckbox = true, + Text = gameLanguageProvider.Language.InfluenceWarlord, + Checked = true, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + searchFilters.GetOrCreateMiscFilters().Filters.WarlordItem = filter.Checked ? new SearchFilterOption(filter) : null; + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs index df04f7b7..e625b049 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs @@ -1,7 +1,7 @@ using System.Globalization; using System.Text.RegularExpressions; +using Microsoft.Extensions.Localization; using Sidekick.Apis.Poe.Modifiers; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Game.Items; @@ -12,7 +12,8 @@ namespace Sidekick.Apis.Poe.Parser.Properties.Definitions; public class WeaponDamageProperty ( IGameLanguageProvider gameLanguageProvider, - IInvariantModifierProvider invariantModifierProvider + IInvariantModifierProvider invariantModifierProvider, + IStringLocalizer localizer ) : PropertyDefinition { private Regex? PhysicalDamagePattern { get; set; } @@ -27,10 +28,6 @@ public override void Initialize() ElementalDamagePattern = gameLanguageProvider.Language.DescriptionElementalDamage.ToRegexStartOfLine(); } - public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) - { - } - public override void ParseAfterModifiers(ItemProperties properties, ParsingItem parsingItem, List modifierLines) { var propertyBlock = parsingItem.Blocks[1]; @@ -124,17 +121,79 @@ private void ParseElementalDamage(ParsingLine line, ItemProperties itemPropertie } } - public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + public override List? GetFilters(Item item, double normalizeValue) { - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_Damage, resources.Filters_Damage, item.Properties.TotalDamage, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_PhysicalDps, resources.Filters_PDps, item.Properties.PhysicalDps, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_ElementalDps, resources.Filters_EDps, item.Properties.ElementalDps, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_ChaosDps, resources.Filters_ChaosDps, item.Properties.ChaosDps, @checked: false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_Dps, resources.Filters_Dps, item.Properties.TotalDps, @checked: false, normalizeValue); + var results = new List(); + + if (item.Properties.TotalDamage > 0) + { + results.Add(new DoublePropertyFilter(this) + { + ShowCheckbox = true, + Text = localizer["Damage"], + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.TotalDamage ?? 0, + Checked = false, + }); + } + + if (item.Properties.PhysicalDps > 0) + { + results.Add(new DoublePropertyFilter(this) + { + ShowCheckbox = true, + Text = localizer["PhysicalDps"], + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.PhysicalDps ?? 0, + Checked = false, + }); + } + + if (item.Properties.ElementalDps > 0) + { + results.Add(new DoublePropertyFilter(this) + { + ShowCheckbox = true, + Text = localizer["ElementalDps"], + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.ElementalDps ?? 0, + Checked = false, + }); + } + + if (item.Properties.ChaosDps > 0) + { + results.Add(new DoublePropertyFilter(this) + { + ShowCheckbox = true, + Text = localizer["Damage"], + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.ChaosDps ?? 0, + Checked = false, + }); + } + + if (item.Properties.TotalDps > 0) + { + results.Add(new DoublePropertyFilter(this) + { + ShowCheckbox = true, + Text = localizer["Dps"], + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.TotalDps ?? 0, + Checked = false, + }); + } + return results.Count > 0 ? results : null; } - internal override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { } } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs index 1988a200..a9bb3a71 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/BooleanPropertyFilter.cs @@ -1,17 +1,14 @@ namespace Sidekick.Apis.Poe.Parser.Properties.Filters; -public class BooleanPropertyFilter +public class BooleanPropertyFilter(PropertyDefinition definition) { - internal BooleanPropertyFilter(PropertyDefinition definition) - { - Definition = definition; - } - public required bool ShowCheckbox { get; init; } + public bool ShowRow { get; init; } = true; + public bool Checked { get; set; } public required string Text { get; init; } - internal PropertyDefinition Definition { get; } + public PropertyDefinition Definition { get; } = definition; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.cs new file mode 100644 index 00000000..5ab68b5b --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.Localization; + +namespace Sidekick.Apis.Poe.Parser.Properties.Filters +{ + public class FilterResources(IStringLocalizer localizer) + { + public string Filters_Damage => localizer["Damage"]; + public string Filters_Dps => localizer["Dps"]; + public string Filters_EDps => localizer["ElementalDps"]; + public string Filters_PDps => localizer["PhysicalDps"]; + public string Filters_ChaosDps => localizer["ChaosDps"]; + } +} diff --git a/src/Sidekick.Apis.Poe/Localization/FilterResources.resx b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.resx similarity index 95% rename from src/Sidekick.Apis.Poe/Localization/FilterResources.resx rename to src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.resx index 24b6be4a..0b0c6c24 100644 --- a/src/Sidekick.Apis.Poe/Localization/FilterResources.resx +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.resx @@ -117,19 +117,19 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Damage per Second - + Elemental DPS - + Physical DPS - + Chaos DPS - + Damage - \ No newline at end of file + diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Filters/PropertyFilters.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/PropertyFilters.cs new file mode 100644 index 00000000..61a598c3 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/PropertyFilters.cs @@ -0,0 +1,9 @@ +namespace Sidekick.Apis.Poe.Parser.Properties.Filters; + +public class PropertyFilters +{ + public bool BaseTypeFilterApplied { get; set; } = true; + public bool ClassFilterApplied { get; set; } + public bool RarityFilterApplied { get; set; } + public List Filters { get; set; } = new(); +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs b/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs index 8268a224..01f6b1c0 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs @@ -1,4 +1,7 @@ -using Sidekick.Common.Game.Items; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Models; +using Sidekick.Apis.Poe.Trade.Requests.Filters; +using Sidekick.Common.Game.Items; using Sidekick.Common.Initialization; namespace Sidekick.Apis.Poe.Parser.Properties; @@ -6,6 +9,10 @@ namespace Sidekick.Apis.Poe.Parser.Properties; public interface IPropertyParser: IInitializableService { ItemProperties Parse(ParsingItem parsingItem); - + void ParseAfterModifiers(ParsingItem parsingItem, ItemProperties properties, List modifierLines); + + Task> GetFilters(Item item); + + void PrepareTradeRequest(SearchFilters searchFilters, Item item, PropertyFilters propertyFilters); } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs index 3cd30089..f771c199 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs @@ -12,13 +12,15 @@ public abstract class PropertyDefinition public abstract void Initialize(); - public abstract void Parse(ItemProperties itemProperties, ParsingItem parsingItem); + public virtual void Parse(ItemProperties itemProperties, ParsingItem parsingItem) {} public virtual void ParseAfterModifiers(ItemProperties itemProperties, ParsingItem parsingItem, List modifierLines) {} - public abstract BooleanPropertyFilter? GetFilter(Item item, double normalizeValue); + public virtual BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) { return null; } - internal abstract void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter); + public virtual List? GetFilters(Item item, double normalizeValue) { return null; } + + public abstract void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter); protected static bool GetBool(Regex? pattern, ParsingItem parsingItem) { @@ -32,12 +34,7 @@ protected static bool GetBool(Regex? pattern, ParsingItem parsingItem) protected static int GetInt(Regex? pattern, ParsingItem parsingItem) { - if (pattern == null) - { - return 0; - } - - if (parsingItem.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) + if (pattern != null && parsingItem.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) { return result; } @@ -47,12 +44,7 @@ protected static int GetInt(Regex? pattern, ParsingItem parsingItem) protected static int GetInt(Regex? pattern, ParsingBlock parsingBlock) { - if (pattern == null) - { - return 0; - } - - if (parsingBlock.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) + if (pattern != null && parsingBlock.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) { return result; } @@ -62,12 +54,7 @@ protected static int GetInt(Regex? pattern, ParsingBlock parsingBlock) protected static double GetDouble(Regex? pattern, ParsingBlock parsingBlock) { - if (pattern == null) - { - return 0; - } - - if (!parsingBlock.TryParseRegex(pattern, out var match)) + if (pattern == null || !parsingBlock.TryParseRegex(pattern, out var match)) { return 0; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs index ec006dd1..aabdf1ac 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs @@ -1,9 +1,11 @@ -using System.Globalization; using System.Text.RegularExpressions; +using Microsoft.Extensions.Localization; using Sidekick.Apis.Poe.Items; using Sidekick.Apis.Poe.Modifiers; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties.Definitions; +using Sidekick.Apis.Poe.Parser.Properties.Filters; +using Sidekick.Apis.Poe.Trade.Models; +using Sidekick.Apis.Poe.Trade.Requests.Filters; using Sidekick.Common.Extensions; using Sidekick.Common.Game.Items; using Sidekick.Common.Game.Languages; @@ -16,7 +18,8 @@ public class PropertyParser IGameLanguageProvider gameLanguageProvider, IInvariantModifierProvider invariantModifierProvider, IApiInvariantItemProvider apiInvariantItemProvider, - ISettingsService settingsService + ISettingsService settingsService, + IStringLocalizer filterLocalizer ) : IPropertyParser { public int Priority => 200; @@ -31,10 +34,6 @@ ISettingsService settingsService private Regex? MonsterPackSize { get; set; } - private Regex? AttacksPerSecond { get; set; } - - private Regex? CriticalStrikeChance { get; set; } - private Regex? Blighted { get; set; } private Regex? BlightRavaged { get; set; } @@ -48,16 +47,38 @@ public async Task Initialize() Definitions.Clear(); Definitions.AddRange([ + new QualityProperty(gameLanguageProvider), + new ArmourProperty(gameLanguageProvider), - new BlockChanceProperty(gameLanguageProvider, game), new EvasionRatingProperty(gameLanguageProvider), new EnergyShieldProperty(gameLanguageProvider), + new BlockChanceProperty(gameLanguageProvider, game), + + new WeaponDamageProperty(gameLanguageProvider, invariantModifierProvider, filterLocalizer), + new AttacksPerSecondProperty(gameLanguageProvider), + new CriticalHitChanceProperty(gameLanguageProvider, game), + + new ItemQuantityProperty(gameLanguageProvider), + new ItemRarityProperty(gameLanguageProvider), + new MonsterPackSizeProperty(gameLanguageProvider), + new BlightedProperty(gameLanguageProvider), + new BlightRavagedProperty(gameLanguageProvider), + new MapTierProperty(gameLanguageProvider), + new AreaLevelProperty(gameLanguageProvider), + + new SeparatorProperty(), + new GemLevelProperty(gameLanguageProvider, game, apiInvariantItemProvider), - new CorruptedProperty(gameLanguageProvider), new ItemLevelProperty(gameLanguageProvider, game), - new QualityProperty(gameLanguageProvider), + new CorruptedProperty(gameLanguageProvider), new UnidentifiedProperty(gameLanguageProvider), - new WeaponDamageProperty(gameLanguageProvider, invariantModifierProvider), + + new ElderProperty(gameLanguageProvider), + new ShaperProperty(gameLanguageProvider), + new CrusaderProperty(gameLanguageProvider), + new HunterProperty(gameLanguageProvider), + new RedeemerProperty(gameLanguageProvider), + new WarlordProperty(gameLanguageProvider), ]); foreach (var definition in Definitions) @@ -65,9 +86,6 @@ public async Task Initialize() definition.Initialize(); } - AttacksPerSecond = gameLanguageProvider.Language.DescriptionAttacksPerSecond.ToRegexDecimalCapture(); - CriticalStrikeChance = gameLanguageProvider.Language.DescriptionCriticalStrikeChance.ToRegexDecimalCapture(); - MapTier = gameLanguageProvider.Language.DescriptionMapTier.ToRegexIntCapture(); AreaLevel = gameLanguageProvider.Language.DescriptionAreaLevel.ToRegexIntCapture(); ItemQuantity = gameLanguageProvider.Language.DescriptionItemQuantity.ToRegexIntCapture(); @@ -82,61 +100,80 @@ public ItemProperties Parse(ParsingItem parsingItem) var properties = new ItemProperties(); foreach (var definition in Definitions) { - if (!definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; + if (definition.ValidCategories.Count > 0 && !definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; definition.Parse(properties, parsingItem); } return properties; - return parsingItem.Header?.Category switch - { - Category.Map or Category.Contract => ParseMapProperties(parsingItem), - Category.Weapon => ParseWeaponProperties(parsingItem, modifierLines), - Category.Sanctum => ParseSanctumProperties(parsingItem), - Category.Logbook => ParseLogbookProperties(parsingItem), - _ => new ItemProperties(), - }; } - public void ParseAfterModifiers(ParsingItem parsingItem, ItemProperties properties, List modifierLines) { foreach (var definition in Definitions) { - if (!definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; + if (definition.ValidCategories.Count > 0 && !definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; definition.ParseAfterModifiers(properties, parsingItem, modifierLines); } } - private ItemProperties ParseMapProperties(ParsingItem parsingItem) + public async Task> GetFilters(Item item) { - var propertyBlock = parsingItem.Blocks[1]; + var normalizeValue = await settingsService.GetObject(SettingKeys.PriceCheckNormalizeValue); + var results = new List(); - return new ItemProperties() + foreach (var definition in Definitions) { - Blighted = Blighted?.IsMatch(parsingItem.Blocks[0].Lines[^1].Text) ?? false, - BlightRavaged = BlightRavaged?.IsMatch(parsingItem.Blocks[0].Lines[^1].Text) ?? false, - ItemQuantity = GetInt(ItemQuantity, propertyBlock), - ItemRarity = GetInt(ItemRarity, propertyBlock), - MonsterPackSize = GetInt(MonsterPackSize, propertyBlock), - MapTier = GetInt(MapTier, propertyBlock), - }; + if (definition.ValidCategories.Count > 0 && !definition.ValidCategories.Contains(item.Header.Category)) continue; + + var filter = definition.GetFilter(item, normalizeValue); + if (filter != null) results.Add(filter); + + var filters = definition.GetFilters(item, normalizeValue); + if (filters != null) results.AddRange(filters); + } + + CleanUpSeparatorFilters(results); + + return results; } - private ItemProperties ParseSanctumProperties(ParsingItem parsingItem) + private void CleanUpSeparatorFilters(List results) { - return new ItemProperties + // Remove leading SeparatorProperty filters + while (results.Count > 0 && results[0].Definition is SeparatorProperty) + { + results.RemoveAt(0); + } + + // Remove trailing SeparatorProperty filters + while (results.Count > 0 && results[^1].Definition is SeparatorProperty) + { + results.RemoveAt(results.Count - 1); + } + + // Remove consecutive SeparatorProperty filters + for (var i = 1; i < results.Count; i++) { - AreaLevel = GetInt(AreaLevel, parsingItem), - }; + if (results[i].Definition is not SeparatorProperty || results[i - 1].Definition is not SeparatorProperty) + { + continue; + } + + results.RemoveAt(i); + i--; // Adjust index to recheck current position + } } - private ItemProperties ParseLogbookProperties(ParsingItem parsingItem) + public void PrepareTradeRequest(SearchFilters searchFilters, Item item, PropertyFilters propertyFilters) { - return new ItemProperties + foreach (var definition in Definitions) { - AreaLevel = GetInt(AreaLevel, parsingItem), - }; + foreach (var filter in propertyFilters.Filters) + { + definition.PrepareTradeRequest(searchFilters, item, filter); + } + } } } diff --git a/src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs b/src/Sidekick.Apis.Poe/Parser/RegexExtensions.cs similarity index 95% rename from src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs rename to src/Sidekick.Apis.Poe/Parser/RegexExtensions.cs index 13254184..3a616492 100644 --- a/src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs +++ b/src/Sidekick.Apis.Poe/Parser/RegexExtensions.cs @@ -1,6 +1,6 @@ using System.Text.RegularExpressions; -namespace Sidekick.Apis.Poe.Parser.Patterns; +namespace Sidekick.Apis.Poe.Parser; public static class RegexExtensions { diff --git a/src/Sidekick.Apis.Poe/Parser/Requirements/IRequirementsParser.cs b/src/Sidekick.Apis.Poe/Parser/Requirements/IRequirementsParser.cs new file mode 100644 index 00000000..a06bc7ba --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Requirements/IRequirementsParser.cs @@ -0,0 +1,8 @@ +using Sidekick.Common.Initialization; + +namespace Sidekick.Apis.Poe.Parser.Requirements; + +public interface IRequirementsParser : IInitializableService +{ + void Parse(ParsingItem parsingItem); +} diff --git a/src/Sidekick.Apis.Poe/Parser/Requirements/RequirementsParser.cs b/src/Sidekick.Apis.Poe/Parser/Requirements/RequirementsParser.cs new file mode 100644 index 00000000..3a0d8160 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Requirements/RequirementsParser.cs @@ -0,0 +1,35 @@ +using System.Text.RegularExpressions; +using Sidekick.Common.Game.Languages; + +namespace Sidekick.Apis.Poe.Parser.Requirements +{ + public class RequirementsParser(IGameLanguageProvider gameLanguageProvider) : IRequirementsParser + { + /// + public int Priority => 100; + + private Regex Pattern { get; set; } = null!; + + /// + public Task Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionRequirements.ToRegexLine(); + + return Task.CompletedTask; + } + + public void Parse(ParsingItem parsingItem) + { + foreach (var block in parsingItem.Blocks.Where(x => !x.Parsed)) + { + if (!block.TryParseRegex(Pattern, out _)) + { + continue; + } + + block.Parsed = true; + return; + } + } + } +} diff --git a/src/Sidekick.Apis.Poe/StartupExtensions.cs b/src/Sidekick.Apis.Poe/StartupExtensions.cs index 8fbc5a5f..ff454238 100644 --- a/src/Sidekick.Apis.Poe/StartupExtensions.cs +++ b/src/Sidekick.Apis.Poe/StartupExtensions.cs @@ -9,15 +9,15 @@ using Sidekick.Apis.Poe.Fuzzy; using Sidekick.Apis.Poe.Items; using Sidekick.Apis.Poe.Leagues; -using Sidekick.Apis.Poe.Localization; using Sidekick.Apis.Poe.Modifiers; using Sidekick.Apis.Poe.Parser; using Sidekick.Apis.Poe.Parser.AdditionalInformation; using Sidekick.Apis.Poe.Parser.Headers; using Sidekick.Apis.Poe.Parser.Modifiers; -using Sidekick.Apis.Poe.Parser.Patterns; using Sidekick.Apis.Poe.Parser.Properties; +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Parser.Pseudo; +using Sidekick.Apis.Poe.Parser.Requirements; using Sidekick.Apis.Poe.Parser.Sockets; using Sidekick.Apis.Poe.Stash; using Sidekick.Apis.Poe.Static; @@ -63,7 +63,7 @@ public static IServiceCollection AddSidekickPoeApi(this IServiceCollection servi services.AddSingleton(); services.AddSingleton(); - services.AddSidekickInitializableService(); + services.AddSidekickInitializableService(); services.AddSidekickInitializableService(); services.AddSidekickInitializableService(); services.AddSidekickInitializableService(); diff --git a/src/Sidekick.Apis.Poe/Trade/Models/ITradeFilter.cs b/src/Sidekick.Apis.Poe/Trade/Models/ITradeFilter.cs index e9775655..68475d0c 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/ITradeFilter.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/ITradeFilter.cs @@ -10,11 +10,11 @@ public interface ITradeFilter /// /// Gets or sets the minimum value for the filter. /// - decimal? Min { get; set; } + double? Min { get; set; } /// /// Gets or sets the maximum value for the filter. /// - decimal? Max { get; set; } + double? Max { get; set; } } } diff --git a/src/Sidekick.Apis.Poe/Trade/Models/ModifierFilter.cs b/src/Sidekick.Apis.Poe/Trade/Models/ModifierFilter.cs index caa3f922..6082aa4b 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/ModifierFilter.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/ModifierFilter.cs @@ -25,9 +25,9 @@ public ModifierFilter(ModifierLine line) public bool HasMoreThanOneCategory => Line.Modifiers.GroupBy(x => x.Category).Count() > 1; - public decimal? Min { get; set; } + public double? Min { get; set; } - public decimal? Max { get; set; } + public double? Max { get; set; } public double NormalizeValue { get; set; } diff --git a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs deleted file mode 100644 index 93f14293..00000000 --- a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs +++ /dev/null @@ -1,124 +0,0 @@ -using Sidekick.Common.Exceptions; - -namespace Sidekick.Apis.Poe.Trade.Models; - -public class PropertyFilter : ITradeFilter -{ - public PropertyFilter( - bool? @checked, - PropertyFilterType type, - string text, - object value, - double? normalizeValue) - { - Checked = @checked; - Type = type; - Text = text; - Value = value; - NormalizeEnabled = normalizeValue != null; - NormalizeValue = normalizeValue ?? 0; - - if (@checked == true) - { - NormalizeMinValue(); - } - } - - public PropertyFilterType Type { get; } - - public bool? Checked { get; set; } - - public decimal? Min { get; set; } - - public decimal? Max { get; set; } - - public string Text { get; } - - public object Value { get; } - - private bool NormalizeEnabled { get; } - - public double NormalizeValue { get; set; } - - public string ValueString - { - get - { - return Value switch - { - bool b => b ? "true" : "false", - int i => i.ToString(), - double d => d.ToString("0.##"), - _ => Value?.ToString() ?? string.Empty - }; - } - } - - public FilterValueType ValueType - { - get - { - switch (Value) - { - case bool: return FilterValueType.Boolean; - case int: return FilterValueType.Int; - case double: return FilterValueType.Double; - default : throw new SidekickException("[PropertyFilter] Unknown value type: " + Value.GetType().Name); - } - } - } - - /// - /// Normalize the Min value with NormalizeValue. - /// - public void NormalizeMinValue() - { - if (!decimal.TryParse(Value.ToString(), out var value) || value == 0) - { - return; - } - - if (value > 0) - { - Min = Math.Max((1 - (decimal)NormalizeValue) * value, 0); - } - else - { - Min = Math.Min((1 + (decimal)NormalizeValue) * value, 0); - } - } - - /// - /// Normalize the Max value, +1 and/or NormalizeValue. - /// - public void NormalizeMaxValue() - { - if (!decimal.TryParse(Value.ToString(), out var value) || value == 0) - { - return; - } - - if (value > 0) - { - Max = Math.Max(Math.Max(value + 1, (1 + (decimal)NormalizeValue) * value), 0); - } - else - { - Max = Math.Min(Math.Max(value + 1, (1 - (decimal)NormalizeValue) * value), 0); - } - } - - /// - /// Sets the filter to be the exact value. - /// - public void SetExactValue() - { - if (!decimal.TryParse(Value.ToString(), out var value)) - { - return; - } - - Min = value; - Max = value; - } -} diff --git a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs deleted file mode 100644 index 5abc368c..00000000 --- a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Sidekick.Apis.Poe.Parser.Properties.Filters; - -namespace Sidekick.Apis.Poe.Trade.Models -{ - public class PropertyFilters - { - public bool BaseTypeFilterApplied { get; set; } = true; - public bool ClassFilterApplied { get; set; } - public bool RarityFilterApplied { get; set; } - public List Filters { get; set; } = new(); - } -} diff --git a/src/Sidekick.Apis.Poe/Trade/Models/PseudoModifierFilter.cs b/src/Sidekick.Apis.Poe/Trade/Models/PseudoModifierFilter.cs index df384a4e..c5ffa377 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/PseudoModifierFilter.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/PseudoModifierFilter.cs @@ -8,9 +8,9 @@ public class PseudoModifierFilter : ITradeFilter public bool? @Checked { get; set; } = false; - public decimal? Min { get; set; } + public double? Min { get; set; } - public decimal? Max { get; set; } + public double? Max { get; set; } public double NormalizeValue { get; set; } diff --git a/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs b/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs index 729e56ba..4718c894 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs @@ -6,7 +6,6 @@ public class TradeItem ( ItemHeader itemHeader, ItemProperties itemProperties, - Influences influences, List sockets, List modifierLines, List pseudoModifiers, @@ -14,7 +13,6 @@ string text ) : Item(null, itemHeader, itemProperties, - influences, sockets, modifierLines, pseudoModifiers, diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilterGroup.cs index aee0d4c3..01b1c30e 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class ArmourFilterGroup +public class ArmourFilterGroup { public ArmourFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs index 69264de6..510f2485 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/ArmourFilters.cs @@ -1,19 +1,18 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class ArmourFilters { - internal class ArmourFilters - { - [JsonPropertyName("ar")] - public StatFilterValue? Armour { get; set; } + [JsonPropertyName("ar")] + public StatFilterValue? Armour { get; set; } - [JsonPropertyName("es")] - public StatFilterValue? EnergyShield { get; set; } + [JsonPropertyName("es")] + public StatFilterValue? EnergyShield { get; set; } - [JsonPropertyName("ev")] - public StatFilterValue? EvasionRating { get; set; } + [JsonPropertyName("ev")] + public StatFilterValue? EvasionRating { get; set; } - [JsonPropertyName("block")] - public StatFilterValue? BlockChance { get; set; } - } + [JsonPropertyName("block")] + public StatFilterValue? BlockChance { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilterGroup.cs index a6205c0c..ab73a710 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class EquipmentFilterGroup +public class EquipmentFilterGroup { public EquipmentFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilters.cs index 73e4d53f..d10ffebd 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/EquipmentFilters.cs @@ -1,37 +1,36 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class EquipmentFilters { - internal class EquipmentFilters - { - [JsonPropertyName("ar")] - public StatFilterValue? Armor { get; set; } + [JsonPropertyName("ar")] + public StatFilterValue? Armor { get; set; } - [JsonPropertyName("es")] - public StatFilterValue? EnergyShield { get; set; } + [JsonPropertyName("es")] + public StatFilterValue? EnergyShield { get; set; } - [JsonPropertyName("ev")] - public StatFilterValue? Evasion { get; set; } + [JsonPropertyName("ev")] + public StatFilterValue? Evasion { get; set; } - [JsonPropertyName("block")] - public StatFilterValue? Block { get; set; } + [JsonPropertyName("block")] + public StatFilterValue? Block { get; set; } - [JsonPropertyName("crit")] - public StatFilterValue? CriticalStrikeChance { get; set; } + [JsonPropertyName("crit")] + public StatFilterValue? CriticalStrikeChance { get; set; } - [JsonPropertyName("aps")] - public StatFilterValue? AttacksPerSecond { get; set; } + [JsonPropertyName("aps")] + public StatFilterValue? AttacksPerSecond { get; set; } - [JsonPropertyName("dps")] - public StatFilterValue? DamagePerSecond { get; set; } + [JsonPropertyName("dps")] + public StatFilterValue? DamagePerSecond { get; set; } - [JsonPropertyName("edps")] - public StatFilterValue? ElementalDps { get; set; } + [JsonPropertyName("edps")] + public StatFilterValue? ElementalDps { get; set; } - [JsonPropertyName("pdps")] - public StatFilterValue? PhysicalDps { get; set; } + [JsonPropertyName("pdps")] + public StatFilterValue? PhysicalDps { get; set; } - [JsonPropertyName("damage")] - public StatFilterValue? Damage { get; set; } - } + [JsonPropertyName("damage")] + public StatFilterValue? Damage { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilterGroup.cs index ce743c27..98cb715d 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class MapFilterGroup +public class MapFilterGroup { public MapFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilters.cs index 17b82143..dad85df3 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilters.cs @@ -1,34 +1,33 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class MapFilters { - internal class MapFilters - { - [JsonPropertyName("map_iiq")] - public StatFilterValue? ItemQuantity { get; set; } + [JsonPropertyName("map_iiq")] + public StatFilterValue? ItemQuantity { get; set; } - [JsonPropertyName("map_iir")] - public StatFilterValue? ItemRarity { get; set; } + [JsonPropertyName("map_iir")] + public StatFilterValue? ItemRarity { get; set; } - [JsonPropertyName("area_level")] - public StatFilterValue? AreaLevel { get; set; } + [JsonPropertyName("area_level")] + public StatFilterValue? AreaLevel { get; set; } - [JsonPropertyName("map_tier")] - public StatFilterValue? MapTier { get; set; } + [JsonPropertyName("map_tier")] + public StatFilterValue? MapTier { get; set; } - [JsonPropertyName("map_packsize")] - public StatFilterValue? MonsterPackSize { get; set; } + [JsonPropertyName("map_packsize")] + public StatFilterValue? MonsterPackSize { get; set; } - [JsonPropertyName("map_blighted")] - public SearchFilterOption? Blighted { get; set; } + [JsonPropertyName("map_blighted")] + public SearchFilterOption? Blighted { get; set; } - [JsonPropertyName("map_uberblighted")] - public SearchFilterOption? BlightRavavaged { get; set; } + [JsonPropertyName("map_uberblighted")] + public SearchFilterOption? BlightRavavaged { get; set; } - [JsonPropertyName("map_elder")] - public SearchFilterOption? Elder { get; set; } + [JsonPropertyName("map_elder")] + public SearchFilterOption? Elder { get; set; } - [JsonPropertyName("map_shaped")] - public SearchFilterOption? Shaped { get; set; } - } + [JsonPropertyName("map_shaped")] + public SearchFilterOption? Shaped { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilterGroup.cs index da1a26fa..da70d183 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class MiscFilterGroup +public class MiscFilterGroup { public MiscFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilters.cs index bc243bd3..d0a6dfe0 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MiscFilters.cs @@ -1,44 +1,43 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class MiscFilters { - internal class MiscFilters - { - public StatFilterValue? Quality { get; set; } + public StatFilterValue? Quality { get; set; } - [JsonPropertyName("gem_level")] - public StatFilterValue? GemLevel { get; set; } + [JsonPropertyName("gem_level")] + public StatFilterValue? GemLevel { get; set; } - [JsonPropertyName("gem_alternate_quality")] - public SearchFilterOption? GemQualityType { get; set; } + [JsonPropertyName("gem_alternate_quality")] + public SearchFilterOption? GemQualityType { get; set; } - /// - /// The item level filter for Path of Exile 1 is inside the misc filters instead of the type filters. - /// - [JsonPropertyName("ilvl")] - public StatFilterValue? ItemLevel { get; set; } + /// + /// The item level filter for Path of Exile 1 is inside the misc filters instead of the type filters. + /// + [JsonPropertyName("ilvl")] + public StatFilterValue? ItemLevel { get; set; } - public SearchFilterOption? Corrupted { get; set; } + public SearchFilterOption? Corrupted { get; set; } - [JsonPropertyName("scourge_tier")] - public StatFilterValue? Scourged { get; set; } + [JsonPropertyName("scourge_tier")] + public StatFilterValue? Scourged { get; set; } - [JsonPropertyName("elder_item")] - public SearchFilterOption? ElderItem { get; set; } + [JsonPropertyName("elder_item")] + public SearchFilterOption? ElderItem { get; set; } - [JsonPropertyName("hunter_item")] - public SearchFilterOption? HunterItem { get; set; } + [JsonPropertyName("hunter_item")] + public SearchFilterOption? HunterItem { get; set; } - [JsonPropertyName("shaper_item")] - public SearchFilterOption? ShaperItem { get; set; } + [JsonPropertyName("shaper_item")] + public SearchFilterOption? ShaperItem { get; set; } - [JsonPropertyName("warlord_item")] - public SearchFilterOption? WarlordItem { get; set; } + [JsonPropertyName("warlord_item")] + public SearchFilterOption? WarlordItem { get; set; } - [JsonPropertyName("crusader_item")] - public SearchFilterOption? CrusaderItem { get; set; } + [JsonPropertyName("crusader_item")] + public SearchFilterOption? CrusaderItem { get; set; } - [JsonPropertyName("redeemer_item")] - public SearchFilterOption? RedeemerItem { get; set; } - } + [JsonPropertyName("redeemer_item")] + public SearchFilterOption? RedeemerItem { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilterGroup.cs index b639207d..5cef2c34 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class RequirementFilterGroup +public class RequirementFilterGroup { public RequirementFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilters.cs index aa2c6561..ea3e8497 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/RequirementFilters.cs @@ -1,19 +1,18 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class RequirementFilters { - internal class RequirementFilters - { - [JsonPropertyName("lvl")] - public StatFilterValue? Level { get; set; } + [JsonPropertyName("lvl")] + public StatFilterValue? Level { get; set; } - [JsonPropertyName("dex")] - public StatFilterValue? Dexterity { get; set; } + [JsonPropertyName("dex")] + public StatFilterValue? Dexterity { get; set; } - [JsonPropertyName("str")] - public StatFilterValue? Strength { get; set; } + [JsonPropertyName("str")] + public StatFilterValue? Strength { get; set; } - [JsonPropertyName("int")] - public StatFilterValue? Intelligence { get; set; } - } + [JsonPropertyName("int")] + public StatFilterValue? Intelligence { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs index 7f36fb4f..419a95f1 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs @@ -1,25 +1,24 @@ using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class SearchFilterOption { - internal class SearchFilterOption + public SearchFilterOption(string option) { - public SearchFilterOption(string option) - { - Option = option; - } - - public SearchFilterOption(PropertyFilter filter) - { - Option = filter.Checked == true ? "true" : "false"; - } + Option = option; + } - public SearchFilterOption(TriStatePropertyFilter filter) - { - Option = filter.Checked == true ? "true" : "false"; - } + public SearchFilterOption(BooleanPropertyFilter filter) + { + Option = filter.Checked ? "true" : "false"; + } - public string Option { get; set; } + public SearchFilterOption(TriStatePropertyFilter filter) + { + Option = filter.Checked == true ? "true" : "false"; } + + public string Option { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs index 56f3fc54..993e1dc6 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs @@ -2,7 +2,7 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class SearchFilters +public class SearchFilters { [JsonPropertyName("type_filters")] public TypeFilterGroup TypeFilters { get; set; } = new(); @@ -18,6 +18,8 @@ internal class SearchFilters [JsonPropertyName("weapon_filters")] public WeaponFilterGroup? WeaponFilters { get; set; } + public WeaponFilterGroup GetOrCreateWeaponFilters() => WeaponFilters ??= new(); + [JsonPropertyName("armour_filters")] public ArmourFilterGroup? ArmourFilters { get; set; } @@ -34,4 +36,7 @@ internal class SearchFilters [JsonPropertyName("map_filters")] public MapFilterGroup? MapFilters { get; set; } + + public MapFilterGroup GetOrCreateMapFilters() => MapFilters ??= new(); + } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterGroup.cs index 8da7e826..9c453c0f 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class SocketFilterGroup +public class SocketFilterGroup { public SocketFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterOption.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterOption.cs index 5a93ef5a..e9b0e0a3 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterOption.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterOption.cs @@ -1,19 +1,18 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class SocketFilterOption : StatFilterValue { - internal class SocketFilterOption : StatFilterValue - { - [JsonPropertyName("r")] - public int? Red { get; set; } + [JsonPropertyName("r")] + public int? Red { get; set; } - [JsonPropertyName("g")] - public int? Green { get; set; } + [JsonPropertyName("g")] + public int? Green { get; set; } - [JsonPropertyName("b")] - public int? Blue { get; set; } + [JsonPropertyName("b")] + public int? Blue { get; set; } - [JsonPropertyName("w")] - public int? White { get; set; } - } + [JsonPropertyName("w")] + public int? White { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilters.cs index 54f2042d..27a81b57 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilters.cs @@ -1,8 +1,7 @@ -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class SocketFilters { - internal class SocketFilters - { - public SocketFilterOption? Sockets { get; set; } - public SocketFilterOption? Links { get; set; } - } + public SocketFilterOption? Sockets { get; set; } + public SocketFilterOption? Links { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterGroup.cs index 5c147805..b70c5f3e 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterGroup.cs @@ -3,7 +3,7 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class StatFilterGroup +public class StatFilterGroup { [JsonIgnore] public StatType Type { get; set; } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs index 184575bc..de48fa07 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs @@ -3,7 +3,7 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class StatFilterValue +public class StatFilterValue { internal StatFilterValue() { @@ -14,14 +14,14 @@ public StatFilterValue(string? option) Option = option; } - public StatFilterValue(PropertyFilter filter) + public StatFilterValue(IntPropertyFilter filter) { - Option = filter.Checked == true ? "true" : "false"; + Option = filter.Checked ? "true" : "false"; Min = filter.Min; Max = filter.Max; } - public StatFilterValue(IntPropertyFilter filter) + public StatFilterValue(DoublePropertyFilter filter) { Option = filter.Checked ? "true" : "false"; Min = filter.Min; @@ -37,9 +37,9 @@ public StatFilterValue(ModifierFilter filter) public object? Option { get; set; } - public decimal? Min { get; set; } + public double? Min { get; set; } - public decimal? Max { get; set; } + public double? Max { get; set; } public double? Weight { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilters.cs index ca05d76c..d5b75010 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilters.cs @@ -1,9 +1,8 @@ -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class StatFilters { - internal class StatFilters - { - public string? Id { get; set; } - public StatFilterValue? Value { get; set; } - public bool Disabled => false; - } + public string? Id { get; set; } + public StatFilterValue? Value { get; set; } + public bool Disabled => false; } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatType.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatType.cs index e1dce545..2c9365f0 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatType.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatType.cs @@ -2,7 +2,7 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal enum StatType +public enum StatType { [EnumValue("and")] And, diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilterGroup.cs index b5d42758..f8bc4161 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class TradeFilterGroup +public class TradeFilterGroup { public TradeFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilters.cs index cf4f1ce9..b522eeaa 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TradeFilters.cs @@ -1,7 +1,6 @@ -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class TradeFilters { - internal class TradeFilters - { - public StatFilterValue? Price { get; set; } - } + public StatFilterValue? Price { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilterGroup.cs index 97de7280..7a676879 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class TypeFilterGroup +public class TypeFilterGroup { public TypeFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilters.cs index 5711cc0f..093d27a4 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/TypeFilters.cs @@ -1,17 +1,16 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class TypeFilters { - internal class TypeFilters - { - public SearchFilterOption? Category { get; set; } + public SearchFilterOption? Category { get; set; } - public SearchFilterOption? Rarity { get; set; } + public SearchFilterOption? Rarity { get; set; } - /// - /// The item level filter for Path of Exile 2 is inside the type filters instead of the misc filters. - /// - [JsonPropertyName("ilvl")] - public StatFilterValue? ItemLevel { get; set; } - } + /// + /// The item level filter for Path of Exile 2 is inside the type filters instead of the misc filters. + /// + [JsonPropertyName("ilvl")] + public StatFilterValue? ItemLevel { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilterGroup.cs index b757c6ba..8315b244 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilterGroup.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilterGroup.cs @@ -1,6 +1,6 @@ namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class WeaponFilterGroup +public class WeaponFilterGroup { public WeaponFilters Filters { get; set; } = new(); } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilters.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilters.cs index 19c6db45..a0b5cc9f 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/WeaponFilters.cs @@ -1,25 +1,24 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public class WeaponFilters { - internal class WeaponFilters - { - [JsonPropertyName("crit")] - public StatFilterValue? CriticalStrikeChance { get; set; } + [JsonPropertyName("crit")] + public StatFilterValue? CriticalHitChance { get; set; } - [JsonPropertyName("aps")] - public StatFilterValue? AttacksPerSecond { get; set; } + [JsonPropertyName("aps")] + public StatFilterValue? AttacksPerSecond { get; set; } - [JsonPropertyName("dps")] - public StatFilterValue? DamagePerSecond { get; set; } + [JsonPropertyName("dps")] + public StatFilterValue? DamagePerSecond { get; set; } - [JsonPropertyName("edps")] - public StatFilterValue? ElementalDps { get; set; } + [JsonPropertyName("edps")] + public StatFilterValue? ElementalDps { get; set; } - [JsonPropertyName("pdps")] - public StatFilterValue? PhysicalDps { get; set; } + [JsonPropertyName("pdps")] + public StatFilterValue? PhysicalDps { get; set; } - [JsonPropertyName("damage")] - public StatFilterValue? Damage { get; set; } - } + [JsonPropertyName("damage")] + public StatFilterValue? Damage { get; set; } } diff --git a/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs b/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs index c27e3c79..79192bfd 100644 --- a/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs +++ b/src/Sidekick.Apis.Poe/Trade/TradeFilterService.cs @@ -1,16 +1,13 @@ -using Sidekick.Apis.Poe.Localization; +using Sidekick.Apis.Poe.Parser.Properties; +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; using Sidekick.Common.Game.Items; -using Sidekick.Common.Game.Languages; -using Sidekick.Common.Settings; namespace Sidekick.Apis.Poe.Trade { public class TradeFilterService ( - IGameLanguageProvider gameLanguageProvider, - ISettingsService settingsService, - FilterResources resources + IPropertyParser propertyParser ) : ITradeFilterService { public IEnumerable GetModifierFilters(Item item) @@ -47,75 +44,11 @@ public IEnumerable GetPseudoModifierFilters(Item item) public async Task GetPropertyFilters(Item item) { - // No filters for currencies and divination cards, etc. - if (item.Header.Category == Category.DivinationCard || item.Header.Category == Category.Currency || item.Header.Category == Category.ItemisedMonster || item.Header.Category == Category.Leaguestone || item.Header.Category == Category.Unknown) + var filters = await propertyParser.GetFilters(item); + return new PropertyFilters() { - return new(); - } - - var normalizeValue = await settingsService.GetObject(SettingKeys.PriceCheckNormalizeValue); - var result = new PropertyFilters(); - - // Weapon properties - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_AttacksPerSecond, gameLanguageProvider.Language.DescriptionAttacksPerSecond, item.Properties.AttacksPerSecond, false, normalizeValue); - InitializeNumericFilter(result.Weapon, PropertyFilterType.Weapon_CriticalStrikeChance, gameLanguageProvider.Language.DescriptionCriticalStrikeChance, item.Properties.CriticalStrikeChance, false, normalizeValue); - - // Map properties - InitializeNumericFilter(result.Map, PropertyFilterType.Map_ItemQuantity, gameLanguageProvider.Language.DescriptionItemQuantity, item.Properties.ItemQuantity, false, normalizeValue); - InitializeNumericFilter(result.Map, PropertyFilterType.Map_ItemRarity, gameLanguageProvider.Language.DescriptionItemRarity, item.Properties.ItemRarity, false, normalizeValue); - InitializeNumericFilter(result.Map, PropertyFilterType.Map_MonsterPackSize, gameLanguageProvider.Language.DescriptionMonsterPackSize, item.Properties.MonsterPackSize, false, normalizeValue); - InitializeBooleanFilter(result.Map, PropertyFilterType.Map_Blighted, gameLanguageProvider.Language.AffixBlighted, item.Properties.Blighted); - InitializeBooleanFilter(result.Map, PropertyFilterType.Map_BlightRavaged, gameLanguageProvider.Language.AffixBlightRavaged, item.Properties.BlightRavaged); - InitializeNumericFilter(result.Map, PropertyFilterType.Map_Tier, gameLanguageProvider.Language.DescriptionMapTier, item.Properties.MapTier, @checked: true, null); - InitializeNumericFilter(result.Map, PropertyFilterType.Map_AreaLevel, gameLanguageProvider.Language.DescriptionAreaLevel, item.Properties.AreaLevel, @checked: true, null); - - // Misc properties - InitializeNumericFilter(result.Misc, PropertyFilterType.Misc_Quality, gameLanguageProvider.Language.DescriptionQuality, item.Properties.Quality, @checked: item.Header.Rarity == Rarity.Gem, null); - InitializeNumericFilter(result.Misc, PropertyFilterType.Misc_GemLevel, gameLanguageProvider.Language.DescriptionLevel, item.Properties.GemLevel, @checked: true, null); - InitializeNumericFilter(result.Misc, PropertyFilterType.Misc_ItemLevel, gameLanguageProvider.Language.DescriptionItemLevel, item.Properties.ItemLevel, @checked: item.Properties.ItemLevel >= 80 && item.Properties.MapTier == 0 && item.Header.Rarity != Rarity.Unique, null); - InitializeBooleanFilter(result.Misc, PropertyFilterType.Misc_Corrupted, gameLanguageProvider.Language.DescriptionCorrupted, item.Properties.Corrupted, true); - - // Influence properties - InitializeBooleanFilter(result.Misc, PropertyFilterType.Misc_Influence_Crusader, gameLanguageProvider.Language.InfluenceCrusader, item.Influences.Crusader); - InitializeBooleanFilter(result.Misc, PropertyFilterType.Misc_Influence_Elder, gameLanguageProvider.Language.InfluenceElder, item.Influences.Elder); - InitializeBooleanFilter(result.Misc, PropertyFilterType.Misc_Influence_Hunter, gameLanguageProvider.Language.InfluenceHunter, item.Influences.Hunter); - InitializeBooleanFilter(result.Misc, PropertyFilterType.Misc_Influence_Redeemer, gameLanguageProvider.Language.InfluenceRedeemer, item.Influences.Redeemer); - InitializeBooleanFilter(result.Misc, PropertyFilterType.Misc_Influence_Shaper, gameLanguageProvider.Language.InfluenceShaper, item.Influences.Shaper); - InitializeBooleanFilter(result.Misc, PropertyFilterType.Misc_Influence_Warlord, gameLanguageProvider.Language.InfluenceWarlord, item.Influences.Warlord); - - return result; - } - - private void InitializePropertyFilter( - List filters, - PropertyFilterType type, - string? label, - object value, - bool? @checked, - double? normalizeValue) - { - if (string.IsNullOrEmpty(label)) - { - return; - } - - filters.Add(new PropertyFilter(@checked, type, label, value, normalizeValue)); - } - - private void InitializeNumericFilter(List filters, PropertyFilterType type, string? label, double? value, bool @checked, double? normalizeValue) - { - if (value > 0) - { - InitializePropertyFilter(filters, type, label, value.Value, @checked: @checked, normalizeValue); - } - } - - private void InitializeBooleanFilter(List filters, PropertyFilterType type, string? label, bool @checked, bool force = false) - { - if (force || @checked) - { - InitializePropertyFilter(filters, type, label, @checked || force, @checked: @checked, 0); - } + Filters = filters, + }; } } } diff --git a/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs b/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs index 293d1723..01bc26c4 100644 --- a/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs +++ b/src/Sidekick.Apis.Poe/Trade/TradeSearchService.cs @@ -5,8 +5,9 @@ using Sidekick.Apis.Poe.Clients; using Sidekick.Apis.Poe.Clients.Models; using Sidekick.Apis.Poe.Filters; -using Sidekick.Apis.Poe.Items; using Sidekick.Apis.Poe.Modifiers; +using Sidekick.Apis.Poe.Parser.Properties; +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; using Sidekick.Apis.Poe.Trade.Requests; using Sidekick.Apis.Poe.Trade.Requests.Filters; @@ -29,7 +30,7 @@ public class TradeSearchService IPoeTradeClient poeTradeClient, IModifierProvider modifierProvider, IFilterProvider filterProvider, - IApiInvariantItemProvider apiInvariantItemProvider + IPropertyParser propertyParser ) : ITradeSearchService { private readonly ILogger logger = logger; @@ -119,11 +120,7 @@ public async Task> Search(Item item, PropertyFilters? if (propertyFilters != null) { - query.Filters.EquipmentFilters = GetEquipmentFilters(item, propertyFilters.Weapon.Concat(propertyFilters.Armour).ToList()); - query.Filters.WeaponFilters = GetWeaponFilters(item, propertyFilters.Weapon); - query.Filters.ArmourFilters = GetArmourFilters(item, propertyFilters.Armour); - query.Filters.MapFilters = GetMapFilters(propertyFilters.Map); - query.Filters.MiscFilters = GetMiscFilters(item, propertyFilters.Misc); + propertyParser.PrepareTradeRequest(query.Filters, item, propertyFilters); } // The item level filter for Path of Exile 2 is inside the type filters instead of the misc filters. @@ -177,311 +174,6 @@ public async Task> Search(Item item, PropertyFilters? return new SearchFilterOption(itemCategory); } - private WeaponFilterGroup? GetWeaponFilters(Item item, List propertyFilters) - { - if (item.Header.Game == GameType.PathOfExile2) - { - return null; - } - - var filters = new WeaponFilterGroup(); - var hasValue = false; - - foreach (var propertyFilter in propertyFilters) - { - if (propertyFilter.Checked != true) - { - continue; - } - - switch (propertyFilter.Type) - { - case PropertyFilterType.Weapon_Damage: - filters.Filters.Damage = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_PhysicalDps: - filters.Filters.PhysicalDps = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_ElementalDps: - filters.Filters.ElementalDps = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_Dps: - filters.Filters.DamagePerSecond = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_AttacksPerSecond: - filters.Filters.AttacksPerSecond = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_CriticalStrikeChance: - filters.Filters.CriticalStrikeChance = new StatFilterValue(propertyFilter); - hasValue = true; - break; - } - } - - return hasValue ? filters : null; - } - - private ArmourFilterGroup? GetArmourFilters(Item item, List propertyFilters) - { - if (item.Header.Game == GameType.PathOfExile2) - { - return null; - } - - var filters = new ArmourFilterGroup(); - var hasValue = false; - - foreach (var propertyFilter in propertyFilters) - { - if (propertyFilter.Checked != true) - { - continue; - } - - switch (propertyFilter.Type) - { - case PropertyFilterType.Armour_Armour: - filters.Filters.Armour = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Armour_Block: - filters.Filters.BlockChance = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Armour_EnergyShield: - filters.Filters.EnergyShield = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Armour_Evasion: - filters.Filters.EvasionRating = new StatFilterValue(propertyFilter); - hasValue = true; - break; - } - } - - return hasValue ? filters : null; - } - - private EquipmentFilterGroup? GetEquipmentFilters(Item item, List propertyFilters) - { - if (item.Header.Game == GameType.PathOfExile) - { - return null; - } - - var filters = new EquipmentFilterGroup(); - var hasValue = false; - - foreach (var propertyFilter in propertyFilters) - { - if (propertyFilter.Checked != true) - { - continue; - } - - switch (propertyFilter.Type) - { - case PropertyFilterType.Weapon_Damage: - filters.Filters.Damage = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_PhysicalDps: - filters.Filters.PhysicalDps = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_ElementalDps: - filters.Filters.ElementalDps = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_Dps: - filters.Filters.DamagePerSecond = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_AttacksPerSecond: - filters.Filters.AttacksPerSecond = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Weapon_CriticalStrikeChance: - filters.Filters.CriticalStrikeChance = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Armour_Armour: - filters.Filters.Armor = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Armour_Block: - filters.Filters.Block = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Armour_EnergyShield: - filters.Filters.EnergyShield = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Armour_Evasion: - filters.Filters.Evasion = new StatFilterValue(propertyFilter); - hasValue = true; - break; - } - } - - return hasValue ? filters : null; - } - - private MapFilterGroup? GetMapFilters(List propertyFilters) - { - var filters = new MapFilterGroup(); - var hasValue = false; - - foreach (var propertyFilter in propertyFilters) - { - if (propertyFilter.Checked != true) - { - continue; - } - - switch (propertyFilter.Type) - { - case PropertyFilterType.Map_ItemQuantity: - filters.Filters.ItemQuantity = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Map_ItemRarity: - filters.Filters.ItemRarity = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Map_AreaLevel: - filters.Filters.AreaLevel = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Map_MonsterPackSize: - filters.Filters.MonsterPackSize = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Map_Blighted: - filters.Filters.Blighted = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Map_BlightRavaged: - filters.Filters.BlightRavavaged = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Map_Tier: - filters.Filters.MapTier = new StatFilterValue(propertyFilter); - hasValue = true; - break; - } - } - - return hasValue ? filters : null; - } - - private MiscFilterGroup? GetMiscFilters(Item item, List propertyFilters) - { - var filters = new MiscFilterGroup(); - var hasValue = false; - - foreach (var propertyFilter in propertyFilters) - { - if (propertyFilter.Checked != true) - { - continue; - } - - switch (propertyFilter.Type) - { - // Influence - case PropertyFilterType.Misc_Influence_Crusader: - filters.Filters.CrusaderItem = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Misc_Influence_Elder: - filters.Filters.ElderItem = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Misc_Influence_Hunter: - filters.Filters.HunterItem = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Misc_Influence_Redeemer: - filters.Filters.RedeemerItem = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Misc_Influence_Shaper: - filters.Filters.ShaperItem = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Misc_Influence_Warlord: - filters.Filters.WarlordItem = new SearchFilterOption(propertyFilter); - hasValue = true; - break; - - // Misc - case PropertyFilterType.Misc_Quality: - filters.Filters.Quality = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Misc_GemLevel: - if (apiInvariantItemProvider.UncutGemIds.Contains(item.Header.ApiItemId)) - { - filters.Filters.ItemLevel = new StatFilterValue(propertyFilter); - } - else - { - filters.Filters.GemLevel = new StatFilterValue(propertyFilter); - } - - hasValue = true; - break; - - case PropertyFilterType.Misc_ItemLevel: - filters.Filters.ItemLevel = new StatFilterValue(propertyFilter); - hasValue = true; - break; - - case PropertyFilterType.Misc_Scourged: - filters.Filters.Scourged = new StatFilterValue(propertyFilter); - hasValue = true; - break; - } - } - - return hasValue ? filters : null; - } - private StatFilterGroup? GetAndStats(List? modifierFilters, List? pseudoFilters) { var andGroup = new StatFilterGroup() @@ -716,13 +408,11 @@ private TradeItem GetItem(GameType game, Result result) ElementalDps = result.Item?.Extended?.ElementalDps ?? 0, PhysicalDps = result.Item?.Extended?.PhysicalDps ?? 0, BaseDefencePercentile = result.Item?.Extended?.BaseDefencePercentile, + Influences = result.Item?.Influences ?? new(), }; - var influences = result.Item?.Influences ?? new(); - var item = new TradeItem(itemHeader: header, itemProperties: properties, - influences: influences, sockets: ParseSockets(result.Item?.Sockets).ToList(), modifierLines: new(), pseudoModifiers: new(), diff --git a/src/Sidekick.Common.Ui/Forms/FormNumberSmall.razor b/src/Sidekick.Common.Ui/Forms/FormNumberSmall.razor index 42ec5351..5c6c6937 100644 --- a/src/Sidekick.Common.Ui/Forms/FormNumberSmall.razor +++ b/src/Sidekick.Common.Ui/Forms/FormNumberSmall.razor @@ -19,10 +19,10 @@ public string? Label { get; set; } [Parameter] - public decimal? Value { get; set; } + public double? Value { get; set; } [Parameter] - public EventCallback ValueChanged { get; set; } + public EventCallback ValueChanged { get; set; } private string Id { get; } = UiUtilities.GenerateId(); @@ -36,9 +36,9 @@ private async Task OnChange(ChangeEventArgs args) { - if (decimal.TryParse(args.Value?.ToString(), out var decimalValue)) + if (double.TryParse(args.Value?.ToString(), out var doubleValue)) { - await ValueChanged.InvokeAsync(decimalValue); + await ValueChanged.InvokeAsync(doubleValue); } else { diff --git a/src/Sidekick.Common.Ui/Forms/FormTriStateCheckbox.razor b/src/Sidekick.Common.Ui/Forms/FormTriStateCheckbox.razor index f910695b..42d0b17f 100644 --- a/src/Sidekick.Common.Ui/Forms/FormTriStateCheckbox.razor +++ b/src/Sidekick.Common.Ui/Forms/FormTriStateCheckbox.razor @@ -1,5 +1,16 @@
- + @if (Value == null) + { + + } + @if (Value == true) + { + + } + else + { + + }
public string? IndentifyingKey { get; init; } - public required bool ShowCheckbox { get; init; } - public bool ShowRow { get; init; } = true; public bool Checked { get; set; } From aafa2035ed3ee2502afb340d81e2e8b22efa2844 Mon Sep 17 00:00:00 2001 From: leMicin Date: Fri, 3 Jan 2025 23:51:32 -0500 Subject: [PATCH 09/12] Remove Flask from ValidCategories in property definitions. --- .../Parser/Properties/Definitions/CrusaderProperty.cs | 2 +- .../Parser/Properties/Definitions/ElderProperty.cs | 2 +- .../Parser/Properties/Definitions/HunterProperty.cs | 2 +- .../Parser/Properties/Definitions/RedeemerProperty.cs | 2 +- .../Parser/Properties/Definitions/ShaperProperty.cs | 2 +- .../Parser/Properties/Definitions/WarlordProperty.cs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs index 1bc65af0..3940a25a 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs @@ -10,7 +10,7 @@ public class CrusaderProperty(IGameLanguageProvider gameLanguageProvider) : Prop { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel]; public override void Initialize() { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs index fa3c060b..6797102a 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs @@ -10,7 +10,7 @@ public class ElderProperty(IGameLanguageProvider gameLanguageProvider) : Propert { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel]; public override void Initialize() { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs index 4d8c23b5..345efe0b 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs @@ -10,7 +10,7 @@ public class HunterProperty(IGameLanguageProvider gameLanguageProvider) : Proper { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel]; public override void Initialize() { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs index 32483fb3..920b7ebd 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs @@ -10,7 +10,7 @@ public class RedeemerProperty(IGameLanguageProvider gameLanguageProvider) : Prop { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel]; public override void Initialize() { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs index debc563e..68da23f6 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs @@ -10,7 +10,7 @@ public class ShaperProperty(IGameLanguageProvider gameLanguageProvider) : Proper { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel]; public override void Initialize() { diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs index fcbd4bf2..308af556 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs @@ -10,7 +10,7 @@ public class WarlordProperty(IGameLanguageProvider gameLanguageProvider) : Prope { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel, Category.Flask]; + public override List ValidCategories { get; } = [Category.Armour, Category.Weapon, Category.Accessory, Category.Jewel]; public override void Initialize() { From 2e4c7afb014dde975e96beb7b918ac22577755aa Mon Sep 17 00:00:00 2001 From: leMicin Date: Fri, 3 Jan 2025 23:53:24 -0500 Subject: [PATCH 10/12] Update item level check to account for game type --- .../Parser/Properties/Definitions/ItemLevelProperty.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs index eb0d3aba..544ab917 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs @@ -33,7 +33,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte NormalizeEnabled = true, NormalizeValue = normalizeValue, Value = item.Properties.ItemLevel, - Checked = item.Properties.ItemLevel >= 80 && item.Properties.MapTier == 0 && item.Header.Rarity != Rarity.Unique, + Checked = game == GameType.PathOfExile && item.Properties.ItemLevel >= 80 && item.Properties.MapTier == 0 && item.Header.Rarity != Rarity.Unique, }; return filter; } From 0207836a55a05238a38009ef4a8e457a2cafe3e9 Mon Sep 17 00:00:00 2001 From: leMicin Date: Fri, 3 Jan 2025 23:57:24 -0500 Subject: [PATCH 11/12] Add "Map" to AreaLevelProperty valid categories to support chronicles of atzoatl --- .../Parser/Properties/Definitions/AreaLevelProperty.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs index f3f2a6e5..da104367 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs @@ -10,7 +10,7 @@ public class AreaLevelProperty(IGameLanguageProvider gameLanguageProvider) : Pro { private Regex? Pattern { get; set; } - public override List ValidCategories { get; } = [Category.Sanctum, Category.Logbook, Category.Contract]; + public override List ValidCategories { get; } = [Category.Sanctum, Category.Logbook, Category.Contract, Category.Map]; public override void Initialize() { From 38d1ee163c1240fbaa317ebcb2d0e9c06e9d633c Mon Sep 17 00:00:00 2001 From: leMicin Date: Sat, 4 Jan 2025 12:52:45 -0500 Subject: [PATCH 12/12] Normalize filters --- .../Definitions/AreaLevelProperty.cs | 1 + .../Properties/Definitions/ArmourProperty.cs | 1 + .../Definitions/AttacksPerSecondProperty.cs | 1 + .../Definitions/BlockChanceProperty.cs | 1 + .../Definitions/CriticalHitChanceProperty.cs | 1 + .../Definitions/EnergyShieldProperty.cs | 1 + .../Definitions/EvasionRatingProperty.cs | 1 + .../Definitions/GemLevelProperty.cs | 1 + .../Definitions/ItemLevelProperty.cs | 3 +- .../Definitions/ItemQuantityProperty.cs | 1 + .../Definitions/ItemRarityProperty.cs | 1 + .../Properties/Definitions/MapTierProperty.cs | 1 + .../Definitions/MonsterPackSizeProperty.cs | 1 + .../Properties/Definitions/QualityProperty.cs | 1 + .../Definitions/WeaponDamageProperty.cs | 32 ++++++++++++------- 15 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs index da104367..01ab7144 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.cs @@ -36,6 +36,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.AreaLevel, Checked = true, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs index 941545dd..fbf306a2 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.cs @@ -41,6 +41,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.Armour, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs index 810a2962..beaa14f2 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs @@ -37,6 +37,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.AttacksPerSecond, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs index dcc3e874..0ec1c803 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs @@ -45,6 +45,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.BlockChance, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs index 392b1681..ff7e6ae9 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs @@ -45,6 +45,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.CriticalHitChance, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs index 061a927d..b1031950 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs @@ -37,6 +37,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.EnergyShield, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs index 52baf847..13ef1545 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs @@ -37,6 +37,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.EvasionRating, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs index eb1939dd..b6b91dfc 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs @@ -43,6 +43,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.GemLevel, Checked = true, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs index 544ab917..5f266d9f 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs @@ -30,11 +30,12 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte var filter = new IntPropertyFilter(this) { Text = gameLanguageProvider.Language.DescriptionItemLevel, - NormalizeEnabled = true, + NormalizeEnabled = false, NormalizeValue = normalizeValue, Value = item.Properties.ItemLevel, Checked = game == GameType.PathOfExile && item.Properties.ItemLevel >= 80 && item.Properties.MapTier == 0 && item.Header.Rarity != Rarity.Unique, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs index 8127afc3..a5ee1925 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs @@ -36,6 +36,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.ItemQuantity, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs index 429b289d..f513edd3 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemRarityProperty.cs @@ -36,6 +36,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.ItemRarity, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs index db62e7c7..caa32f51 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MapTierProperty.cs @@ -36,6 +36,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.MapTier, Checked = true, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs index 0d0bb7ba..6ca7bae6 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/MonsterPackSizeProperty.cs @@ -36,6 +36,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.MonsterPackSize, Checked = false, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs index 1b5bbb42..31f25228 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.cs @@ -36,6 +36,7 @@ public override void Parse(ItemProperties itemProperties, ParsingItem parsingIte Value = item.Properties.Quality, Checked = item.Header.Rarity == Rarity.Gem, }; + filter.NormalizeMinValue(); return filter; } diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs index 22e81438..e43bbb14 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs @@ -125,7 +125,7 @@ private void ParseElementalDamage(ParsingLine line, ItemProperties itemPropertie if (item.Properties.TotalDamage > 0) { - results.Add(new DoublePropertyFilter(this) + var filter = new DoublePropertyFilter(this) { Text = localizer["Damage"], NormalizeEnabled = true, @@ -133,55 +133,65 @@ private void ParseElementalDamage(ParsingLine line, ItemProperties itemPropertie Value = item.Properties.TotalDamage ?? 0, Checked = false, IndentifyingKey = DamageKey, - }); + }; + filter.NormalizeMinValue(); + results.Add(filter); } if (item.Properties.PhysicalDps > 0) { - results.Add(new DoublePropertyFilter(this) + var filter = new DoublePropertyFilter(this) { Text = localizer["PhysicalDps"], NormalizeEnabled = true, NormalizeValue = normalizeValue, Value = item.Properties.PhysicalDps ?? 0, Checked = false, - }); + }; + filter.NormalizeMinValue(); + results.Add(filter); } if (item.Properties.ElementalDps > 0) { - results.Add(new DoublePropertyFilter(this) + var filter = new DoublePropertyFilter(this) { Text = localizer["ElementalDps"], NormalizeEnabled = true, NormalizeValue = normalizeValue, Value = item.Properties.ElementalDps ?? 0, Checked = false, - }); + }; + filter.NormalizeMinValue(); + results.Add(filter); } if (item.Properties.ChaosDps > 0) { - results.Add(new DoublePropertyFilter(this) + var filter = new DoublePropertyFilter(this) { Text = localizer["ChaosDps"], NormalizeEnabled = true, NormalizeValue = normalizeValue, Value = item.Properties.ChaosDps ?? 0, Checked = false, - }); + }; + filter.NormalizeMinValue(); + results.Add(filter); } if (item.Properties.TotalDps > 0) { - results.Add(new DoublePropertyFilter(this) + var filter = new DoublePropertyFilter(this) { Text = localizer["Dps"], NormalizeEnabled = true, NormalizeValue = normalizeValue, Value = item.Properties.TotalDps ?? 0, Checked = false, - }); + }; + filter.NormalizeMinValue(); + results.Add(filter); } return results.Count > 0 ? results : null; @@ -189,7 +199,7 @@ private void ParseElementalDamage(ParsingLine line, ItemProperties itemPropertie public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) { - if(!filter.Checked) return; + if (!filter.Checked) return; if (filter.Text == localizer["Damage"] && filter is DoublePropertyFilter damageFilter) {