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

@ -69,10 +69,16 @@
</ItemGroup>
<ItemGroup>
<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\TestItemFilterProcessor.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
@ -84,6 +90,19 @@
<Project>{4aac3beb-1dc1-483e-9d11-0e9334e80227}</Project>
<Name>Filtration.ObjectModel</Name>
</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>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

@ -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);
}
}
}
}

@ -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

@ -1,10 +1,16 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Resources;
using System.Runtime.Versioning;
using Filtration.ItemFilterPreview.Model;
using Filtration.ItemFilterPreview.Services;
using Filtration.ItemFilterPreview.Tests.Properties;
using Filtration.ObjectModel;
using Filtration.ObjectModel.BlockItemBaseTypes;
using Filtration.ObjectModel.BlockItemTypes;
using Filtration.ObjectModel.Enums;
using Filtration.Translators;
using Moq;
using NUnit.Framework;
@ -25,19 +31,206 @@ namespace Filtration.ItemFilterPreview.Tests.Services
public void ProcessItemsAgainstItemFilterScript_Matches_ReturnsTrue()
{
//Arrange
var testInputItem = Mock.Of<IItem>(i => i.ItemClass == "Test Class");
var testInputBlockItem = new ActionBlockItem(BlockAction.Show);
var testInputBlock = Mock.Of<IItemFilterBlock>(b => b.Action == BlockAction.Show &&
b.BlockItems == new ObservableCollection<IItemFilterBlockItem> {testInputBlockItem});
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(true)
.Verifiable();
//Act
var result = _testUtility.ItemFilterProcessor.ProcessItemsAgainstItemFilterScript(testInputScript, new List<IItem> { testInputItem });
//Assert
_testUtility.MockBlockItemMatcher.Verify();
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
{
public ItemFilterProcessorTestUtility()

@ -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>

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

@ -36,6 +36,14 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<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.Data" />
<Reference Include="System.Xml" />
@ -63,6 +71,7 @@
<Compile Include="UserControls\ItemSocketsControl.xaml.cs">
<DependentUpon>ItemSocketsControl.xaml</DependentUpon>
</Compile>
<Compile Include="WindsorInstallers\ServicesInstaller.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -98,6 +107,7 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Filtration.ObjectModel;
using Filtration.ObjectModel.Enums;
@ -54,8 +55,8 @@ namespace Filtration.ItemFilterPreview.Model
}
var evenSocketCount = socketCount % 2 == 0;
var maxSocketGroups = evenSocketCount ? socketCount / 2 : socketCount - 1;
var maxLinkedSocketGroups = evenSocketCount ? maxSocketGroups : maxSocketGroups - 1;
var maxSocketGroups = Math.Max(1, evenSocketCount ? socketCount / 2 : socketCount - 1);
var maxLinkedSocketGroups = Math.Max(1, evenSocketCount ? maxSocketGroups : maxSocketGroups - 1);
if (value.Count > maxSocketGroups)
{
@ -69,7 +70,10 @@ namespace Filtration.ItemFilterPreview.Model
_socketGroups = value;
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;
}
}
}

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

@ -3,11 +3,15 @@ using System.Diagnostics;
using System.Linq;
using Filtration.ItemFilterPreview.Model;
using Filtration.ObjectModel;
using Filtration.ObjectModel.BlockItemBaseTypes;
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;
@ -18,6 +22,8 @@ namespace Filtration.ItemFilterPreview.Services
public IReadOnlyDictionary<IItem, IItemFilterBlock> ProcessItemsAgainstItemFilterScript(IItemFilterScript itemFilterScript, IEnumerable<IItem> items)
{
var overallsw = Stopwatch.StartNew();
var matchedItemBlockPairs = new Dictionary<IItem, IItemFilterBlock>();
var sw = Stopwatch.StartNew();
@ -25,13 +31,18 @@ namespace Filtration.ItemFilterPreview.Services
{
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);
Debug.WriteLine("Processed Item in {0}ms", sw.ElapsedMilliseconds);
}
sw.Stop();
overallsw.Stop();
Debug.WriteLine("Total processing time: {0}ms", overallsw.ElapsedMilliseconds);
return matchedItemBlockPairs;
}
}

@ -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);
}
}
}

@ -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>

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

@ -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);
}
}
}
}

@ -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>

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

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