feat: implement generic data set manipulator, ref: NOISSUE

This commit is contained in:
Simon Diesenreiter
2024-12-05 23:36:23 +01:00
parent 2ed103abbf
commit 85d94eca2f
14 changed files with 568 additions and 71 deletions

View 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;
}
}