mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-06-22 05:47:28 +02:00
Version 3.0.364
This commit is contained in:
parent
91d42552c7
commit
0b9196a78d
91 changed files with 3452 additions and 555 deletions
|
@ -7,6 +7,7 @@ using TINK.Model.Connector.Filter;
|
|||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.Stations;
|
||||
using TINK.Model.Stations.StationNS;
|
||||
using TINK.Model.Stations.StationNS.Operator;
|
||||
using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
|
@ -92,11 +93,18 @@ namespace TINK.Model.Connector
|
|||
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 filteredStationsDictionary = new StationDictionary(
|
||||
providerBikesAndStations.Response.StationsAll.CopriVersion,
|
||||
DoFilter(providerBikesAndStations.Response.StationsAll, Filter));
|
||||
|
||||
var filteredBikesOccupiedDictionary = new BikeCollection(
|
||||
DoFilter(providerBikesAndStations.Response.BikesOccupied, Filter));
|
||||
|
||||
var filteredBikesAndStations = new Result<StationsAndBikesContainer>(
|
||||
providerBikesAndStations.Source,
|
||||
new StationsAndBikesContainer(filteredStationsDictionary, filteredBikesDictionary),
|
||||
new StationsAndBikesContainer(
|
||||
filteredStationsDictionary,
|
||||
filteredBikesOccupiedDictionary),
|
||||
providerBikesAndStations.GeneralData,
|
||||
providerBikesAndStations.Exception);
|
||||
|
||||
|
@ -106,17 +114,25 @@ namespace TINK.Model.Connector
|
|||
/// <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);
|
||||
}
|
||||
private static Dictionary<string, BikeInfo> DoFilter(BikeCollection bikes, IGroupFilter filter) =>
|
||||
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);
|
||||
}
|
||||
/// <summary> Filter stations by group and removes bike group collection entries which do not match group filter. </summary>
|
||||
/// <returns>Matching stations.</returns>
|
||||
private static Dictionary<string, IStation> DoFilter(StationDictionary stations, IGroupFilter filter) =>
|
||||
stations
|
||||
.Where(station => filter.DoFilter(station.Group).Count() > 0)
|
||||
.Select(station => new Station(
|
||||
station.Id,
|
||||
station.Group,
|
||||
station.Position,
|
||||
station.StationName,
|
||||
station.OperatorData,
|
||||
new BikeGroupCol(station.BikeGroups
|
||||
.Where(group => filter.DoFilter(new List<string> { group.Group }).Count() > 0))) as IStation)
|
||||
.ToDictionary(x => x.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,8 +86,11 @@ namespace TINK.Model.Connector
|
|||
return new Result<StationsAndBikesContainer>(
|
||||
result.Source,
|
||||
new StationsAndBikesContainer(
|
||||
new StationDictionary(result.Response.StationsAll.CopriVersion, result.Response.StationsAll.ToDictionary(x => x.Id)),
|
||||
new BikeCollection(result.Response.Bikes.ToDictionary(x => x.Id))),
|
||||
new StationDictionary(
|
||||
result.Response.StationsAll.CopriVersion,
|
||||
result.Response.StationsAll.ToDictionary(x => x.Id)),
|
||||
new BikeCollection(
|
||||
result.Response.BikesOccupied?.ToDictionary(x => x.Id) ?? new Dictionary<string, BikeInfo>())),
|
||||
result.GeneralData,
|
||||
result.Exception);
|
||||
}
|
||||
|
|
|
@ -41,31 +41,19 @@ namespace TINK.Model.Connector
|
|||
resultStations.Source,
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
(await server.GetBikesAvailable(true)).Response.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
new BikeCollection() /* There are no bikes occupied because user is not logged in. */),
|
||||
resultStations.GeneralData,
|
||||
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(Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
resultBikes.GeneralData,
|
||||
resultBikes.Exception);
|
||||
}
|
||||
|
||||
// Communicatin with copri succeeded.
|
||||
// Communication with copri succeeded.
|
||||
server.AddToCache(resultStations);
|
||||
server.AddToCache(resultBikes);
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
resultStations.Source,
|
||||
new StationsAndBikesContainer(resultStations.Response.GetStationsAllMutable(), resultBikes.Response.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Copri)),
|
||||
new StationsAndBikesContainer(
|
||||
resultStations.Response.GetStationsAllMutable(),
|
||||
new BikeCollection()),
|
||||
resultStations.GeneralData);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
@ -6,6 +7,7 @@ using TINK.Model.Bikes;
|
|||
using TINK.Model.Connector.Updater;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
@ -25,90 +27,47 @@ namespace TINK.Model.Connector
|
|||
Server = copriServer as ICachedCopriServer;
|
||||
if (Server == null)
|
||||
{
|
||||
throw new ArgumentException($"Copri server is not of expected typ. Type detected is {copriServer.GetType()}.");
|
||||
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 availbalbe and occupied from cache as well to avoid inconsistencies
|
||||
// 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(),
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
(await Server.GetBikesAvailable(true)).Response?.bikes?.Values,
|
||||
(await Server.GetBikesOccupied(true)).Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
GetBikeCollection(stationsResponse.Response.bikes_occupied?.Values, Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
stationsResponse.GeneralData,
|
||||
stationsResponse.Exception);
|
||||
}
|
||||
|
||||
var bikesAvailableResponse = await Server.GetBikesAvailable();
|
||||
if (bikesAvailableResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesAvailableResponse.Exception != null)
|
||||
{
|
||||
// Bikes avilable were read from cache ==> get bikes occupied from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
bikesAvailableResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
(await Server.GetStations(true)).Response.GetStationsAllMutable(),
|
||||
BikeCollectionFactory.GetBikesAll(bikesAvailableResponse.Response?.bikes?.Values,
|
||||
(await Server.GetBikesOccupied(true)).Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
bikesAvailableResponse.GeneralData,
|
||||
bikesAvailableResponse.Exception);
|
||||
}
|
||||
|
||||
var bikesOccupiedResponse = await Server.GetBikesOccupied();
|
||||
if (bikesOccupiedResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||
|| bikesOccupiedResponse.Exception != null)
|
||||
{
|
||||
// Bikes occupied were read from cache ==> get bikes available from cache as well to avoid inconsistencies
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
bikesOccupiedResponse.Source,
|
||||
new StationsAndBikesContainer(
|
||||
(await Server.GetStations(true)).Response.GetStationsAllMutable(),
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
(await Server.GetBikesAvailable(true)).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(stationsResponse);
|
||||
Server.AddToCache(bikesAvailableResponse);
|
||||
Server.AddToCache(bikesOccupiedResponse);
|
||||
|
||||
var exceptions = new[] { stationsResponse?.Exception, bikesAvailableResponse?.Exception, bikesOccupiedResponse?.Exception }.Where(x => x != null).ToArray();
|
||||
|
||||
var stationsMutable = stationsResponse.Response.GetStationsAllMutable();
|
||||
var bikesMutable = BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse.Response?.bikes?.Values,
|
||||
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
|
||||
Mail,
|
||||
DateTimeProvider,
|
||||
Bikes.BikeInfoNS.BC.DataSource.Copri);
|
||||
|
||||
return new Result<StationsAndBikesContainer>(
|
||||
stationsResponse.Source,
|
||||
new StationsAndBikesContainer(stationsMutable, bikesMutable),
|
||||
new StationsAndBikesContainer(
|
||||
stationsResponse.Response.GetStationsAllMutable(),
|
||||
GetBikeCollection(stationsResponse.Response.bikes_occupied?.Values, Bikes.BikeInfoNS.BC.DataSource.Copri)),
|
||||
stationsResponse.GeneralData,
|
||||
exceptions.Length > 0 ? new AggregateException(exceptions) : null);
|
||||
stationsResponse?.Exception);
|
||||
}
|
||||
|
||||
/// <summary> Gets bikes occupied. </summary>
|
||||
|
|
|
@ -32,11 +32,12 @@ namespace TINK.Model.Connector
|
|||
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(Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||
new StationsAndBikesContainer(
|
||||
stationsAllResponse.GetStationsAllMutable(),
|
||||
new BikeCollection() /* There are no bikes occupied because user is not logged in. */),
|
||||
stationsAllResponse.GetGeneralData());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bikes;
|
||||
using TINK.Model.Connector.Updater;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Repository;
|
||||
using TINK.Repository.Response;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
@ -34,16 +36,14 @@ namespace TINK.Model.Connector
|
|||
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(),
|
||||
BikeCollectionFactory.GetBikesAll(
|
||||
bikesAvailableResponse?.bikes?.Values,
|
||||
bikesOccupiedResponse?.bikes_occupied?.Values,
|
||||
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)),
|
||||
|
|
|
@ -7,9 +7,12 @@ using Serilog;
|
|||
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
|
||||
using TINK.Model.Services.CopriApi.ServerUris;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.Stations.StationNS;
|
||||
using TINK.Model.Stations.StationNS.Operator;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository.Response;
|
||||
using TINK.Repository.Response.Stations.Station;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace TINK.Model.Connector
|
||||
{
|
||||
|
@ -388,5 +391,52 @@ namespace TINK.Model.Connector
|
|||
/// <param name="bike">Bike get to state from.</param>
|
||||
public static bool GetIsFeedbackPending(this BikeInfoAvailable bike)
|
||||
=> bike.co2saving != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of bikes available at station.
|
||||
/// </summary>
|
||||
/// <param name="stationInfo">Object to get information from.</param>
|
||||
/// <returns>Count of bikes available or null if information is unknown.</returns>
|
||||
public static int? GetBikesAvailableCount(this StationInfo stationInfo)
|
||||
=> !string.IsNullOrWhiteSpace(stationInfo?.bike_count)
|
||||
&& int.TryParse(stationInfo?.bike_count, out int bikeCount)
|
||||
? bikeCount
|
||||
: (int?)null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets station object from response object.
|
||||
/// </summary>
|
||||
/// <param name="station">Response object to get station object from.</param>
|
||||
/// <returns>Station object.</returns>
|
||||
public static Station GetStation(this StationInfo station) =>
|
||||
new Station(
|
||||
station.station,
|
||||
station.GetGroup(),
|
||||
station.GetPosition(),
|
||||
station.description,
|
||||
new Data(station.operator_data?.operator_name,
|
||||
station.operator_data?.operator_phone,
|
||||
station.operator_data?.operator_hours,
|
||||
station.operator_data?.operator_email,
|
||||
!string.IsNullOrEmpty(station.operator_data?.operator_color)
|
||||
? Color.FromHex(station.operator_data?.operator_color)
|
||||
: (Color?)null),
|
||||
new BikeGroupCol(station.station_type?.Select(x => new BikeGroupCol.Entry(
|
||||
x.Key,
|
||||
int.TryParse(x.Value.bike_count, out int count) ? count : 0,
|
||||
x.Value.bike_group)) ?? new List<BikeGroupCol.Entry>()
|
||||
));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bike group object from response object.
|
||||
/// </summary>
|
||||
/// <param name="bikeGroup">Response object to get station from.</param>
|
||||
/// <param name="name">Name of the bike group.</param>
|
||||
/// <returns></returns>
|
||||
public static BikeGroupCol.Entry GetBikeGroup(this BikeGroup bikeGroup, string name) =>
|
||||
new BikeGroupCol.Entry(
|
||||
name,
|
||||
int.TryParse(bikeGroup?.bike_count ?? "0", out var countCity) ? countCity : 0,
|
||||
bikeGroup?.bike_group ?? string.Empty);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace TINK.Model.Connector.Updater
|
|||
/// <summary>
|
||||
/// Gets all station for station provider and add them into station list.
|
||||
/// </summary>
|
||||
/// <param name="p_oStationList">List of stations to update.</param>
|
||||
/// <param name="stationsAllResponse">List of stations to update.</param>
|
||||
public static StationDictionary GetStationsAllMutable(this StationsAvailableResponse stationsAllResponse)
|
||||
{
|
||||
// Get stations from Copri/ file/ memory, ....
|
||||
|
@ -43,7 +43,7 @@ namespace TINK.Model.Connector.Updater
|
|||
|
||||
Version.TryParse(stationsAllResponse.copri_version, out Version copriVersion);
|
||||
|
||||
var stations = new StationDictionary(p_oVersion: copriVersion);
|
||||
var stations = new StationDictionary(version: copriVersion);
|
||||
|
||||
foreach (var station in stationsAllResponse.stations)
|
||||
{
|
||||
|
@ -54,18 +54,7 @@ namespace TINK.Model.Connector.Updater
|
|||
string.Format("Station id {0} is not unique.", station.Value.station), stationsAllResponse);
|
||||
}
|
||||
|
||||
stations.Add(new Stations.StationNS.Station(
|
||||
station.Value.station,
|
||||
station.Value.GetGroup(),
|
||||
station.Value.GetPosition(),
|
||||
station.Value.description,
|
||||
new Data(station.Value.operator_data?.operator_name,
|
||||
station.Value.operator_data?.operator_phone,
|
||||
station.Value.operator_data?.operator_hours,
|
||||
station.Value.operator_data?.operator_email,
|
||||
!string.IsNullOrEmpty(station.Value.operator_data?.operator_color)
|
||||
? Color.FromHex(station.Value.operator_data?.operator_color)
|
||||
: (Color?)null)));
|
||||
stations.Add(station.Value.GetStation());
|
||||
}
|
||||
|
||||
return stations;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue