feat: implement generic data set manipulator, ref: NOISSUE
This commit is contained in:
141
TextParser/Data/DataSetManipulatorBase.cs
Normal file
141
TextParser/Data/DataSetManipulatorBase.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using Parsing.Data;
|
||||
|
||||
namespace Parsing.Data;
|
||||
|
||||
public class SearchResult<TIndexType>
|
||||
{
|
||||
public IDataIndex<TIndexType>? DataIndex { get; set; }
|
||||
}
|
||||
|
||||
public class DirectionalSearchResult<TIndexType> : SearchResult<TIndexType>
|
||||
{
|
||||
public Direction Direction { get; set; }
|
||||
public int Length { get; set; }
|
||||
}
|
||||
|
||||
public abstract class DataSetManipulatorBase<TCollectedType, TDataType, TIndexType> where TDataType : IEquatable<TDataType>
|
||||
{
|
||||
protected IDataSetIndexer<TDataType, TIndexType> indexer;
|
||||
|
||||
protected List<TCollectedType> dataSet;
|
||||
|
||||
public DataSetManipulatorBase(List<TCollectedType> dataSet, IDataSetIndexer<TDataType, TIndexType> indexer)
|
||||
{
|
||||
this.indexer = indexer;
|
||||
this.dataSet = dataSet;
|
||||
}
|
||||
|
||||
// we do not know how to iterate a specific data set exactly, the implementation has to take care of validating directional input
|
||||
protected abstract Direction ValidDirections();
|
||||
|
||||
protected void ValidateDirection(Direction d)
|
||||
{
|
||||
var allValidDirections = this.ValidDirections();
|
||||
var isValid = ((d | allValidDirections) == allValidDirections) && ((d & allValidDirections) > 0);
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
throw new ArgumentException("Invalid search direction provided for given data set!");
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Direction> SimplifyDirections(Direction d)
|
||||
{
|
||||
this.ValidateDirection(d);
|
||||
var allDirections = DirectionProvider.GetAllDirections();
|
||||
var singleDirections = new List<Direction>();
|
||||
|
||||
foreach (Direction direction in allDirections)
|
||||
{
|
||||
if ((direction & d) > 0)
|
||||
{
|
||||
singleDirections.Add(direction);
|
||||
}
|
||||
}
|
||||
|
||||
return singleDirections;
|
||||
}
|
||||
|
||||
public List<Direction> GetValidDirectionList(Direction d)
|
||||
{
|
||||
return SimplifyDirections(this.ValidDirections());
|
||||
}
|
||||
|
||||
// we do not know how to iterate a specific data set exactly, the implementation has to take care of ending traversal in any direction
|
||||
public abstract bool IsValidIndex(IDataIndex<TIndexType> queryPosition);
|
||||
|
||||
// we do not know how to iterate a specific data set exactly, the implementation has to take care of traversing the set
|
||||
public abstract IDataIndex<TIndexType> Move(IDataIndex<TIndexType> currentPosition, Direction direction);
|
||||
|
||||
public List<IDataIndex<TIndexType>> GetNeighborIndices(IDataIndex<TIndexType> currentPosition, Direction directions)
|
||||
{
|
||||
var singleDirections = this.SimplifyDirections(directions);
|
||||
var neighbors = new List<IDataIndex<TIndexType>>();
|
||||
|
||||
foreach (var direction in singleDirections)
|
||||
{
|
||||
var newPosition = this.Move(currentPosition, direction);
|
||||
if (this.IsValidIndex(newPosition))
|
||||
{
|
||||
neighbors.Add(newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
// we do not know how to iterate a specific data set exactly, but we only need to find specific items to be able to continue with any other algorithm
|
||||
public abstract List<SearchResult<TIndexType>> FindInSet(TDataType data);
|
||||
|
||||
public List<DirectionalSearchResult<TIndexType>> FindAtPosition(IDataIndex<TIndexType> currentPosition, List<TDataType> data)
|
||||
{
|
||||
return this.FindAtPosition(currentPosition, data, this.ValidDirections());
|
||||
}
|
||||
|
||||
public List<DirectionalSearchResult<TIndexType>> FindAtPosition(IDataIndex<TIndexType> currentPosition, List<TDataType> data, Direction directions)
|
||||
{
|
||||
var results = new List<DirectionalSearchResult<TIndexType>>();
|
||||
var givenDirections = this.SimplifyDirections(directions);
|
||||
if (EqualityComparer<TDataType>.Default.Equals(this.indexer.Get(this.dataSet, currentPosition), data[0]))
|
||||
{
|
||||
// found valid search start point, now validate each given direction
|
||||
foreach (var direction in givenDirections)
|
||||
{
|
||||
int searchIndex = 1;
|
||||
var searchPosition = this.Move(currentPosition, direction); ;
|
||||
while (searchIndex < data.Count && this.IsValidIndex(searchPosition)
|
||||
&& EqualityComparer<TDataType>.Default.Equals(this.indexer.Get(this.dataSet, searchPosition), data[searchIndex]))
|
||||
{
|
||||
searchPosition = this.Move(searchPosition, direction);
|
||||
searchIndex++;
|
||||
}
|
||||
if (searchIndex == data.Count)
|
||||
{
|
||||
var result = new DirectionalSearchResult<TIndexType>();
|
||||
result.DataIndex = currentPosition;
|
||||
result.Direction = direction;
|
||||
result.Length = searchIndex;
|
||||
results.Add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<DirectionalSearchResult<TIndexType>> FindInSet(List<TDataType> data)
|
||||
{
|
||||
var result = new List<DirectionalSearchResult<TIndexType>>();
|
||||
|
||||
// find valid starting points in set and perform search from there
|
||||
var startingPoints = this.FindInSet(data[0]);
|
||||
foreach (var startingPoint in startingPoints)
|
||||
{
|
||||
foreach (var results in this.FindAtPosition(startingPoint.DataIndex, data))
|
||||
{
|
||||
result.AddRange(results);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user