mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-06-22 05:47:28 +02:00
Initial version.
This commit is contained in:
parent
193aaa1a56
commit
b72c67a53e
228 changed files with 25924 additions and 0 deletions
27
TINKLib/Model/Connector/Query/Base.cs
Normal file
27
TINKLib/Model/Connector/Query/Base.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using TINK.Model.Repository;
|
||||
|
||||
namespace TINK.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
TINKLib/Model/Connector/Query/BaseLoggedIn.cs
Normal file
39
TINKLib/Model/Connector/Query/BaseLoggedIn.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using TINK.Model.Repository;
|
||||
|
||||
namespace TINK.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="p_oCopriServer">Server which implements communication.</param>
|
||||
public BaseLoggedIn(ICopriServerBase p_oCopriServer,
|
||||
string p_strSessionCookie,
|
||||
string p_strMail,
|
||||
Func<DateTime> p_oDateTimeProvider) : base(p_oCopriServer)
|
||||
{
|
||||
if (string.IsNullOrEmpty(p_strSessionCookie))
|
||||
throw new ArgumentException("Can not instantiate query object- object. Session cookie must never be null or emtpy.");
|
||||
|
||||
if (string.IsNullOrEmpty(p_strMail))
|
||||
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 = p_strSessionCookie;
|
||||
|
||||
Mail = p_strMail;
|
||||
}
|
||||
}
|
||||
}
|
86
TINKLib/Model/Connector/Query/CachedQuery.cs
Normal file
86
TINKLib/Model/Connector/Query/CachedQuery.cs
Normal file
|
@ -0,0 +1,86 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using BikeInfo = TINK.Model.Bike.BC.BikeInfo;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
public class CachedQuery : Base, IQuery
|
||||
{
|
||||
/// <summary> Cached copri server. </summary>
|
||||
private readonly ICachedCopriServer server;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="p_oCopriServer">Server which implements communication.</param>
|
||||
public CachedQuery(
|
||||
ICopriServerBase p_oCopriServer) : base(p_oCopriServer)
|
||||
{
|
||||
server = p_oCopriServer as ICachedCopriServer;
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected typ. Type detected is {p_oCopriServer.GetType()}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including postions 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(),
|
||||
(await server.GetBikesAvailable(true)).Response.GetBikesAvailable()),
|
||||
resultStations.Exception);
|
||||
}
|
||||
|
||||
var resultBikes = await server.GetBikesAvailable();
|
||||
if (resultBikes.Source == typeof(CopriCallsMonkeyStore))
|
||||
{
|
||||
// Communication with copri in order to get bikes failed.
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultBikes.Source,
|
||||
new StationsAndBikesContainer(
|
||||
(await server.GetStations(true)).Response.GetStationsAllMutable(),
|
||||
resultBikes.Response.GetBikesAvailable()),
|
||||
resultBikes.Exception);
|
||||
}
|
||||
|
||||
// Communicatin with copri succeeded.
|
||||
server.AddToCache(resultStations);
|
||||
server.AddToCache(resultBikes);
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
new StationsAndBikesContainer(resultStations.Response.GetStationsAllMutable(), resultBikes.Response.GetBikesAvailable()));
|
||||
}
|
||||
|
||||
/// <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 occpied detected. No user is logged in.");
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
await Task.Run(() => new BikeCollection(new Dictionary<int, BikeInfo>())),
|
||||
new System.Exception("Abfrage der reservierten/ gebuchten Räder nicht möglich. Kein Benutzer angemeldet."));
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes available. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync()
|
||||
{
|
||||
var result = await server.GetBikesAvailable();
|
||||
server.AddToCache(result);
|
||||
return new Result<BikeCollection>(result.Source, result.Response.GetBikesAvailable(), result.Exception);
|
||||
}
|
||||
}
|
||||
}
|
159
TINKLib/Model/Connector/Query/CachedQueryLoggedIn.cs
Normal file
159
TINKLib/Model/Connector/Query/CachedQueryLoggedIn.cs
Normal file
|
@ -0,0 +1,159 @@
|
|||
using MonkeyCache.FileStore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
/// <summary> Provides query functionality for a logged in user. </summary>
|
||||
public class CachedQueryLoggedIn : BaseLoggedIn, IQuery
|
||||
{
|
||||
/// <summary> Cached copri server. </summary>
|
||||
private readonly ICachedCopriServer server;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="p_oCopriServer">Server which implements communication.</param>
|
||||
public CachedQueryLoggedIn(ICopriServerBase p_oCopriServer,
|
||||
string p_strSessionCookie,
|
||||
string p_strMail,
|
||||
Func<DateTime> p_oDateTimeProvider) : base(p_oCopriServer, p_strSessionCookie, p_strMail, p_oDateTimeProvider)
|
||||
{
|
||||
server = p_oCopriServer as ICachedCopriServer;
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected typ. Type detected is {p_oCopriServer.GetType()}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including postions.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var resultStations = await server.GetStations();
|
||||
|
||||
if (resultStations.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| resultStations.Exception != null)
|
||||
{
|
||||
// Stations were read from cache ==> get bikes availbalbe and occupied from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(
|
||||
(await server.GetBikesAvailable(true)).Response,
|
||||
(await server.GetBikesOccupied(true)).Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
resultStations.Exception);
|
||||
}
|
||||
|
||||
var l_oBikesAvailableResponse = await server.GetBikesAvailable();
|
||||
if (l_oBikesAvailableResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| l_oBikesAvailableResponse.Exception != null)
|
||||
{
|
||||
// Bikes avilable were read from cache ==> get bikes occupied from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
l_oBikesAvailableResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
(await server.GetStations(true)).Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(l_oBikesAvailableResponse.Response,
|
||||
(await server.GetBikesOccupied(true)).Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
l_oBikesAvailableResponse.Exception);
|
||||
}
|
||||
|
||||
var l_oBikesOccupiedResponse = await server.GetBikesOccupied();
|
||||
if (l_oBikesOccupiedResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| l_oBikesOccupiedResponse.Exception != null)
|
||||
{
|
||||
// Bikes occupied were read from cache ==> get bikes available from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
l_oBikesOccupiedResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
(await server.GetStations(true)).Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(
|
||||
(await server.GetBikesAvailable(true)).Response,
|
||||
l_oBikesOccupiedResponse.Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
l_oBikesOccupiedResponse.Exception);
|
||||
}
|
||||
|
||||
// Both types bikes could read from copri => update cache
|
||||
server.AddToCache(resultStations);
|
||||
server.AddToCache(l_oBikesAvailableResponse);
|
||||
server.AddToCache(l_oBikesOccupiedResponse);
|
||||
|
||||
var exceptions = new[] { resultStations?.Exception, l_oBikesAvailableResponse?.Exception, l_oBikesOccupiedResponse?.Exception }.Where(x => x != null).ToArray();
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(
|
||||
l_oBikesAvailableResponse.Response,
|
||||
l_oBikesOccupiedResponse.Response,
|
||||
Mail,
|
||||
DateTimeProvider)),
|
||||
exceptions.Length > 0 ? new AggregateException(exceptions) : null);
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
|
||||
{
|
||||
var result = await server.GetBikesOccupied();
|
||||
server.AddToCache(result);
|
||||
return new Result<BikeCollection>(result.Source, result.Response.GetBikesOccupied(Mail, DateTimeProvider), result.Exception);
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes available and bikes occupied. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync()
|
||||
{
|
||||
var l_oBikesAvailableResponse = await server.GetBikesAvailable();
|
||||
|
||||
if (l_oBikesAvailableResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| l_oBikesAvailableResponse.Exception != null)
|
||||
{
|
||||
// Bikes avilable were read from cache ==> get bikes occupied from cache as well to avoid inconsistencies
|
||||
return new Result<BikeCollection>(
|
||||
l_oBikesAvailableResponse.Source,
|
||||
UpdaterJSON.GetBikesAll(
|
||||
l_oBikesAvailableResponse.Response,
|
||||
(await server.GetBikesOccupied(true)).Response,
|
||||
Mail,
|
||||
DateTimeProvider),
|
||||
l_oBikesAvailableResponse.Exception);
|
||||
}
|
||||
|
||||
var l_oBikesOccupiedResponse = await server.GetBikesOccupied();
|
||||
if (l_oBikesOccupiedResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| l_oBikesOccupiedResponse.Exception != null)
|
||||
{
|
||||
// Bikes occupied were read from cache ==> get bikes available from cache as well to avoid inconsistencies
|
||||
return new Result<BikeCollection>(
|
||||
l_oBikesOccupiedResponse.Source,
|
||||
UpdaterJSON.GetBikesAll(
|
||||
(await server.GetBikesAvailable(true)).Response,
|
||||
l_oBikesOccupiedResponse.Response,
|
||||
Mail,
|
||||
DateTimeProvider),
|
||||
l_oBikesOccupiedResponse.Exception);
|
||||
|
||||
}
|
||||
|
||||
// Both types bikes could read from copri => update cache
|
||||
server.AddToCache(l_oBikesAvailableResponse);
|
||||
server.AddToCache(l_oBikesOccupiedResponse);
|
||||
|
||||
return new Result<BikeCollection>(
|
||||
l_oBikesAvailableResponse.Source,
|
||||
UpdaterJSON.GetBikesAll(l_oBikesAvailableResponse.Response, l_oBikesOccupiedResponse.Response, Mail, DateTimeProvider),
|
||||
l_oBikesAvailableResponse.Exception != null || l_oBikesOccupiedResponse.Exception != null ? new AggregateException(new[] { l_oBikesAvailableResponse.Exception, l_oBikesOccupiedResponse.Exception }) : null);
|
||||
}
|
||||
}
|
||||
}
|
20
TINKLib/Model/Connector/Query/IQuery.cs
Normal file
20
TINKLib/Model/Connector/Query/IQuery.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
public interface IQuery
|
||||
{
|
||||
/// <summary> Gets all stations including postions.</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>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
Task<Result<BikeCollection>> GetBikesAsync();
|
||||
}
|
||||
}
|
60
TINKLib/Model/Connector/Query/Query.cs
Normal file
60
TINKLib/Model/Connector/Query/Query.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
using BikeInfo = TINK.Model.Bike.BC.BikeInfo;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
/// <summary> Provides query functionality 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="p_oCopriServer">Server which implements communication.</param>
|
||||
public Query(ICopriServerBase p_oCopriServer) : base(p_oCopriServer)
|
||||
{
|
||||
server = p_oCopriServer as ICopriServer;
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected typ. Type detected is {p_oCopriServer.GetType()}.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including postions.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var stationsAllResponse = await server.GetStationsAsync();
|
||||
var bikesAvailableResponse = await server.GetBikesAvailableAsync();
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
new StationsAndBikesContainer( stationsAllResponse.GetStationsAllMutable(), bikesAvailableResponse.GetBikesAvailable()));
|
||||
}
|
||||
|
||||
/// <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 occpied detected. No user is logged in.");
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
await Task.Run(() => new BikeCollection(new Dictionary<int, BikeInfo>())),
|
||||
new System.Exception("Abfrage der reservierten/ gebuchten Räder fehlgeschlagen. Kein Benutzer angemeldet."));
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
/// <returns> Collection of bikes. </returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync()
|
||||
{
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
(await server.GetBikesAvailableAsync()).GetBikesAvailable());
|
||||
}
|
||||
}
|
||||
}
|
65
TINKLib/Model/Connector/Query/QueryLoggedIn.cs
Normal file
65
TINKLib/Model/Connector/Query/QueryLoggedIn.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Repository;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
/// <summary> Provides query functionality for a logged in user. </summary>
|
||||
public class QueryLoggedIn : BaseLoggedIn, IQuery
|
||||
{
|
||||
/// <summary> Cached copri server. </summary>
|
||||
private readonly ICopriServer server;
|
||||
|
||||
/// <summary>Constructs a copri query object.</summary>
|
||||
/// <param name="p_oCopriServer">Server which implements communication.</param>
|
||||
public QueryLoggedIn(ICopriServerBase p_oCopriServer,
|
||||
string p_strSessionCookie,
|
||||
string p_strMail,
|
||||
Func<DateTime> p_oDateTimeProvider) : base(p_oCopriServer, p_strSessionCookie, p_strMail, p_oDateTimeProvider)
|
||||
{
|
||||
server = p_oCopriServer as ICopriServer;
|
||||
if (server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected typ. Type detected is {p_oCopriServer.GetType()}.");
|
||||
}
|
||||
|
||||
server = p_oCopriServer as ICopriServer;
|
||||
}
|
||||
|
||||
/// <summary> Gets all stations including postions.</summary>
|
||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||
{
|
||||
var stationResponse = await server.GetStationsAsync();
|
||||
var bikesAvailableResponse = await server.GetBikesAvailableAsync();
|
||||
var bikesOccupiedResponse = await server.GetBikesOccupiedAsync();
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
new StationsAndBikesContainer(
|
||||
stationResponse.GetStationsAllMutable(),
|
||||
UpdaterJSON.GetBikesAll(bikesAvailableResponse, bikesOccupiedResponse, Mail, DateTimeProvider)));
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
|
||||
{
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
(await server.GetBikesOccupiedAsync()).GetBikesOccupied(Mail, DateTimeProvider));
|
||||
}
|
||||
/// <summary> Gets bikes available and bikes occupied. </summary>
|
||||
/// <returns>Collection of bikes.</returns>
|
||||
public async Task<Result<BikeCollection>> GetBikesAsync()
|
||||
{
|
||||
var l_oBikesAvailableResponse = await server.GetBikesAvailableAsync();
|
||||
var l_oBikesOccupiedResponse = await server.GetBikesOccupiedAsync();
|
||||
|
||||
return new Result<BikeCollection>(
|
||||
typeof(CopriCallsMonkeyStore),
|
||||
UpdaterJSON.GetBikesAll(l_oBikesAvailableResponse, l_oBikesOccupiedResponse, Mail, DateTimeProvider));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue