sharee.bike-App/TINKLib/Model/Connector/FilteredConnector.cs
2023-04-19 12:14:14 +02:00

123 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TINK.Model.Bikes;
using TINK.Model.Connector.Filter;
using TINK.Model.Services.CopriApi;
using TINK.Model.Stations;
using TINK.Model.Stations.StationNS;
using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
namespace TINK.Model.Connector
{
/// <summary> Filters connector responses.</summary>
/// <remarks>Former name: Filter</remarks>
public class FilteredConnector : IFilteredConnector
{
/// <summary> Constructs a filter object. </summary>
/// <param name="group">Filter group.</param>
/// <param name="connector">Connector object.</param>
public FilteredConnector(
IEnumerable<string> group,
IConnector connector)
{
Connector = connector;
if (Connector == null)
{
throw new ArgumentException("Can not construct filter object. Connector- and command objects must not be null.");
}
Query = new QueryProvider(Connector.Query, GroupFilterFactory.Create(group));
}
/// <summary> Inner connector object.</summary>
public IConnector Connector { get; }
/// <summary> Command object. </summary>
public ICommand Command => Connector.Command;
/// <summary> Object to query information. </summary>
public IQuery Query { get; }
/// <summary> True if connector has access to copri server, false if cached values are used. </summary>
public bool IsConnected => Connector.IsConnected;
/// <summary> Object to perform filtered queries.</summary>
private class QueryProvider : IQuery
{
/// <summary> Holds the filter. </summary>
private IGroupFilter Filter { get; }
/// <summary> Holds the reference to object which performs copri queries.</summary>
private IQuery m_oInnerQuery;
/// <summary> Constructs a query object.</summary>
/// <param name="innerQuerry"></param>
/// <param name="filter"></param>
public QueryProvider(IQuery innerQuerry, IGroupFilter filter)
{
m_oInnerQuery = innerQuerry;
Filter = filter;
}
/// <summary> Gets bikes either bikes available if no user is logged in or bikes available and bikes occupied if a user is logged in. </summary>
public async Task<Result<BikeCollection>> GetBikesAsync()
{
var result = await m_oInnerQuery.GetBikesAsync();
return new Result<BikeCollection>(
result.Source,
new BikeCollection(DoFilter(result.Response, Filter)),
result.GeneralData,
result.Exception);
}
/// <summary> Gets bikes occupied if a user is logged in. </summary>
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
{
var result = await m_oInnerQuery.GetBikesOccupiedAsync();
return new Result<BikeCollection>(
result.Source,
new BikeCollection(result.Response.ToDictionary(x => x.Id)),
result.GeneralData,
result.Exception);
}
/// <summary> Gets all station applying filter rules. </summary>
/// <returns></returns>
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
{
// Bikes and stations from COPRI or cache
var providerBikesAndStations = await m_oInnerQuery.GetBikesAndStationsAsync();
// Do filtering.
var filteredStationsDictionary = new StationDictionary(providerBikesAndStations.Response.StationsAll.CopriVersion, DoFilter(providerBikesAndStations.Response.StationsAll, Filter));
var filteredBikesDictionary = new BikeCollection(DoFilter(providerBikesAndStations.Response.Bikes, Filter));
var filteredBikesAndStations = new Result<StationsAndBikesContainer>(
providerBikesAndStations.Source,
new StationsAndBikesContainer(filteredStationsDictionary, filteredBikesDictionary),
providerBikesAndStations.GeneralData,
providerBikesAndStations.Exception);
return filteredBikesAndStations;
}
/// <summary> Filter bikes by group. </summary>
/// <param name="bikes">Bikes to filter.</param>
/// <returns>Filtered bikes.</returns>
private static Dictionary<string, BikeInfo> DoFilter(BikeCollection bikes, IGroupFilter filter)
{
return bikes.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id);
}
/// <summary> Filter stations by group. </summary>
/// <returns></returns>
private static Dictionary<string, IStation> DoFilter(StationDictionary stations, IGroupFilter filter)
{
return stations.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id);
}
}
}
}