Finished initial implementation of filter processing core

This commit is contained in:
Ben Wallis 2015-12-29 22:03:07 +00:00
parent 1bdc8bf6fd
commit d159f0b262
18 changed files with 11872 additions and 35 deletions

View File

@ -69,10 +69,16 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Services\TestItemBlockItemMatcher.cs" /> <Compile Include="Services\TestItemBlockItemMatcher.cs" />
<Compile Include="Services\TestItemFilterProcessor.cs" /> <Compile Include="Services\TestItemFilterProcessor.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -84,6 +90,19 @@
<Project>{4aac3beb-1dc1-483e-9d11-0e9334e80227}</Project> <Project>{4aac3beb-1dc1-483e-9d11-0e9334e80227}</Project>
<Name>Filtration.ObjectModel</Name> <Name>Filtration.ObjectModel</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\Filtration\Filtration.csproj">
<Project>{55e0a34c-e039-43d7-a024-a4045401cdda}</Project>
<Name>Filtration</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Resources\MuldiniFilterScript.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" /> <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

View File

@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Filtration.ItemFilterPreview.Tests.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Filtration.ItemFilterPreview.Tests.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to ###############################################################################
///################ Path of Exile Item Filter - Script by Muldini ################
///###############################################################################
///############ http://www.pathofexile.com/forum/view-thread/1259059 #############
///
///
///
///
///###############################################################################
///### Overview ##################################################################
///################## [rest of string was truncated]&quot;;.
/// </summary>
internal static string MuldiniFilterScript {
get {
return ResourceManager.GetString("MuldiniFilterScript", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="MuldiniFilterScript" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\MuldiniFilterScript.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,16 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using System.Resources;
using System.Runtime.Versioning;
using Filtration.ItemFilterPreview.Model; using Filtration.ItemFilterPreview.Model;
using Filtration.ItemFilterPreview.Services; using Filtration.ItemFilterPreview.Services;
using Filtration.ItemFilterPreview.Tests.Properties;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.ObjectModel.BlockItemBaseTypes; using Filtration.ObjectModel.BlockItemBaseTypes;
using Filtration.ObjectModel.BlockItemTypes;
using Filtration.ObjectModel.Enums; using Filtration.ObjectModel.Enums;
using Filtration.Translators;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
@ -25,19 +31,206 @@ namespace Filtration.ItemFilterPreview.Tests.Services
public void ProcessItemsAgainstItemFilterScript_Matches_ReturnsTrue() public void ProcessItemsAgainstItemFilterScript_Matches_ReturnsTrue()
{ {
//Arrange //Arrange
var testInputItem = Mock.Of<IItem>(i => i.ItemClass == "Test Class"); var testInputItem = Mock.Of<IItem>();
var testInputBlockItem = new ActionBlockItem(BlockAction.Show); var testInputBlock = Mock.Of<IItemFilterBlock>();
var testInputBlock = Mock.Of<IItemFilterBlock>(b => b.Action == BlockAction.Show &&
b.BlockItems == new ObservableCollection<IItemFilterBlockItem> {testInputBlockItem});
var testInputScript = Mock.Of<IItemFilterScript>(s => s.ItemFilterBlocks == new ObservableCollection<IItemFilterBlock> {testInputBlock}); var testInputScript = Mock.Of<IItemFilterScript>(s => s.ItemFilterBlocks == new ObservableCollection<IItemFilterBlock> {testInputBlock});
_testUtility.MockBlockItemMatcher
.Setup(b => b.ItemBlockMatch(testInputBlock, testInputItem))
.Returns(true)
.Verifiable();
//Act //Act
var result = _testUtility.ItemFilterProcessor.ProcessItemsAgainstItemFilterScript(testInputScript, new List<IItem> { testInputItem }); var result = _testUtility.ItemFilterProcessor.ProcessItemsAgainstItemFilterScript(testInputScript, new List<IItem> { testInputItem });
//Assert //Assert
_testUtility.MockBlockItemMatcher.Verify();
Assert.AreEqual(testInputBlock, result[testInputItem]); Assert.AreEqual(testInputBlock, result[testInputItem]);
} }
[Test]
public void ProcessItemsAgainstItemFilterScript_DoesNotMatch_ReturnsFalse()
{
//Arrange
var testInputItem = Mock.Of<IItem>();
var testInputBlock = Mock.Of<IItemFilterBlock>();
var testInputScript = Mock.Of<IItemFilterScript>(s => s.ItemFilterBlocks == new ObservableCollection<IItemFilterBlock> { testInputBlock });
_testUtility.MockBlockItemMatcher
.Setup(b => b.ItemBlockMatch(testInputBlock, testInputItem))
.Returns(false)
.Verifiable();
//Act
var result = _testUtility.ItemFilterProcessor.ProcessItemsAgainstItemFilterScript(testInputScript, new List<IItem> { testInputItem });
//Assert
_testUtility.MockBlockItemMatcher.Verify();
Assert.AreEqual(null, result[testInputItem]);
}
[Test]
public void ProcessItemsAgainstItemFilterScript_IntegrationTest()
{
//Arrange
var testInputScriptFile = Resources.MuldiniFilterScript;
var blockGroupHierarchyBuilder = new BlockGroupHierarchyBuilder();
var scriptTranslator = new ItemFilterScriptTranslator(new ItemFilterBlockTranslator(blockGroupHierarchyBuilder), blockGroupHierarchyBuilder);
var script = scriptTranslator.TranslateStringToItemFilterScript(testInputScriptFile);
var testInputItem = new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
};
var itemFilterProcessor = new ItemFilterProcessor(new BlockItemMatcher());
//Act
var result = itemFilterProcessor.ProcessItemsAgainstItemFilterScript(script, new List<IItem> { testInputItem });
//Assert
Assert.AreEqual("Wands", result.Values.First().BlockItems.OfType<ClassBlockItem>().First().Items.First());
}
[Test]
public void ProcessItemsAgainstItemFilterScript_IntegrationTest_10Items()
{
//Arrange
var testInputScriptFile = Resources.MuldiniFilterScript;
var blockGroupHierarchyBuilder = new BlockGroupHierarchyBuilder();
var scriptTranslator = new ItemFilterScriptTranslator(new ItemFilterBlockTranslator(blockGroupHierarchyBuilder), blockGroupHierarchyBuilder);
var script = scriptTranslator.TranslateStringToItemFilterScript(testInputScriptFile);
var testInputItems = new List<IItem>
{
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
},
new Item
{
BaseType = "BlahdeBlah",
ItemClass = "Wands",
ItemRarity = ItemRarity.Magic,
ItemLevel = 9,
DropLevel = 9,
Height = 3,
Width = 1,
SocketGroups = new List<SocketGroup> {new SocketGroup(new List<Socket> {new Socket(SocketColor.Red)}, false)}
}
};
var itemFilterProcessor = new ItemFilterProcessor(new BlockItemMatcher());
//Act
var result = itemFilterProcessor.ProcessItemsAgainstItemFilterScript(script, testInputItems);
//Assert
Assert.AreEqual("Wands", result.Values.First().BlockItems.OfType<ClassBlockItem>().First().Items.First());
}
private class ItemFilterProcessorTestUtility private class ItemFilterProcessorTestUtility
{ {
public ItemFilterProcessorTestUtility() public ItemFilterProcessorTestUtility()

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Xceed.Wpf.AvalonDock" publicKeyToken="3e4669d2f30244f4" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.5.0.0" newVersion="2.5.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -1,16 +1,7 @@
using System; using System.Windows;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace Filtration.ItemFilterPreview namespace Filtration.ItemFilterPreview
{ {
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application public partial class App : Application
{ {
} }

View File

@ -36,6 +36,14 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.3.3.0\lib\net45\Castle.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Castle.Windsor, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Windsor.3.3.0\lib\net45\Castle.Windsor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
@ -63,6 +71,7 @@
<Compile Include="UserControls\ItemSocketsControl.xaml.cs"> <Compile Include="UserControls\ItemSocketsControl.xaml.cs">
<DependentUpon>ItemSocketsControl.xaml</DependentUpon> <DependentUpon>ItemSocketsControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="WindsorInstallers\ServicesInstaller.cs" />
<Page Include="MainWindow.xaml"> <Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
@ -98,6 +107,7 @@
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.ObjectModel.Enums; using Filtration.ObjectModel.Enums;
@ -54,8 +55,8 @@ namespace Filtration.ItemFilterPreview.Model
} }
var evenSocketCount = socketCount % 2 == 0; var evenSocketCount = socketCount % 2 == 0;
var maxSocketGroups = evenSocketCount ? socketCount / 2 : socketCount - 1; var maxSocketGroups = Math.Max(1, evenSocketCount ? socketCount / 2 : socketCount - 1);
var maxLinkedSocketGroups = evenSocketCount ? maxSocketGroups : maxSocketGroups - 1; var maxLinkedSocketGroups = Math.Max(1, evenSocketCount ? maxSocketGroups : maxSocketGroups - 1);
if (value.Count > maxSocketGroups) if (value.Count > maxSocketGroups)
{ {
@ -69,7 +70,10 @@ namespace Filtration.ItemFilterPreview.Model
_socketGroups = value; _socketGroups = value;
Sockets = socketCount; Sockets = socketCount;
LinkedSockets = value.Where(s => s.Linked).Max(s => s.Count);
var linkedSocketGroups = value.Where(s => s.Linked).ToList();
LinkedSockets = linkedSocketGroups.Any() ? linkedSocketGroups.Max(s => s.Count) : 0;
} }
} }
} }

View File

@ -17,9 +17,11 @@ namespace Filtration.ItemFilterPreview.Services
public bool ItemBlockMatch(IItemFilterBlock block, IItem item) public bool ItemBlockMatch(IItemFilterBlock block, IItem item)
{ {
return block.BlockItems var match = block.BlockItems
.Where(blockItem => !(blockItem is IAudioVisualBlockItem) && !(blockItem is ActionBlockItem)) .Where(blockItem => !(blockItem is IAudioVisualBlockItem) && !(blockItem is ActionBlockItem))
.All(blockItem => ItemBlockItemMatch(blockItem, item)); .All(blockItem => ItemBlockItemMatch(blockItem, item));
return match;
} }
public bool ItemBlockItemMatch(IItemFilterBlockItem blockItem, IItem item) public bool ItemBlockItemMatch(IItemFilterBlockItem blockItem, IItem item)

View File

@ -3,11 +3,15 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using Filtration.ItemFilterPreview.Model; using Filtration.ItemFilterPreview.Model;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.ObjectModel.BlockItemBaseTypes;
namespace Filtration.ItemFilterPreview.Services namespace Filtration.ItemFilterPreview.Services
{ {
internal class ItemFilterProcessor internal interface IItemFilterProcessor
{
IReadOnlyDictionary<IItem, IItemFilterBlock> ProcessItemsAgainstItemFilterScript(IItemFilterScript itemFilterScript, IEnumerable<IItem> items);
}
internal class ItemFilterProcessor : IItemFilterProcessor
{ {
private readonly IBlockItemMatcher _blockItemMatcher; private readonly IBlockItemMatcher _blockItemMatcher;
@ -18,6 +22,8 @@ namespace Filtration.ItemFilterPreview.Services
public IReadOnlyDictionary<IItem, IItemFilterBlock> ProcessItemsAgainstItemFilterScript(IItemFilterScript itemFilterScript, IEnumerable<IItem> items) public IReadOnlyDictionary<IItem, IItemFilterBlock> ProcessItemsAgainstItemFilterScript(IItemFilterScript itemFilterScript, IEnumerable<IItem> items)
{ {
var overallsw = Stopwatch.StartNew();
var matchedItemBlockPairs = new Dictionary<IItem, IItemFilterBlock>(); var matchedItemBlockPairs = new Dictionary<IItem, IItemFilterBlock>();
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
@ -25,13 +31,18 @@ namespace Filtration.ItemFilterPreview.Services
{ {
sw.Restart(); sw.Restart();
var matchedBlock = itemFilterScript.ItemFilterBlocks.FirstOrDefault(block => _blockItemMatcher.ItemBlockMatch(block, item)); var matchedBlock = itemFilterScript.ItemFilterBlocks
.Where(b => !(b is ItemFilterSection))
.FirstOrDefault(block => _blockItemMatcher.ItemBlockMatch(block, item));
matchedItemBlockPairs.Add(item, matchedBlock); matchedItemBlockPairs.Add(item, matchedBlock);
Debug.WriteLine("Processed Item in {0}ms", sw.ElapsedMilliseconds); Debug.WriteLine("Processed Item in {0}ms", sw.ElapsedMilliseconds);
} }
sw.Stop(); sw.Stop();
overallsw.Stop();
Debug.WriteLine("Total processing time: {0}ms", overallsw.ElapsedMilliseconds);
return matchedItemBlockPairs; return matchedItemBlockPairs;
} }
} }

View File

@ -0,0 +1,23 @@
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using Filtration.ItemFilterPreview.Services;
namespace Filtration.ItemFilterPreview.WindsorInstallers
{
public class ServicesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IBlockItemMatcher>()
.ImplementedBy<BlockItemMatcher>()
.LifeStyle.Singleton);
container.Register(
Component.For<IItemFilterProcessor>()
.ImplementedBy<ItemFilterProcessor>()
.LifeStyle.Singleton);
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="3.3.0" targetFramework="net461" />
<package id="Castle.Windsor" version="3.3.0" targetFramework="net461" />
</packages>

View File

@ -58,6 +58,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Repositories\TestItemFilterScriptRepository.cs" /> <Compile Include="Repositories\TestItemFilterScriptRepository.cs" />
<Compile Include="Services\TestHTTPService.cs" /> <Compile Include="Services\TestHTTPService.cs" />
<Compile Include="Services\TestItemFilterPersistenceService.cs" /> <Compile Include="Services\TestItemFilterPersistenceService.cs" />
@ -94,12 +99,16 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Resources\testscript.txt"> <EmbeddedResource Include="Properties\Resources.resx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Generator>ResXFileCodeGenerator</Generator>
</Content> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
<Content Include="Resources\ThioleItemFilter.txt"> </EmbeddedResource>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </ItemGroup>
</Content> <ItemGroup>
<None Include="Resources\ThioleItemFilter.txt" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\testscript.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -0,0 +1,120 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Filtration.Tests.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Filtration.Tests.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to # Item Filter Script created by Filtration v0.1 - www.github.com/XVar/filtration
///# Begin Script Description
///# This is a test script
///#
///# End Script Description
///
///# First test condition booyah
///Show
/// ItemLevel = 32
/// DropLevel &gt;= 85
/// Quality &gt;= 15
/// Sockets &lt; 4
/// LinkedSockets &gt;= 3
/// SetFontSize 12
///
///# Section: Gud stuff u shud pick up m9
///
///# Second test condition
///Show
/// ItemLevel &gt; 50
/// Quality &gt;= 15
/// Rarity &gt; Magic
/// Class &quot;Test Class 1&quot; &quot;Test Class 2&quot; &quot;Test Class [rest of string was truncated]&quot;;.
/// </summary>
internal static string testscript {
get {
return ResourceManager.GetString("testscript", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ###BETA VERSION 1.0.0.1-8
///#Please test and let me know via pm on reddit /u/brute_force or @Thiole in game if i am online
///
///#------------------------------------------------------------------
///#Fishing Rods First OFC
///Show
/// Class Fishing Rods
/// SetTextColor 0 0 0
/// SetBorderColor 0 0 0
/// SetBackgroundColor 255 255 255
///
///Show
/// Class &quot;Quest Items&quot;
///
///#####Shows better currency differently from lower currency for efficiency
///##### skill gems
///Show
/// Class &quot;Active Skill Gems&quot; &quot;Support Skil [rest of string was truncated]&quot;;.
/// </summary>
internal static string ThioleItemFilter {
get {
return ResourceManager.GetString("ThioleItemFilter", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="testscript" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\testscript.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="ThioleItemFilter" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ThioleItemFilter.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.ObjectModel.BlockItemTypes; using Filtration.ObjectModel.BlockItemTypes;
using Filtration.ObjectModel.Enums; using Filtration.ObjectModel.Enums;
@ -10,6 +11,7 @@ using Filtration.Properties;
using Filtration.Translators; using Filtration.Translators;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using Resources = Filtration.Tests.Properties.Resources;
namespace Filtration.Tests.Translators namespace Filtration.Tests.Translators
{ {
@ -25,12 +27,11 @@ namespace Filtration.Tests.Translators
Settings.Default.Reset(); Settings.Default.Reset();
} }
[Ignore("Need to fix file reading in NUnit 3.x")]
[Test] [Test]
public void TranslateStringToItemFilterScript_ReturnsScriptWithCorrectNumberOfBlocks() public void TranslateStringToItemFilterScript_ReturnsScriptWithCorrectNumberOfBlocks()
{ {
// Arrange // Arrange
var testInput = File.ReadAllText(@"Resources/testscript.txt"); var testInput = Resources.testscript;
_testUtility.MockItemFilterBlockTranslator.Setup(t => t.TranslateStringToItemFilterBlock(It.IsAny<string>(), It.IsAny<ThemeComponentCollection>())).Verifiable(); _testUtility.MockItemFilterBlockTranslator.Setup(t => t.TranslateStringToItemFilterBlock(It.IsAny<string>(), It.IsAny<ThemeComponentCollection>())).Verifiable();
@ -42,12 +43,11 @@ namespace Filtration.Tests.Translators
_testUtility.MockItemFilterBlockTranslator.Verify(); _testUtility.MockItemFilterBlockTranslator.Verify();
} }
[Ignore("Need to fix file reading in NUnit 3.x")]
[Test] [Test]
public void TranslateStringToItemFilterScript_ReturnsScriptWithDescriptionCorrectlySet() public void TranslateStringToItemFilterScript_ReturnsScriptWithDescriptionCorrectlySet()
{ {
// Arrange // Arrange
var testInput = File.ReadAllText(@"Resources/testscript.txt"); var testInput = Resources.testscript;
var expectedDescription = "Item Filter Script created by Filtration v0.1 - www.github.com/XVar/filtration" + Environment.NewLine + var expectedDescription = "Item Filter Script created by Filtration v0.1 - www.github.com/XVar/filtration" + Environment.NewLine +
"Begin Script Description" + Environment.NewLine + "Begin Script Description" + Environment.NewLine +
"This is a test script" + Environment.NewLine + "This is a test script" + Environment.NewLine +
@ -64,19 +64,18 @@ namespace Filtration.Tests.Translators
Assert.AreEqual(expectedDescription, script.Description); Assert.AreEqual(expectedDescription, script.Description);
} }
[Ignore("Integration Test / need to fix file reading for NUnit 3.x")]
[Test] [Test]
public void TranslateStringToItemFilterScript_ThioleItemFilterTest() public void TranslateStringToItemFilterScript_ThioleItemFilterTest()
{ {
// Arrange // Arrange
var testInput = File.ReadAllText(@"Resources/ThioleItemFilter.txt"); var testInput = Resources.ThioleItemFilter;
var blockTranslator = new ItemFilterBlockTranslator(_testUtility.MockBlockGroupHierarchyBuilder.Object); var blockTranslator = new ItemFilterBlockTranslator(_testUtility.MockBlockGroupHierarchyBuilder.Object);
var translator = new ItemFilterScriptTranslator(blockTranslator, var translator = new ItemFilterScriptTranslator(blockTranslator, _testUtility.MockBlockGroupHierarchyBuilder.Object);
_testUtility.MockBlockGroupHierarchyBuilder.Object);
// Act // Act
translator.TranslateStringToItemFilterScript(testInput); translator.TranslateStringToItemFilterScript(testInput);
// Assert // Assert
// Not crashing out when loading a huge script means this integration test has passed! // Not crashing out when loading a huge script means this integration test has passed!
} }

View File

@ -53,4 +53,5 @@ using System.Windows;
[assembly: AssemblyVersion("0.11.*")] [assembly: AssemblyVersion("0.11.*")]
[assembly: InternalsVisibleTo("Filtration.Tests")] [assembly: InternalsVisibleTo("Filtration.Tests")]
[assembly: InternalsVisibleTo("Filtration.ItemFilterPreview.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]