mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-04-20 03:56:29 +02:00
Version 3.0.381
This commit is contained in:
parent
f963c0a219
commit
3a363acf3a
1525 changed files with 60589 additions and 125098 deletions
27
SharedBusinessLogic/Model/Connector/Query/Base.cs
Normal file
27
SharedBusinessLogic/Model/Connector/Query/Base.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using ShareeBike.Repository;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides information required for copri commands/ query operations.
|
||||
/// </summary>
|
||||
public class Base
|
||||
{
|
||||
/// <summary> Reference to object which provides access to copri server. </summary>
|
||||
protected ICopriServerBase CopriServer { get; }
|
||||
|
||||
/// <summary> Gets the merchant id.</summary>
|
||||
protected string MerchantId => CopriServer.MerchantId;
|
||||
|
||||
/// <summary> Constructs a query base object.</summary>
|
||||
/// <param name="p_oCopriServer">Server which implements communication.</param>
|
||||
/// <param name="p_oErrorStack">Object which hold communication objects.</param>
|
||||
protected Base(
|
||||
ICopriServerBase p_oCopriServer)
|
||||
{
|
||||
CopriServer = p_oCopriServer
|
||||
?? throw new ArgumentException("Can not instantiate command/ query base- object. Copri server object must never be null or emtpy.");
|
||||
}
|
||||
}
|
||||
}
|
39
SharedBusinessLogic/Model/Connector/Query/BaseLoggedIn.cs
Normal file
39
SharedBusinessLogic/Model/Connector/Query/BaseLoggedIn.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using ShareeBike.Repository;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
/// <summary>Holds user infromation required for copri related commands/ query operations. </summary>
|
||||
public class BaseLoggedIn : Base
|
||||
{
|
||||
/// <summary>Session cookie used to sign in to copri.</summary>
|
||||
public string SessionCookie { get; }
|
||||
|
||||
/// <summary> Mail address of the user. </summary>
|
||||
protected string Mail { get; }
|
||||
|
||||
/// <summary> Object which provides date time info. </summary>
|
||||
protected readonly Func<DateTime> DateTimeProvider;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="copriServer">Server which implements communication.</param>
|
||||
public BaseLoggedIn(ICopriServerBase copriServer,
|
||||
string sessionCookie,
|
||||
string mail,
|
||||
Func<DateTime> p_oDateTimeProvider) : base(copriServer)
|
||||
{
|
||||
if (string.IsNullOrEmpty(sessionCookie))
|
||||
throw new ArgumentException("Can not instantiate query object- object. Session cookie must never be null or emtpy.");
|
||||
|
||||
if (string.IsNullOrEmpty(mail))
|
||||
throw new ArgumentException("Can not instantiate query object- object. Mail address must never be null or emtpy.");
|
||||
|
||||
DateTimeProvider = p_oDateTimeProvider
|
||||
?? throw new ArgumentException("Can not instantiate connector- object. No date time provider object available.");
|
||||
|
||||
SessionCookie = sessionCookie;
|
||||
|
||||
Mail = mail;
|
||||
}
|
||||
}
|
||||
}
|
96
SharedBusinessLogic/Model/Connector/Query/CachedQuery.cs
Normal file
96
SharedBusinessLogic/Model/Connector/Query/CachedQuery.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
using ShareeBike.Model.Bikes;
|
||||
using ShareeBike.Model.Connector.Updater;
|
||||
using ShareeBike.Model.Services.CopriApi;
|
||||
using ShareeBike.Repository;
|
||||
using ShareeBike.Services.CopriApi;
|
||||
using BikeInfo = ShareeBike.Model.Bikes.BikeInfoNS.BC.BikeInfo;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
/// <summary> Provides query functionality for use without log in. </summary>
|
||||
public class CachedQuery : Base, IQuery
|
||||
{
|
||||
/// <summary> Cached copri server (connection to copri backed up by cache). </summary>
|
||||
private readonly ICachedCopriServer server;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="copriServer">Server which implements communication.</param>
|
||||
public CachedQuery(
|
||||
ICopriServerBase copriServer) : base(copriServer)
|
||||
{
|
||||
server = copriServer as ICachedCopriServer;
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected type. Type detected is {copriServer.GetType()}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including positions and bikes.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var resultStations = await server.GetStations();
|
||||
|
||||
if (resultStations.Source == typeof(CopriCallsMonkeyStore))
|
||||
{
|
||||
// Communication with copri in order to get stations failed.
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
new BikeCollection() /* There are no bikes occupied because user is not logged in. */),
|
||||
resultStations.GeneralData,
|
||||
resultStations.Exception);
|
||||
}
|
||||
|
||||
// Communication with copri succeeded.
|
||||
server.AddToCache(resultStations);
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
new BikeCollection()),
|
||||
resultStations.GeneralData);
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
|
||||
{
|
||||
Log.ForContext<CachedQuery>().Error("Unexpected call to get be bikes occupied detected. No user is logged in.");
|
||||
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
await Task.FromResult(new BikeCollection(new Dictionary<string, BikeInfo>())),
|
||||
new GeneralData(),
|
||||
new Exception("Abfrage der reservierten/ gebuchten Räder nicht möglich. Kein Benutzer angemeldet."));
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes available. </summary>
|
||||
/// <param name="operatorUri">Uri of the operator host to get bikes from or null if bikes have to be gotten form primary host.</param>
|
||||
/// <param name="stationId"> Id of station which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <param name="bikeId"> Id of bike which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync(Uri operatorUri = null, string stationId = null, string bikeId = null)
|
||||
{
|
||||
var result = await server.GetBikesAvailable(operatorUri: operatorUri, stationId: stationId, bikeId: bikeId);
|
||||
|
||||
if (result.Source != typeof(CopriCallsMonkeyStore))
|
||||
{
|
||||
server.AddToCache(result, operatorUri, stationId, bikeId);
|
||||
}
|
||||
|
||||
return new Result<BikeCollection>(
|
||||
result.Source,
|
||||
result.Response.GetBikesAvailable(result.Source == typeof(CopriCallsMonkeyStore)
|
||||
? Bikes.BikeInfoNS.BC.DataSource.Cache
|
||||
: Bikes.BikeInfoNS.BC.DataSource.Copri),
|
||||
result.GeneralData,
|
||||
result.Exception);
|
||||
}
|
||||
}
|
||||
}
|
212
SharedBusinessLogic/Model/Connector/Query/CachedQueryLoggedIn.cs
Normal file
212
SharedBusinessLogic/Model/Connector/Query/CachedQueryLoggedIn.cs
Normal file
|
@ -0,0 +1,212 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
using ShareeBike.Model.Bikes;
|
||||
using ShareeBike.Model.Connector.Updater;
|
||||
using ShareeBike.Model.Services.CopriApi;
|
||||
using ShareeBike.Repository;
|
||||
using ShareeBike.Repository.Response;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
/// <summary> Provides query functionality for a logged in user. </summary>
|
||||
public class CachedQueryLoggedIn : BaseLoggedIn, IQuery
|
||||
{
|
||||
/// <summary> Cached copri server (connection to copri backed up by cache). </summary>
|
||||
private ICachedCopriServer Server { get; }
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="copriServer">Server which implements communication.</param>
|
||||
public CachedQueryLoggedIn(ICopriServerBase copriServer,
|
||||
string sessionCookie,
|
||||
string mail,
|
||||
Func<DateTime> dateTimeProvider) : base(copriServer, sessionCookie, mail, dateTimeProvider)
|
||||
{
|
||||
Server = copriServer as ICachedCopriServer;
|
||||
if (Server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected type. Type detected is {copriServer.GetType()}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including positions.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
BikeCollection GetBikeCollection(IEnumerable<BikeInfoReservedOrBooked> bikeInfoEnumerable, Bikes.BikeInfoNS.BC.DataSource dataSource) =>
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
null, // Bikes available are no more of interest because count of available bikes at each given station is was added to station object.
|
||||
bikeInfoEnumerable ?? new Dictionary<string, BikeInfoReservedOrBooked>().Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
dataSource);
|
||||
|
||||
var stationsResponse = await Server.GetStations();
|
||||
|
||||
if (stationsResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| stationsResponse.Exception != null)
|
||||
{
|
||||
// Stations were read from cache ==> get bikes available and occupied from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
stationsResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
stationsResponse.Response.GetStationsAllMutable(),
|
||||
GetBikeCollection(stationsResponse.Response.bikes_occupied?.Values, Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
stationsResponse.GeneralData,
|
||||
stationsResponse.Exception);
|
||||
}
|
||||
|
||||
|
||||
// Both types bikes could read from copri => update cache
|
||||
Server.AddToCache(stationsResponse);
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
stationsResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
stationsResponse.Response.GetStationsAllMutable(),
|
||||
GetBikeCollection(stationsResponse.Response.bikes_occupied?.Values, Bikes.BikeInfoNS.BC.DataSource.Copri)),
|
||||
stationsResponse.GeneralData,
|
||||
stationsResponse?.Exception);
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
|
||||
{
|
||||
var bikesAvailableResponse = await Server.GetBikesAvailable(false);
|
||||
if (bikesAvailableResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesAvailableResponse.Exception != null)
|
||||
{
|
||||
// Bikes available were read from cache ==> get bikes occupied from cache as well to avoid inconsistencies.
|
||||
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes available read from cache. Reading bikes occupied from cache as well.");
|
||||
return new Result<BikeCollection>(
|
||||
bikesAvailableResponse.Source,
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse.Response?.bikes?.Values?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
|
||||
(await Server.GetBikesOccupied(true))?.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache),
|
||||
bikesAvailableResponse.GeneralData,
|
||||
bikesAvailableResponse.Exception);
|
||||
}
|
||||
|
||||
var bikesOccupiedResponse = await Server.GetBikesOccupied(false);
|
||||
if (bikesOccupiedResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesOccupiedResponse.Exception != null)
|
||||
{
|
||||
// Bikes occupied were read from cache ==> get bikes available from cache as well to avoid inconsistencies
|
||||
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes occupied read from cache. Reread bikes available from cache as well.");
|
||||
return new Result<BikeCollection>(
|
||||
bikesOccupiedResponse.Source,
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
(await Server.GetBikesAvailable(true)).Response?.bikes?.Values?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
|
||||
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache),
|
||||
bikesOccupiedResponse.GeneralData,
|
||||
bikesOccupiedResponse.Exception);
|
||||
}
|
||||
|
||||
// Both types bikes could read from copri => update bikes occupied cache.
|
||||
// // Do not add bikes available to cache because this might lead to conflicts calls GetBikesAsync() and bikes with FeedbackPending state are of no use offline.
|
||||
Server.AddToCache(bikesOccupiedResponse);
|
||||
|
||||
return new Result<BikeCollection>(
|
||||
bikesOccupiedResponse.Source,
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse?.Response.bikes?.Values?.Select(bike => bike)?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
|
||||
bikesOccupiedResponse?.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Copri),
|
||||
bikesOccupiedResponse.GeneralData,
|
||||
bikesOccupiedResponse.Exception);
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes available and bikes occupied. </summary>
|
||||
/// <param name="operatorUri">Uri of the operator host to get bikes from or null if bikes have to be gotten form primary host.</param>
|
||||
/// <param name="stationId"> Id of station which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <param name="bikeId"> Id of bike which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync(Uri operatorUri = null, string stationId = null, string bikeId = null)
|
||||
{
|
||||
var bikesAvailableResponse = await Server.GetBikesAvailable(operatorUri: operatorUri, stationId: stationId, bikeId: bikeId);
|
||||
|
||||
if (bikesAvailableResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesAvailableResponse.Exception != null)
|
||||
{
|
||||
// Bikes were read from cache.
|
||||
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes available and bikes occupied from cache invoking one single call.");
|
||||
return new Result<BikeCollection>(
|
||||
bikesAvailableResponse.Source,
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse.Response?.bikes?.Values,
|
||||
operatorUri?.AbsoluteUri == null ?
|
||||
(await Server.GetBikesOccupied(true)).Response?.bikes_occupied?.Values // Get bikes occupied from cache as well to avoid inconsistencies.
|
||||
: bikesAvailableResponse.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache),
|
||||
bikesAvailableResponse.GeneralData,
|
||||
bikesAvailableResponse.Exception);
|
||||
}
|
||||
|
||||
if (operatorUri?.AbsoluteUri != null)
|
||||
{
|
||||
// Both types bikes could read from copri successfully => update cache
|
||||
Server.AddToCache(bikesAvailableResponse, operatorUri, stationId, bikeId);
|
||||
|
||||
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes available and occupied read successfully from server invoking one single request.");
|
||||
return new Result<BikeCollection>(
|
||||
bikesAvailableResponse.Source,
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse.Response?.bikes?.Values,
|
||||
bikesAvailableResponse.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Copri),
|
||||
bikesAvailableResponse.GeneralData,
|
||||
bikesAvailableResponse.Exception != null ? new AggregateException(new[] { bikesAvailableResponse.Exception }) : null);
|
||||
}
|
||||
|
||||
/// Legacy implementation: GetBikesOccupied are not returned in <see cref="ICachedCopriServer.GetBikesAvailable"/> call.
|
||||
/// A separate call <see cref="ICachedCopriServer.GetBikesOccupied"/> is required to retrieve all bikes.
|
||||
var bikesOccupiedResponse = await Server.GetBikesOccupied(); /* Only query bikes occupied if operator uri is unknown. */
|
||||
if (bikesOccupiedResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesOccupiedResponse.Exception != null)
|
||||
{
|
||||
// Bikes occupied were read from cache ==> get bikes available from cache as well to avoid inconsistencies
|
||||
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes occupied read from cache. Reread bikes available from cache as well.");
|
||||
return new Result<BikeCollection>(
|
||||
bikesOccupiedResponse.Source,
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
(await Server.GetBikesAvailable(true, operatorUri, stationId, bikeId)).Response?.bikes?.Values,
|
||||
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache),
|
||||
bikesOccupiedResponse.GeneralData,
|
||||
bikesOccupiedResponse.Exception);
|
||||
}
|
||||
|
||||
// Both types bikes could read from copri => update cache
|
||||
Server.AddToCache(bikesAvailableResponse, operatorUri, stationId, bikeId);
|
||||
Server.AddToCache(bikesOccupiedResponse);
|
||||
|
||||
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes available and occupied read successfully from server.");
|
||||
return new Result<BikeCollection>(
|
||||
bikesAvailableResponse.Source,
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse.Response?.bikes?.Values,
|
||||
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Copri),
|
||||
bikesAvailableResponse.GeneralData,
|
||||
bikesAvailableResponse.Exception != null || bikesOccupiedResponse.Exception != null ? new AggregateException(new[] { bikesAvailableResponse.Exception, bikesOccupiedResponse.Exception }) : null);
|
||||
}
|
||||
}
|
||||
}
|
23
SharedBusinessLogic/Model/Connector/Query/IQuery.cs
Normal file
23
SharedBusinessLogic/Model/Connector/Query/IQuery.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using ShareeBike.Model.Bikes;
|
||||
using ShareeBike.Model.Services.CopriApi;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
public interface IQuery
|
||||
{
|
||||
/// <summary> Gets all stations including positions.</summary>
|
||||
Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync();
|
||||
|
||||
/// <summary> Gets bikes occupied is a user is logged in. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
Task<Result<BikeCollection>> GetBikesOccupiedAsync();
|
||||
|
||||
/// <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>
|
||||
/// <param name="operatorUri">Uri of the operator host to get bikes from or null if bikes have to be gotten form primary host.</param>
|
||||
/// <param name="stationId"> Id of station which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
Task<Result<BikeCollection>> GetBikesAsync(Uri operatorUri = null, string stationId = null, string bikeId = null);
|
||||
}
|
||||
}
|
72
SharedBusinessLogic/Model/Connector/Query/Query.cs
Normal file
72
SharedBusinessLogic/Model/Connector/Query/Query.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
using ShareeBike.Model.Bikes;
|
||||
using ShareeBike.Model.Connector.Updater;
|
||||
using ShareeBike.Model.Services.CopriApi;
|
||||
using ShareeBike.Repository;
|
||||
using ShareeBike.Services.CopriApi;
|
||||
using BikeInfo = ShareeBike.Model.Bikes.BikeInfoNS.BC.BikeInfo;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
/// <summary> Provides query functionality from cache without login. </summary>
|
||||
public class Query : Base, IQuery
|
||||
{
|
||||
/// <summary> Cached copri server. </summary>
|
||||
private readonly ICopriServer server;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="copriServer">Server which implements communication.</param>
|
||||
public Query(ICopriServerBase copriServer) : base(copriServer)
|
||||
{
|
||||
server = copriServer as ICopriServer;
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected type. Type detected is {copriServer.GetType()}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including positions.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var stationsAllResponse = await server.GetStationsAsync();
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
new StationsAndBikesContainer(
|
||||
stationsAllResponse.GetStationsAllMutable(),
|
||||
new BikeCollection() /* There are no bikes occupied because user is not logged in. */),
|
||||
stationsAllResponse.GetGeneralData());
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
|
||||
{
|
||||
Log.ForContext<Query>().Error("Unexpected call to get be bikes occupied detected. No user is logged in.");
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
await Task.FromResult(new BikeCollection(new Dictionary<string, BikeInfo>())),
|
||||
new GeneralData(),
|
||||
new Exception("Abfrage der reservierten/ gebuchten Räder fehlgeschlagen. Kein Benutzer angemeldet."));
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
/// <param name="operatorUri">Uri of the operator host to get bikes from or null if bikes have to be gotten form primary host.</param>
|
||||
/// <param name="stationId"> Id of station which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <param name="bikeId"> Id of bike which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <returns> Collection of bikes. </returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync(Uri operatorUri = null, string stationId = null, string bikeId = null)
|
||||
{
|
||||
var bikesAvailableResponse = await server.GetBikesAvailableAsync(operatorUri, stationId, bikeId);
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
bikesAvailableResponse != null
|
||||
? bikesAvailableResponse.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Cache)
|
||||
: await Task.FromResult(new BikeCollection(new Dictionary<string, BikeInfo>())),
|
||||
bikesAvailableResponse?.GetGeneralData());
|
||||
}
|
||||
}
|
||||
}
|
106
SharedBusinessLogic/Model/Connector/Query/QueryLoggedIn.cs
Normal file
106
SharedBusinessLogic/Model/Connector/Query/QueryLoggedIn.cs
Normal file
|
@ -0,0 +1,106 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ShareeBike.Model.Bikes;
|
||||
using ShareeBike.Model.Connector.Updater;
|
||||
using ShareeBike.Model.Services.CopriApi;
|
||||
using ShareeBike.Repository;
|
||||
using ShareeBike.Repository.Response;
|
||||
|
||||
namespace ShareeBike.Model.Connector
|
||||
{
|
||||
/// <summary> Provides query functionality from cache for a logged in user. </summary>
|
||||
public class QueryLoggedIn : BaseLoggedIn, IQuery
|
||||
{
|
||||
/// <summary> Copri server. </summary>
|
||||
private readonly ICopriServer server;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="copriServer">Server which implements communication.</param>
|
||||
public QueryLoggedIn(ICopriServerBase copriServer,
|
||||
string sessionCookie,
|
||||
string mail,
|
||||
Func<DateTime> dateTimeProvider) : base(copriServer, sessionCookie, mail, dateTimeProvider)
|
||||
{
|
||||
server = copriServer as ICopriServer;
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected type. Type detected is {copriServer.GetType()}.");
|
||||
}
|
||||
|
||||
server = copriServer as ICopriServer;
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including positions.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var stationResponse = await server.GetStationsAsync();
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
new StationsAndBikesContainer(
|
||||
stationResponse.GetStationsAllMutable(),
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
null, // Bikes available are no more of interest because count of available bikes at each given station is was added to station object.
|
||||
stationResponse.bikes_occupied?.Values ?? new Dictionary<string, BikeInfoReservedOrBooked>().Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
stationResponse.GetGeneralData());
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied and bikes for which feedback is required. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
|
||||
{
|
||||
var bikesFeedbackRequired = await server.GetBikesAvailableAsync();
|
||||
var bikesOccupiedResponse = await server.GetBikesOccupiedAsync();
|
||||
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesFeedbackRequired.bikes?.Values?.Select(bike => bike)?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
|
||||
bikesOccupiedResponse?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache),
|
||||
bikesOccupiedResponse.GetGeneralData());
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes available and bikes occupied. </summary>
|
||||
/// <param name="operatorUri">Uri of the operator host to get bikes from or null if bikes have to be gotten form primary host.</param>
|
||||
/// <param name="stationId"> Id of station which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <param name="bikeId"> Id of bike which is used for filtering bikes. Null if no filtering should be applied.</param>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync(Uri operatorUri = null, string stationId = null, string bikeId = null)
|
||||
{
|
||||
var bikesAvailableResponse = await server.GetBikesAvailableAsync(operatorUri, stationId, bikeId);
|
||||
|
||||
if (operatorUri?.AbsoluteUri != null)
|
||||
{
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse?.bikes?.Values,
|
||||
bikesAvailableResponse?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache),
|
||||
bikesAvailableResponse?.GetGeneralData());
|
||||
}
|
||||
|
||||
var bikesOccupiedResponse = await server.GetBikesOccupiedAsync();
|
||||
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse?.bikes?.Values,
|
||||
bikesOccupiedResponse?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache),
|
||||
bikesAvailableResponse?.GetGeneralData());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue