diff --git a/src/Sidekick.Apis.Poe/Authentication/IAuthenticationService.cs b/src/Sidekick.Apis.Poe/Authentication/IAuthenticationService.cs index 0151649a3..10d63d582 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 b61304d6e..8e38c33d7 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 b6f1d30e0..cb5fa6a25 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/IItemStaticDataProvider.cs b/src/Sidekick.Apis.Poe/IItemStaticDataProvider.cs index 83088329b..ed58d9838 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/ITradeFilterService.cs b/src/Sidekick.Apis.Poe/ITradeFilterService.cs index b2e65f8eb..b97f93197 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 67163f534..f9c157d28 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/Items/ApiItemConstants.cs b/src/Sidekick.Apis.Poe/Items/ApiItemConstants.cs index 9e7d24826..ae2a7ddc5 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/Items/Models/ApiItem.cs b/src/Sidekick.Apis.Poe/Items/Models/ApiItem.cs index abd0e60eb..597b2d35c 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/Localization/FilterResources.cs b/src/Sidekick.Apis.Poe/Localization/FilterResources.cs deleted file mode 100644 index 510142fd9..000000000 --- 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 c27cb0ac0..0a91d4407 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; @@ -205,7 +204,7 @@ private void InitializeRarityPatterns() }; } - public Header Parse(ParsingItem parsingItem) + public ItemHeader Parse(ParsingItem parsingItem) { var rarity = ParseRarity(parsingItem); @@ -231,7 +230,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 f3f57197c..042fd21ee 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 30f08eb56..395b0bb77 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, @@ -47,24 +46,22 @@ 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(); } // Order of parsing is important - ParseRequirements(parsingItem); - - var influences = ParseInfluences(parsingItem); + requirementsParser.Parse(parsingItem); var sockets = socketParser.Parse(parsingItem); - var modifierLines = ParseModifiers(parsingItem); - var properties = propertyParser.Parse(parsingItem, modifierLines); + var properties = propertyParser.Parse(parsingItem); + var modifierLines = modifierParser.Parse(parsingItem); + propertyParser.ParseAfterModifiers(parsingItem, properties, modifierLines); var pseudoModifiers = pseudoParser.Parse(modifierLines); var item = new Item(invariant: invariant, - header: parsingItem.Header, - properties: properties, - influences: influences, + itemHeader: parsingItem.Header, + itemProperties: properties, sockets: sockets, modifierLines: modifierLines, pseudoModifiers: pseudoModifiers, @@ -83,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 7a6f559f3..1836d4da4 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/ParsingItem.cs b/src/Sidekick.Apis.Poe/Parser/ParsingItem.cs index 22b3a8b30..cc7c090f5 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/Parser/Patterns/IParserPatterns.cs b/src/Sidekick.Apis.Poe/Parser/Patterns/IParserPatterns.cs deleted file mode 100644 index 6050f9964..000000000 --- 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 6b7f3bddb..000000000 --- a/src/Sidekick.Apis.Poe/Parser/Patterns/ParserPatterns.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Text.RegularExpressions; -using Sidekick.Common.Game.Items; -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 000000000..01ab71447 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AreaLevelProperty.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 AreaLevelProperty(IGameLanguageProvider gameLanguageProvider) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Sanctum, Category.Logbook, Category.Contract, Category.Map]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionAreaLevel.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + 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) + { + Text = gameLanguageProvider.Language.DescriptionAreaLevel, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.AreaLevel, + Checked = true, + }; + filter.NormalizeMinValue(); + 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 new file mode 100644 index 000000000..fbf306a2a --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ArmourProperty.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 ArmourProperty +( + IGameLanguageProvider gameLanguageProvider, + GameType game +) : 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) + { + Text = gameLanguageProvider.Language.DescriptionArmour, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.Armour, + Checked = false, + }; + filter.NormalizeMinValue(); + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateArmourFilters().Filters.Armour = new StatFilterValue(intFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.Armour = new StatFilterValue(intFilter); break; + } + } +} 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 000000000..beaa14f28 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/AttacksPerSecondProperty.cs @@ -0,0 +1,54 @@ +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 AttacksPerSecondProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : 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) + { + Text = gameLanguageProvider.Language.DescriptionAttacksPerSecond, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.AttacksPerSecond, + Checked = false, + }; + filter.NormalizeMinValue(); + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not DoublePropertyFilter doubleFilter) return; + + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateWeaponFilters().Filters.AttacksPerSecond = new StatFilterValue(doubleFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.AttacksPerSecond = new StatFilterValue(doubleFilter); break; + } + } +} 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 000000000..982d33991 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightRavagedProperty.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 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..e074df2a2 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlightedProperty.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 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..0ec1c803e --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/BlockChanceProperty.cs @@ -0,0 +1,62 @@ +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 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) + { + Text = text, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.BlockChance, + Checked = false, + }; + filter.NormalizeMinValue(); + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateArmourFilters().Filters.BlockChance = new StatFilterValue(intFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.BlockChance = new StatFilterValue(intFilter); break; + } + } +} 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 000000000..cd00f7046 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CorruptedProperty.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 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, Category.Gem]; + + 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) + { + Text = gameLanguageProvider.Language.DescriptionCorrupted, + Checked = null, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (filter is not TriStatePropertyFilter triStateFilter || triStateFilter.Checked == null) + { + return; + } + + searchFilters.GetOrCreateMiscFilters().Filters.Corrupted = new SearchFilterOption(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 000000000..ff7e6ae99 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CriticalHitChanceProperty.cs @@ -0,0 +1,62 @@ +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) + { + Text = text, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.CriticalHitChance, + Checked = false, + }; + filter.NormalizeMinValue(); + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not DoublePropertyFilter doubleFilter) return; + + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateWeaponFilters().Filters.CriticalHitChance = new StatFilterValue(doubleFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.CriticalHitChance = new StatFilterValue(doubleFilter); break; + } + } +} 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 000000000..3940a25ae --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/CrusaderProperty.cs @@ -0,0 +1,43 @@ +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]; + + 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..6797102a2 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ElderProperty.cs @@ -0,0 +1,43 @@ +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]; + + 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..b10319501 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EnergyShieldProperty.cs @@ -0,0 +1,54 @@ +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 EnergyShieldProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : 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) + { + Text = gameLanguageProvider.Language.DescriptionEnergyShield, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.EnergyShield, + Checked = false, + }; + filter.NormalizeMinValue(); + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateArmourFilters().Filters.EnergyShield = new StatFilterValue(intFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.EnergyShield = new StatFilterValue(intFilter); break; + } + } +} 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 000000000..13ef15456 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/EvasionRatingProperty.cs @@ -0,0 +1,54 @@ +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 EvasionRatingProperty(IGameLanguageProvider gameLanguageProvider, GameType game) : 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) + { + Text = gameLanguageProvider.Language.DescriptionEvasion, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.EvasionRating, + Checked = false, + }; + filter.NormalizeMinValue(); + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateArmourFilters().Filters.EvasionRating = new StatFilterValue(intFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.EvasionRating = new StatFilterValue(intFilter); break; + } + } +} diff --git a/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs new file mode 100644 index 000000000..b6b91dfc1 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/GemLevelProperty.cs @@ -0,0 +1,63 @@ +using System.Text.RegularExpressions; +using Sidekick.Apis.Poe.Items; +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 GemLevelProperty +( + IGameLanguageProvider gameLanguageProvider, + GameType game, + IApiInvariantItemProvider apiInvariantItemProvider +) : PropertyDefinition +{ + private Regex? Pattern { get; set; } + + public override List ValidCategories { get; } = [Category.Gem]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionLevel.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + var propertyBlock = parsingItem.Blocks[1]; + itemProperties.GemLevel = GetInt(Pattern, propertyBlock); + if (itemProperties.GemLevel > 0) propertyBlock.Parsed = true; + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.GemLevel <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + Text = gameLanguageProvider.Language.DescriptionLevel, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.GemLevel, + Checked = true, + }; + filter.NormalizeMinValue(); + return filter; + } + + public 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.GemLevel = new StatFilterValue(intFilter); break; + + 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/HunterProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs new file mode 100644 index 000000000..345efe0bb --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/HunterProperty.cs @@ -0,0 +1,43 @@ +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]; + + 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..5f266d9fc --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemLevelProperty.cs @@ -0,0 +1,53 @@ +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 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, Category.Map, Category.Contract, Category.Sanctum, Category.Logbook]; + + public override void Initialize() + { + Pattern = gameLanguageProvider.Language.DescriptionItemLevel.ToRegexIntCapture(); + } + + public override void Parse(ItemProperties itemProperties, ParsingItem parsingItem) + { + itemProperties.ItemLevel = GetInt(Pattern, parsingItem); + } + + public override BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) + { + if (item.Properties.ItemLevel <= 0) return null; + + var filter = new IntPropertyFilter(this) + { + Text = gameLanguageProvider.Language.DescriptionItemLevel, + 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; + } + + public 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/ItemQuantityProperty.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ItemQuantityProperty.cs new file mode 100644 index 000000000..a5ee1925d --- /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) + { + Text = gameLanguageProvider.Language.DescriptionItemQuantity, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.ItemQuantity, + Checked = false, + }; + filter.NormalizeMinValue(); + 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 = new StatFilterValue(intFilter); + } +} 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 000000000..f513edd38 --- /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) + { + Text = gameLanguageProvider.Language.DescriptionItemRarity, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.ItemRarity, + Checked = false, + }; + filter.NormalizeMinValue(); + 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 = new StatFilterValue(intFilter); + } +} 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 000000000..caa32f517 --- /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]; + + 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) + { + Text = gameLanguageProvider.Language.DescriptionMapTier, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.MapTier, + Checked = true, + }; + filter.NormalizeMinValue(); + 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 = new StatFilterValue(intFilter); + } +} 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 000000000..6ca7bae6f --- /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) + { + Text = gameLanguageProvider.Language.DescriptionMonsterPackSize, + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.MonsterPackSize, + Checked = false, + }; + filter.NormalizeMinValue(); + 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 = new StatFilterValue(intFilter); + } +} 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 000000000..31f252286 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/QualityProperty.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 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) + { + Text = gameLanguageProvider.Language.DescriptionQuality, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.Quality, + Checked = item.Header.Rarity == Rarity.Gem, + }; + filter.NormalizeMinValue(); + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMiscFilters().Filters.Quality = new StatFilterValue(intFilter); + } +} 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 000000000..920b7ebdc --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/RedeemerProperty.cs @@ -0,0 +1,43 @@ +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]; + + 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..100da33c7 --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/SeparatorProperty.cs @@ -0,0 +1,29 @@ +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) + { + 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 000000000..68da23f6e --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/ShaperProperty.cs @@ -0,0 +1,43 @@ +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]; + + 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..fa8e9e7ba --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/UnidentifiedProperty.cs @@ -0,0 +1,46 @@ +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 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) + { + 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) + { + Text = gameLanguageProvider.Language.DescriptionQuality, + NormalizeEnabled = false, + NormalizeValue = normalizeValue, + Value = item.Properties.Quality, + Checked = item.Header.Rarity == Rarity.Gem, + }; + return filter; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked || filter is not IntPropertyFilter intFilter) return; + + searchFilters.GetOrCreateMiscFilters().Filters.Quality = new StatFilterValue(intFilter); + } +} 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 000000000..308af556b --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WarlordProperty.cs @@ -0,0 +1,43 @@ +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]; + + 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) + { + 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 = new SearchFilterOption(filter); + } +} 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 000000000..e43bbb14a --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/Definitions/WeaponDamageProperty.cs @@ -0,0 +1,245 @@ +using System.Globalization; +using System.Text.RegularExpressions; +using Microsoft.Extensions.Localization; +using Sidekick.Apis.Poe.Modifiers; +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 WeaponDamageProperty +( + IGameLanguageProvider gameLanguageProvider, + GameType game, + IInvariantModifierProvider invariantModifierProvider, + IStringLocalizer localizer +) : PropertyDefinition +{ + public const string DamageKey = "Damage"; + + public override List ValidCategories { get; } = [Category.Weapon]; + + public override void Initialize() + { + } + + 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 List? GetFilters(Item item, double normalizeValue) + { + var results = new List(); + + if (item.Properties.TotalDamage > 0) + { + var filter = new DoublePropertyFilter(this) + { + Text = localizer["Damage"], + NormalizeEnabled = true, + NormalizeValue = normalizeValue, + Value = item.Properties.TotalDamage ?? 0, + Checked = false, + IndentifyingKey = DamageKey, + }; + filter.NormalizeMinValue(); + results.Add(filter); + } + + if (item.Properties.PhysicalDps > 0) + { + 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) + { + 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) + { + 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) + { + 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; + } + + public override void PrepareTradeRequest(SearchFilters searchFilters, Item item, BooleanPropertyFilter filter) + { + if (!filter.Checked) return; + + if (filter.Text == localizer["Damage"] && filter is DoublePropertyFilter damageFilter) + { + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateWeaponFilters().Filters.Damage = new StatFilterValue(damageFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.Damage = new StatFilterValue(damageFilter); break; + } + } + + if (filter.Text == localizer["PhysicalDps"] && filter is DoublePropertyFilter physicalDpsFilter) + { + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateWeaponFilters().Filters.PhysicalDps = new StatFilterValue(physicalDpsFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.PhysicalDps = new StatFilterValue(physicalDpsFilter); break; + } + } + + if (filter.Text == localizer["ElementalDps"] && filter is DoublePropertyFilter elementalDpsFilter) + { + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateWeaponFilters().Filters.ElementalDps = new StatFilterValue(elementalDpsFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.ElementalDps = new StatFilterValue(elementalDpsFilter); break; + } + } + + if (filter.Text == localizer["ChaosDps"] && filter is DoublePropertyFilter chaosDpsFilter) + { + // searchFilters.GetOrCreateWeaponFilters().Filters.ChaosDps = new StatFilterValue(chaosDpsFilter); + } + + if (filter.Text == localizer["Dps"] && filter is DoublePropertyFilter dpsFilter) + { + switch (game) + { + case GameType.PathOfExile: searchFilters.GetOrCreateWeaponFilters().Filters.DamagePerSecond = new StatFilterValue(dpsFilter); break; + case GameType.PathOfExile2: searchFilters.GetOrCreateEquipmentFilters().Filters.DamagePerSecond = new StatFilterValue(dpsFilter); break; + } + } + } +} 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 000000000..c383e2385 --- /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(PropertyDefinition definition) +{ + /// + /// Represents a key used to uniquely identify a property filter to do custom work on this filter. + /// + public string? IndentifyingKey { get; init; } + + public bool ShowRow { get; init; } = true; + + public bool Checked { get; set; } + + public required string Text { get; init; } + + public PropertyDefinition Definition { get; } = definition; +} 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 000000000..8226b01eb --- /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/FilterResources.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/FilterResources.cs new file mode 100644 index 000000000..5ab68b5ba --- /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 24b6be4ad..0b0c6c246 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/IntPropertyFilter.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/IntPropertyFilter.cs new file mode 100644 index 000000000..06a5df5fd --- /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/PropertyFilters.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/PropertyFilters.cs new file mode 100644 index 000000000..61a598c33 --- /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/Filters/TriStatePropertyFilter.cs b/src/Sidekick.Apis.Poe/Parser/Properties/Filters/TriStatePropertyFilter.cs new file mode 100644 index 000000000..906ca5d7f --- /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 c2486c61c..01f6b1c06 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/IPropertyParser.cs @@ -1,9 +1,18 @@ -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; public interface IPropertyParser: IInitializableService { - Common.Game.Items.Properties Parse(ParsingItem parsingItem, List modifierLines); + 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 new file mode 100644 index 000000000..f771c199a --- /dev/null +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyDefinition.cs @@ -0,0 +1,75 @@ +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 +{ + public abstract List ValidCategories { get; } + + public abstract void Initialize(); + + public virtual void Parse(ItemProperties itemProperties, ParsingItem parsingItem) {} + + public virtual void ParseAfterModifiers(ItemProperties itemProperties, ParsingItem parsingItem, List modifierLines) {} + + public virtual BooleanPropertyFilter? GetFilter(Item item, double normalizeValue) { return null; } + + 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) + { + if (pattern == null) + { + return false; + } + + return parsingItem.TryParseRegex(pattern, out _); + } + + protected static int GetInt(Regex? pattern, ParsingItem parsingItem) + { + if (pattern != null && 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 && 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 || !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 d37c0ad66..8097a6bbd 100644 --- a/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs +++ b/src/Sidekick.Apis.Poe/Parser/Properties/PropertyParser.cs @@ -1,35 +1,29 @@ -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.Requests.Filters; +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, + IStringLocalizer filterLocalizer ) : 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; } @@ -39,39 +33,57 @@ IInvariantModifierProvider invariantModifierProvider private Regex? MonsterPackSize { get; set; } - private Regex? AttacksPerSecond { get; set; } + private Regex? Blighted { get; set; } - private Regex? CriticalStrikeChance { get; set; } + private Regex? BlightRavaged { get; set; } - private Regex? ElementalDamage { get; set; } + private Regex? AreaLevel { get; set; } - private Regex? PhysicalDamage { get; set; } + public async Task Initialize() + { + var leagueId = await settingsService.GetString(SettingKeys.LeagueId); + var game = leagueId.GetGameFromLeagueId(); - private Regex? Blighted { get; set; } + Definitions.Clear(); + Definitions.AddRange([ + new QualityProperty(gameLanguageProvider), - private Regex? BlightRavaged { get; set; } + new ArmourProperty(gameLanguageProvider, game), + new EvasionRatingProperty(gameLanguageProvider, game), + new EnergyShieldProperty(gameLanguageProvider, game), + new BlockChanceProperty(gameLanguageProvider, game), - private Regex? AreaLevel { get; set; } + new WeaponDamageProperty(gameLanguageProvider, game, invariantModifierProvider, filterLocalizer), + new AttacksPerSecondProperty(gameLanguageProvider, game), + new CriticalHitChanceProperty(gameLanguageProvider, game), - private Regex? Unidentified { get; set; } + new ItemQuantityProperty(gameLanguageProvider), + new ItemRarityProperty(gameLanguageProvider), + new MonsterPackSizeProperty(gameLanguageProvider), + new BlightedProperty(gameLanguageProvider), + new BlightRavagedProperty(gameLanguageProvider), + new MapTierProperty(gameLanguageProvider), + new AreaLevelProperty(gameLanguageProvider), - private Regex? Corrupted { get; set; } + new SeparatorProperty(), - 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(); + new GemLevelProperty(gameLanguageProvider, game, apiInvariantItemProvider), + new ItemLevelProperty(gameLanguageProvider, game), + new CorruptedProperty(gameLanguageProvider), + new UnidentifiedProperty(gameLanguageProvider), + + new ElderProperty(gameLanguageProvider), + new ShaperProperty(gameLanguageProvider), + new CrusaderProperty(gameLanguageProvider), + new HunterProperty(gameLanguageProvider), + new RedeemerProperty(gameLanguageProvider), + new WarlordProperty(gameLanguageProvider), + ]); + + foreach (var definition in Definitions) + { + definition.Initialize(); + } MapTier = gameLanguageProvider.Language.DescriptionMapTier.ToRegexIntCapture(); AreaLevel = gameLanguageProvider.Language.DescriptionAreaLevel.ToRegexIntCapture(); @@ -80,296 +92,84 @@ 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 Common.Game.Items.Properties Parse(ParsingItem parsingItem, List modifierLines) + public ItemProperties Parse(ParsingItem parsingItem) { - return parsingItem.Header?.Category switch + var properties = new ItemProperties(); + foreach (var definition in Definitions) { - 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 Common.Game.Items.Properties(), - }; - } - - private Common.Game.Items.Properties ParseWeaponProperties(ParsingItem parsingItem, List modifierLines) - { - var propertyBlock = parsingItem.Blocks[1]; - var attacksPerSecond = GetDouble(AttacksPerSecond, propertyBlock); - var criticalStrikeChance = GetDouble(CriticalStrikeChance, propertyBlock); + if (definition.ValidCategories.Count > 0 && !definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; - var properties = new Common.Game.Items.Properties - { - 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; + definition.Parse(properties, parsingItem); } return properties; } - private void ParseElementalDamage(ParsingLine line, Common.Game.Items.Properties properties, 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) - { - properties.FireDamage = range; - matchIndex++; - continue; - } - - var isCold = invariantModifierProvider.ColdWeaponDamageIds.Any(x => ids.Contains(x)); - if (isCold) - { - properties.ColdDamage = range; - matchIndex++; - continue; - } - - var isLightning = invariantModifierProvider.LightningWeaponDamageIds.Any(x => ids.Contains(x)); - if (isLightning) - { - properties.LightningDamage = range; - matchIndex++; - continue; - } + if (definition.ValidCategories.Count > 0 && !definition.ValidCategories.Contains(parsingItem.Header?.Category ?? Category.Unknown)) continue; - matchIndex++; + definition.ParseAfterModifiers(properties, parsingItem, modifierLines); } } - private Common.Game.Items.Properties ParseArmourProperties(ParsingItem parsingItem) - { - var propertyBlock = parsingItem.Blocks[1]; - - return new Common.Game.Items.Properties() - { - 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 Common.Game.Items.Properties ParseAccessoryProperties(ParsingItem parsingItem) - { - return new Common.Game.Items.Properties() - { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - }; - } - - private Common.Game.Items.Properties ParseMapProperties(ParsingItem parsingItem) - { - var propertyBlock = parsingItem.Blocks[1]; - - return new Common.Game.Items.Properties() - { - 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 Common.Game.Items.Properties ParseGemProperties(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 Common.Game.Items.Properties() - { - Corrupted = GetBool(Corrupted, parsingItem), - GemLevel = GetInt(Level, propertyBlock), - Quality = GetInt(Quality, propertyBlock), - AlternateQuality = GetBool(AlternateQuality, parsingItem), - }; - } - - private Common.Game.Items.Properties ParseJewelProperties(ParsingItem parsingItem) - { - return new Common.Game.Items.Properties() + foreach (var definition in Definitions) { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - }; - } + if (definition.ValidCategories.Count > 0 && !definition.ValidCategories.Contains(item.Header.Category)) continue; - private Common.Game.Items.Properties ParseFlaskProperties(ParsingItem parsingItem) - { - return new Common.Game.Items.Properties() - { - ItemLevel = GetInt(ItemLevel, parsingItem), - Identified = !GetBool(Unidentified, parsingItem), - Corrupted = GetBool(Corrupted, parsingItem), - Quality = GetInt(Quality, parsingItem), - }; - } + var filter = definition.GetFilter(item, normalizeValue); + if (filter != null) results.Add(filter); - private Common.Game.Items.Properties ParseSanctumProperties(ParsingItem parsingItem) - { - return new Common.Game.Items.Properties - { - AreaLevel = GetInt(AreaLevel, parsingItem), - }; - } - - private Common.Game.Items.Properties ParseLogbookProperties(ParsingItem parsingItem) - { - return new Common.Game.Items.Properties - { - AreaLevel = GetInt(AreaLevel, parsingItem), - }; - } - - private static bool GetBool(Regex? pattern, ParsingItem parsingItem) - { - if (pattern == null) - { - return false; + var filters = definition.GetFilters(item, normalizeValue); + if (filters != null) results.AddRange(filters); } - return parsingItem.TryParseRegex(pattern, out _); + CleanUpSeparatorFilters(results); + + return results; } - private static int GetInt(Regex? pattern, ParsingItem parsingItem) + private void CleanUpSeparatorFilters(List results) { - if (pattern == null) + // Remove leading SeparatorProperty filters + while (results.Count > 0 && results[0].Definition is SeparatorProperty) { - return 0; + results.RemoveAt(0); } - if (parsingItem.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) + // Remove trailing SeparatorProperty filters + while (results.Count > 0 && results[^1].Definition is SeparatorProperty) { - return result; + results.RemoveAt(results.Count - 1); } - return 0; - } - - private static int GetInt(Regex? pattern, ParsingBlock parsingBlock) - { - if (pattern == null) + // Remove consecutive SeparatorProperty filters + for (var i = 1; i < results.Count; i++) { - return 0; - } + if (results[i].Definition is not SeparatorProperty || results[i - 1].Definition is not SeparatorProperty) + { + continue; + } - if (parsingBlock.TryParseRegex(pattern, out var match) && int.TryParse(match.Groups[1].Value, out var result)) - { - return result; + results.RemoveAt(i); + i--; // Adjust index to recheck current position } - - return 0; } - private static double GetDouble(Regex? pattern, ParsingBlock parsingBlock) + public void PrepareTradeRequest(SearchFilters searchFilters, Item item, PropertyFilters propertyFilters) { - if (pattern == null) + foreach (var filter in propertyFilters.Filters) { - return 0; + filter.Definition.PrepareTradeRequest(searchFilters, item, filter); } - - 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/Patterns/RegexExtensions.cs b/src/Sidekick.Apis.Poe/Parser/RegexExtensions.cs similarity index 83% rename from src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs rename to src/Sidekick.Apis.Poe/Parser/RegexExtensions.cs index 542ea4dd3..3a6164929 100644 --- a/src/Sidekick.Apis.Poe/Parser/Patterns/RegexExtensions.cs +++ b/src/Sidekick.Apis.Poe/Parser/RegexExtensions.cs @@ -1,12 +1,12 @@ using System.Text.RegularExpressions; -namespace Sidekick.Apis.Poe.Parser.Patterns; +namespace Sidekick.Apis.Poe.Parser; 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/Requirements/IRequirementsParser.cs b/src/Sidekick.Apis.Poe/Parser/Requirements/IRequirementsParser.cs new file mode 100644 index 000000000..a06bc7ba1 --- /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 000000000..3a0d81602 --- /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/Sidekick.Apis.Poe.csproj b/src/Sidekick.Apis.Poe/Sidekick.Apis.Poe.csproj index 11337fff3..4981e80b9 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/StartupExtensions.cs b/src/Sidekick.Apis.Poe/StartupExtensions.cs index 8fbc5a5ff..ff454238b 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/Static/ItemStaticDataProvider.cs b/src/Sidekick.Apis.Poe/Static/ItemStaticDataProvider.cs index 65c84dcaa..b95d6a3d3 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/ITradeFilter.cs b/src/Sidekick.Apis.Poe/Trade/Models/ITradeFilter.cs index e97756556..68475d0c6 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 caa3f9223..6082aa4b9 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 9c132998f..000000000 --- a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilter.cs +++ /dev/null @@ -1,132 +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); - } - } - } - - public bool ShowCheckbox - { - get - { - return Type != PropertyFilterType.Weapon_ChaosDps; - } - } - - /// - /// 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/PropertyFilterType.cs b/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilterType.cs deleted file mode 100644 index 0d6e79f5e..000000000 --- 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 deleted file mode 100644 index 6b561112e..000000000 --- a/src/Sidekick.Apis.Poe/Trade/Models/PropertyFilters.cs +++ /dev/null @@ -1,13 +0,0 @@ -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 Weapon { get; set; } = new(); - public List Armour { get; set; } = new(); - public List Map { get; set; } = new(); - public List Misc { get; set; } = new(); - } -} diff --git a/src/Sidekick.Apis.Poe/Trade/Models/PseudoModifierFilter.cs b/src/Sidekick.Apis.Poe/Trade/Models/PseudoModifierFilter.cs index df384a4e2..c5ffa377b 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 84722be59..4718c8944 100644 --- a/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs +++ b/src/Sidekick.Apis.Poe/Trade/Models/TradeItem.cs @@ -4,17 +4,15 @@ namespace Sidekick.Apis.Poe.Trade.Models { public class TradeItem ( - Header header, - Properties properties, - Influences influences, + ItemHeader itemHeader, + ItemProperties itemProperties, List sockets, List modifierLines, List pseudoModifiers, string text ) : Item(null, - header, - properties, - influences, + itemHeader, + itemProperties, 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 aee0d4c3d..01b1c30ef 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 cb18a8dea..510f24858 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? Armor { 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? Evasion { get; set; } + [JsonPropertyName("ev")] + public StatFilterValue? EvasionRating { get; set; } - [JsonPropertyName("block")] - public StatFilterValue? Block { 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 a6205c0c3..ab73a710f 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 73e4d53fe..01c8f7052 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? Armour { 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? EvasionRating { get; set; } - [JsonPropertyName("block")] - public StatFilterValue? Block { get; set; } + [JsonPropertyName("block")] + public StatFilterValue? BlockChance { get; set; } - [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/Requests/Filters/MapFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/MapFilterGroup.cs index ce743c27a..98cb715d7 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 17b821438..dad85df31 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 da1a26fad..da70d183f 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 bc243bd30..d0a6dfe01 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 b639207d0..5cef2c34f 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 aa2c6561f..ea3e84970 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 6785c1cd3..419a95f1d 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilterOption.cs @@ -1,19 +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; - } + Option = option; + } - public SearchFilterOption(PropertyFilter 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 09676f63f..a03cb7ed7 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SearchFilters.cs @@ -1,34 +1,44 @@ using System.Text.Json.Serialization; -namespace Sidekick.Apis.Poe.Trade.Requests.Filters +namespace Sidekick.Apis.Poe.Trade.Requests.Filters; + +public 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("misc_filters")] + public MiscFilterGroup? MiscFilters { get; set; } + + public MiscFilterGroup GetOrCreateMiscFilters() => MiscFilters ??= new(); + + [JsonPropertyName("weapon_filters")] + public WeaponFilterGroup? WeaponFilters { get; set; } + + public WeaponFilterGroup GetOrCreateWeaponFilters() => WeaponFilters ??= new(); + + [JsonPropertyName("armour_filters")] + public ArmourFilterGroup? ArmourFilters { get; set; } - [JsonPropertyName("trade_filters")] - public TradeFilterGroup? TradeFilters { get; set; } + public ArmourFilterGroup GetOrCreateArmourFilters() => ArmourFilters ??= new(); - [JsonPropertyName("misc_filters")] - public MiscFilterGroup? MiscFilters { get; set; } + [JsonPropertyName("equipment_filters")] + public EquipmentFilterGroup? EquipmentFilters { get; set; } - [JsonPropertyName("weapon_filters")] - public WeaponFilterGroup? WeaponFilters { get; set; } + public EquipmentFilterGroup GetOrCreateEquipmentFilters() => EquipmentFilters ??= new(); - [JsonPropertyName("armour_filters")] - public ArmourFilterGroup? ArmourFilters { get; set; } + [JsonPropertyName("socket_filters")] + public SocketFilterGroup? SocketFilters { get; set; } - [JsonPropertyName("equipment_filters")] - public EquipmentFilterGroup? EquipmentFilters { get; set; } + [JsonPropertyName("req_filters")] + public RequirementFilterGroup? RequirementFilters { get; set; } - [JsonPropertyName("socket_filters")] - public SocketFilterGroup? SocketFilters { get; set; } + [JsonPropertyName("map_filters")] + public MapFilterGroup? MapFilters { get; set; } - [JsonPropertyName("req_filters")] - public RequirementFilterGroup? RequirementFilters { get; set; } + public MapFilterGroup GetOrCreateMapFilters() => MapFilters ??= new(); - [JsonPropertyName("map_filters")] - public MapFilterGroup? MapFilters { get; set; } - } } diff --git a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterGroup.cs b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/SocketFilterGroup.cs index 8da7e826b..9c453c0fb 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 5a93ef5a8..e9b0e0a36 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 54f2042dd..27a81b57e 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 5c1478058..b70c5f3e4 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 8b7241540..de48fa07a 100644 --- a/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs +++ b/src/Sidekick.Apis.Poe/Trade/Requests/Filters/StatFilterValue.cs @@ -1,8 +1,9 @@ +using Sidekick.Apis.Poe.Parser.Properties.Filters; using Sidekick.Apis.Poe.Trade.Models; namespace Sidekick.Apis.Poe.Trade.Requests.Filters; -internal class StatFilterValue +public class StatFilterValue { internal StatFilterValue() { @@ -13,9 +14,16 @@ 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(DoublePropertyFilter filter) + { + Option = filter.Checked ? "true" : "false"; Min = filter.Min; Max = filter.Max; } @@ -29,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 ca05d76cf..d5b75010a 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 e1dce5452..2c9365f03 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 b5d427589..f8bc41618 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 cf4f1ce9e..b522eeaad 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 97de7280a..7a676879b 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 5711cc0ff..093d27a40 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 b757c6bac..8315b2443 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 19c6db45c..a0b5cc9f3 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 5e61fba9f..79192bfdc 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,86 +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(); - - // 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); - - // 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 6ec3cf33c..06f86035e 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; @@ -121,11 +122,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. @@ -175,318 +172,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.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 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.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; - } - - 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() @@ -697,7 +382,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, @@ -709,25 +394,23 @@ 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, - 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, BaseDefencePercentile = result.Item?.Extended?.BaseDefencePercentile, + Influences = result.Item?.Influences ?? new(), }; - var influences = result.Item?.Influences ?? new(); - - var item = new TradeItem(header: header, - properties: properties, - influences: influences, + var item = new TradeItem(itemHeader: header, + itemProperties: properties, sockets: ParseSockets(result.Item?.Sockets).ToList(), modifierLines: new(), pseudoModifiers: new(), @@ -961,7 +644,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.Ui/Forms/FormNumberSmall.razor b/src/Sidekick.Common.Ui/Forms/FormNumberSmall.razor index 42ec53513..5c6c69371 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 f910695b6..42d0b17f9 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 + { + + }