mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-04-19 03:27:29 +02:00
Version 3.0.364
This commit is contained in:
parent
91d42552c7
commit
0b9196a78d
91 changed files with 3452 additions and 555 deletions
|
@ -54,7 +54,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
|
|||
public enum DataSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Data source corpi.
|
||||
/// Data source copri.
|
||||
/// </summary>
|
||||
Copri,
|
||||
/// <summary>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace TINK.Model.Settings
|
|||
/// <returns>Logging level</returns>
|
||||
public static Uri GetCopriHostUri(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get uri of corpi server.
|
||||
// Get uri of copri server.
|
||||
if (!settingsJSON.TryGetValue(typeof(CopriServerUriList).ToString(), out string uriText)
|
||||
|| string.IsNullOrEmpty(uriText))
|
||||
{
|
||||
|
@ -381,7 +381,7 @@ namespace TINK.Model.Settings
|
|||
/// <returns>Active lock service name.</returns>
|
||||
public static string GetActiveLockService(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get uri of corpi server.
|
||||
// Get uri of copri server.
|
||||
if (!settingsJSON.TryGetValue(typeof(ILocksService).Name, out string activeLockService)
|
||||
|| string.IsNullOrEmpty(activeLockService))
|
||||
{
|
||||
|
@ -418,7 +418,7 @@ namespace TINK.Model.Settings
|
|||
/// <returns>Active lock service name.</returns>
|
||||
public static string GetActiveGeolocationService(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get uri of corpi server.
|
||||
// Get uri of copri server.
|
||||
if (!settingsJSON.TryGetValue(typeof(IGeolocationService).Name, out string activeGeolocationService)
|
||||
|| string.IsNullOrEmpty(activeGeolocationService))
|
||||
{
|
||||
|
|
|
@ -10,19 +10,27 @@ namespace TINK.Model.Stations
|
|||
/// <summary> Holds the list of stations. </summary>
|
||||
private readonly IDictionary<string, IStation> m_oStationDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a station by key.
|
||||
/// </summary>
|
||||
/// <param name="key">Key to get station.</param>
|
||||
/// <returns>Station for given key.</returns>
|
||||
public IStation this[string key] =>
|
||||
ContainsKey(key) ? m_oStationDictionary[key] : new NullStation();
|
||||
|
||||
/// <summary> Count of stations. </summary>
|
||||
public int Count { get { return m_oStationDictionary.Count; } }
|
||||
|
||||
public Version CopriVersion { get; }
|
||||
|
||||
/// <summary> Constructs a station dictionary object. </summary>
|
||||
/// <param name="p_oVersion">Version of copri- service.</param>
|
||||
public StationDictionary(Version p_oVersion = null, IDictionary<string, IStation> p_oStations = null)
|
||||
/// <param name="version">Version of copri- service.</param>
|
||||
public StationDictionary(Version version = null, IDictionary<string, IStation> stations = null)
|
||||
{
|
||||
m_oStationDictionary = p_oStations ?? new Dictionary<string, IStation>();
|
||||
m_oStationDictionary = stations ?? new Dictionary<string, IStation>();
|
||||
|
||||
CopriVersion = p_oVersion != null
|
||||
? new Version(p_oVersion.Major, p_oVersion.Minor, p_oVersion.Revision, p_oVersion.Build)
|
||||
CopriVersion = version != null
|
||||
? new Version(version.Major, version.Minor, version.Revision, version.Build)
|
||||
: new Version(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ using TINK.Model.Stations.StationNS.Operator;
|
|||
|
||||
namespace TINK.Model.Stations.StationNS
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds station information, i.e. static information like station name, station position and dynamic information like bikes available.
|
||||
/// </summary>
|
||||
public interface IStation
|
||||
{
|
||||
/// <summary> Holds the unique id of the station.c</summary>
|
||||
|
@ -19,5 +22,12 @@ namespace TINK.Model.Stations.StationNS
|
|||
|
||||
/// <summary> Holds operator related data.</summary>
|
||||
IData OperatorData { get; }
|
||||
|
||||
/// <summary> Gets the count of bikes available at station. </summary>
|
||||
int? AvailableBikesCount { get; }
|
||||
|
||||
/// <summary> Gets bike <see cref="BikeGroupCol.Entry"/> objects. </summary>
|
||||
/// <remarks> Each entry has a name, holds the count of available bikes at station and the group value. /// </remarks>
|
||||
IBikeGroupCol BikeGroups { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,5 +20,12 @@ namespace TINK.Model.Stations.StationNS
|
|||
|
||||
/// <summary> Holds operator related data.</summary>
|
||||
public IData OperatorData => new Data();
|
||||
|
||||
/// <summary> Gets the count of bikes available at station. </summary>
|
||||
public int? AvailableBikesCount => null;
|
||||
|
||||
/// <summary> Gets bike <see cref="BikeGroupCol.Entry"/> objects. </summary>
|
||||
/// <remarks> Each entry has a name, holds the count of available bikes at station and the group value. /// </remarks>
|
||||
public IBikeGroupCol BikeGroups => null;
|
||||
}
|
||||
}
|
||||
|
|
49
TINKLib/Model/Stations/StationNS/Operator/BikeGroupCol.cs
Normal file
49
TINKLib/Model/Stations/StationNS/Operator/BikeGroupCol.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace TINK.Model.Stations.StationNS.Operator
|
||||
{
|
||||
public class BikeGroupCol : List<BikeGroupCol.Entry> , IBikeGroupCol
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds a group of bikes at a station.
|
||||
/// </summary>
|
||||
public class Entry
|
||||
{
|
||||
/// <summary>
|
||||
/// Bike group entry.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the group, either "Citybikes" or "Cargobikes".</param>
|
||||
/// <param name="availableCount"></param>
|
||||
/// <param name="group"></param>
|
||||
public Entry(string name, int? availableCount = null, string group = null)
|
||||
{
|
||||
Name = name;
|
||||
AvailableCount = availableCount ?? 0;
|
||||
Group = group ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the group, either "Citybikes" or "Cargobikes".
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary> Holds the count of bikes available of given type at station. </summary>
|
||||
public int AvailableCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the group of the bikes. Konrad separates cargo and city bikes by group.
|
||||
/// </summary>
|
||||
public string Group { get; }
|
||||
}
|
||||
|
||||
public BikeGroupCol() : base() { }
|
||||
|
||||
public BikeGroupCol(IEnumerable<Entry> source) : base(source) { }
|
||||
|
||||
/// <summary> Holds the count of bikes available of any type at station. </summary>
|
||||
public int AvailableCount => this.Select(x => x.AvailableCount).Sum();
|
||||
|
||||
}
|
||||
}
|
10
TINKLib/Model/Stations/StationNS/Operator/IBikeGroupCol.cs
Normal file
10
TINKLib/Model/Stations/StationNS/Operator/IBikeGroupCol.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace TINK.Model.Stations.StationNS.Operator
|
||||
{
|
||||
public interface IBikeGroupCol : IEnumerable<BikeGroupCol.Entry>
|
||||
{
|
||||
/// <summary> Holds the count of bikes available of given type at station. </summary>
|
||||
int AvailableCount { get; }
|
||||
}
|
||||
}
|
|
@ -14,16 +14,18 @@ namespace TINK.Model.Stations.StationNS
|
|||
/// <param name="stationName">Name of the station.</param>
|
||||
public Station(
|
||||
string id,
|
||||
IEnumerable<string> group,
|
||||
IPosition position,
|
||||
IEnumerable<string> group = null,
|
||||
IPosition position = null,
|
||||
string stationName = "",
|
||||
Data operatorData = null)
|
||||
IData operatorData = null,
|
||||
IBikeGroupCol bikeGropCol = null)
|
||||
{
|
||||
Id = id;
|
||||
Group = group ?? throw new ArgumentException("Can not construct station object. Group of stations must not be null.");
|
||||
Position = position;
|
||||
StationName = stationName ?? string.Empty;
|
||||
OperatorData = operatorData ?? new Data();
|
||||
BikeGroups = bikeGropCol ?? new BikeGroupCol();
|
||||
}
|
||||
|
||||
/// <summary> Holds the unique id of the station.c</summary>
|
||||
|
@ -40,5 +42,12 @@ namespace TINK.Model.Stations.StationNS
|
|||
|
||||
/// <summary> Holds operator related info.</summary>
|
||||
public IData OperatorData { get; }
|
||||
|
||||
/// <summary> Gets the count of bikes available at station. </summary>
|
||||
public int? AvailableBikesCount => BikeGroups.AvailableCount;
|
||||
|
||||
/// <summary> Gets bike <see cref="BikeGroupCol.Entry"/> objects. </summary>
|
||||
/// <remarks> Each entry has a name, holds the count of available bikes at station and the group value. /// </remarks>
|
||||
public IBikeGroupCol BikeGroups { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ namespace TINK.Model
|
|||
/// <summary> Holds available app themes.</summary>
|
||||
public IServicesContainer<IGeolocationService> GeolocationServices { get; }
|
||||
|
||||
/// <summary> Holds the flavor of the app, i.e. specifies if app is sharee.bike, Mein konrad or Lastenrad Bayern.</summary>
|
||||
/// <summary> Holds the flavor of the app, i.e. specifies if app is sharee.bike, Mein konrad or LastenRad Bayern.</summary>
|
||||
public AppFlavor Flavor { get; private set; }
|
||||
|
||||
/// <summary> Manages the different types of LocksService objects.</summary>
|
||||
|
@ -418,7 +418,7 @@ namespace TINK.Model
|
|||
private LoggingLevelSwitch m_oLoggingLevelSwitch;
|
||||
|
||||
/// <summary>
|
||||
/// Object to allow swithing logging level
|
||||
/// Object to allow switching logging level
|
||||
/// </summary>
|
||||
public LoggingLevelSwitch Level
|
||||
{
|
||||
|
@ -448,7 +448,7 @@ namespace TINK.Model
|
|||
return;
|
||||
}
|
||||
|
||||
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing vialation occurs.
|
||||
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing violation occurs.
|
||||
|
||||
Level.MinimumLevel = minimumLevel;
|
||||
|
||||
|
@ -480,7 +480,7 @@ namespace TINK.Model
|
|||
var sourceContex = e.Properties[Constants.SourceContextPropertyName].ToString();
|
||||
|
||||
if ((e.Level == LogEventLevel.Information) &&
|
||||
(sourceContex.Contains(typeof(AppAndEnvironmentInfo).Namespace) /* Log App and enviroment info. */
|
||||
(sourceContex.Contains(typeof(AppAndEnvironmentInfo).Namespace) /* Log App and environment info. */
|
||||
|| sourceContex.Contains(typeof(ViewModel.Bikes.Bike.BluetoothLock.RequestHandler.Base).Namespace /* Log info-level messages to provide context for bluetooth log. */ )))
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -687,6 +687,11 @@ namespace TINK.Model
|
|||
AppResources.ChangeLog_3_0_363_MK_SB,
|
||||
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 364),
|
||||
AppResources.ChangeLog_MinorImprovements,
|
||||
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
|
||||
},
|
||||
};
|
||||
|
||||
/// <summary> Manges the whats new information.</summary>
|
||||
|
|
|
@ -1459,7 +1459,7 @@ namespace TINK.MultilingualResources {
|
|||
///1. close app,
|
||||
///2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
|
||||
///3. make sure that the lock is completely closed and remains closed.
|
||||
///4. send e-mail to operator (otherwise your chargeable rental will continue!): Problem description, Drop-off station..
|
||||
///4. send e-mail to operator (otherwise your chargeable rental will continue!): Please include problem description, bike-id and drop-off station..
|
||||
/// </summary>
|
||||
public static string ErrorBookedSearchMessageEscalationLevel2 {
|
||||
get {
|
||||
|
|
|
@ -761,7 +761,7 @@ Alternativ:
|
|||
1. App schließen,
|
||||
2. auf den Knopf oben am Schloss kurz drücken und sofort loslassen, sobald Knopf zu blinken beginnt,
|
||||
3. sicherstellen, dass das Schloss vollständig geschlossen ist und geschlossen bleibt.
|
||||
4. E-Mail an Betreiber schicken (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Problembeschreibung, Rad-ID, Abgabestation.</value>
|
||||
4. E-Mail an Betreiber schicken (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Bitte Problembeschreibung, Rad-ID und Abgabestation angeben.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_278" xml:space="preserve">
|
||||
<value>Hinweise hinzugefügt, um das Schließen des Schlosses zu erleichtern, falls dies nicht beim ersten Versuch gelingt.</value>
|
||||
|
@ -840,7 +840,7 @@ Activity Indicator zu Konto-Verwaltungsseiten hinzugefügt und Logging erweitert
|
|||
<value>Starte Miete beenden...</value>
|
||||
</data>
|
||||
<data name="ExceptionTextWebConnectFailureException" xml:space="preserve">
|
||||
<value>Ist WLAN/Mobilfunknetz vefügbar und mobile Daten aktiviert?</value>
|
||||
<value>Ist WLAN/Mobilfunknetz verfügbar und mobile Daten aktiviert?</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_289" xml:space="preserve">
|
||||
<value>Flyout-Menü Überschift verschönert.</value>
|
||||
|
|
|
@ -869,7 +869,7 @@ Alternative:
|
|||
1. close app,
|
||||
2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
|
||||
3. make sure that the lock is completely closed and remains closed.
|
||||
4. send e-mail to operator (otherwise your chargeable rental will continue!): Problem description, Drop-off station.</value>
|
||||
4. send e-mail to operator (otherwise your chargeable rental will continue!): Please include problem description, bike-id and drop-off station.</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_278" xml:space="preserve">
|
||||
<value>Hints added to ease closing of lock in case closing does not succeed on first try.</value>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
|
||||
<file datatype="xml" source-language="en-GB" target-language="de" original="TINKLIB/MULTILINGUALRESOURCES/APPRESOURCES.RESX" tool-id="MultilingualAppToolkit" product-name="n/a" product-version="n/a" build-num="n/a">
|
||||
<header>
|
||||
|
@ -1026,14 +1026,14 @@ Alternative:
|
|||
1. close app,
|
||||
2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
|
||||
3. make sure that the lock is completely closed and remains closed.
|
||||
4. send e-mail to operator (otherwise your chargeable rental will continue!): Problem description, Drop-off station.</source>
|
||||
4. send e-mail to operator (otherwise your chargeable rental will continue!): Please include problem description, bike-id and drop-off station.</source>
|
||||
<target state="translated">Es kann weiterhin keine Verbindung zwischen Ihrem mobilen Gerät und dem Schloss aufgebaut werden. Rufen Sie den Betreiber an!
|
||||
|
||||
Alternativ:
|
||||
1. App schließen,
|
||||
2. auf den Knopf oben am Schloss kurz drücken und sofort loslassen, sobald Knopf zu blinken beginnt,
|
||||
3. sicherstellen, dass das Schloss vollständig geschlossen ist und geschlossen bleibt.
|
||||
4. E-Mail an Betreiber schicken (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Problembeschreibung, Rad-ID, Abgabestation.</target>
|
||||
4. E-Mail an Betreiber schicken (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Bitte Problembeschreibung, Rad-ID und Abgabestation angeben.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_278" translate="yes" xml:space="preserve">
|
||||
<source>Hints added to ease closing of lock in case closing does not succeed on first try.</source>
|
||||
|
@ -1141,7 +1141,7 @@ Activity Indicator zu Konto-Verwaltungsseiten hinzugefügt und Logging erweitert
|
|||
</trans-unit>
|
||||
<trans-unit id="ExceptionTextWebConnectFailureException" translate="yes" xml:space="preserve">
|
||||
<source>Is WIFI/mobile network available and mobile data activated?</source>
|
||||
<target state="translated">Ist WLAN/Mobilfunknetz vefügbar und mobile Daten aktiviert?</target>
|
||||
<target state="translated">Ist WLAN/Mobilfunknetz verfügbar und mobile Daten aktiviert?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_289" translate="yes" xml:space="preserve">
|
||||
<source>Flyout menu header improved.</source>
|
||||
|
@ -1631,4 +1631,4 @@ Außerdem:<br/>
|
|||
</group>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
</xliff>
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using Serilog;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Repository.Response;
|
||||
|
@ -22,7 +22,7 @@ namespace TINK.Repository
|
|||
|
||||
public static Version UnsupportedVersionUpper => UNSUPPORTEDFUTURECOPRIVERSIONUPPER;
|
||||
|
||||
/// <summary> Deserializes reponse JSON if response is of supported version or provides default response otherwise. </summary>
|
||||
/// <summary> Deserializes response JSON if response is of supported version or provides default response otherwise. </summary>
|
||||
/// <typeparam name="T">Type of response object.</typeparam>
|
||||
/// <param name="response">Response JSON.</param>
|
||||
/// <param name="emptyResponseFactory">Factory providing default delegate.</param>
|
||||
|
|
|
@ -43,12 +43,12 @@ namespace TINK.Repository.Request
|
|||
|
||||
/// <summary> Gets reservation request (synonym: reservation == request == reservieren). </summary>
|
||||
/// <param name="bikeId">Id of the bike to reserve.</param>
|
||||
/// <returns>Requst to reserve bike.</returns>
|
||||
/// <returns>Request to reserve bike.</returns>
|
||||
string DoReserve(string bikeId);
|
||||
|
||||
/// <summary> Gets request to cancel reservation. </summary>
|
||||
/// <param name="bikeId">Id of the bike to cancel reservation for.</param>
|
||||
/// <returns>Requst on cancel booking request.</returns>
|
||||
/// <returns>Request on cancel booking request.</returns>
|
||||
string DoCancelReservation(string bikeId);
|
||||
|
||||
/// <summary> Request to get keys. </summary>
|
||||
|
@ -96,17 +96,17 @@ namespace TINK.Repository.Request
|
|||
/// <summary> Gets request for returning the bike. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="location">Geolocation of lock when returning bike.</param>
|
||||
/// <returns>Requst on returning request.</returns>
|
||||
/// <returns>Request on returning request.</returns>
|
||||
string DoReturn(string bikeId, LocationDto location);
|
||||
|
||||
/// <summary> Returns a bike and starts closing. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
/// <returns>Response to send to corpi.</returns>
|
||||
/// <returns>Response to send to copri.</returns>
|
||||
string ReturnAndStartClosing(string bikeId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets request for submiting feedback to copri server.
|
||||
/// Gets request for submitting feedback to copri server.
|
||||
/// </summary>
|
||||
/// <param name="bikeId">Id of the bike to which the feedback is related to.</param>
|
||||
/// <param name="currentChargeBars">Null if bike has no engine or charge is unknown. Otherwise the charge filling level of the drive battery.</param>
|
||||
|
@ -119,7 +119,7 @@ namespace TINK.Repository.Request
|
|||
bool isBikeBroken = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets request for submiting mini survey to copri server.
|
||||
/// Gets request for submitting mini survey to copri server.
|
||||
/// </summary>
|
||||
/// <param name="answers">Collection of answers.</param>
|
||||
string DoSubmitMiniSurvey(IDictionary<string, string> answers);
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace TINK.Repository.Request
|
|||
/// <summary> Returns a bike and starts closing. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
/// <returns>Response to send to corpi.</returns>
|
||||
/// <returns>Response to send to copri.</returns>
|
||||
public string ReturnAndStartClosing(string bikeId)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
|
@ -152,7 +152,7 @@ namespace TINK.Repository.Request
|
|||
=> throw new NotSupportedException();
|
||||
|
||||
/// <summary>
|
||||
/// Gets request for submiting mini survey to copri server.
|
||||
/// Gets request for submitting mini survey to copri server.
|
||||
/// </summary>
|
||||
/// <param name="answers">Collection of answers.</param>
|
||||
public string DoSubmitMiniSurvey(IDictionary<string, string> answers) =>
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace TINK.Repository.Request
|
|||
private ISmartDevice SmartDevice { get; }
|
||||
|
||||
/// <summary> Gets request to log user in. </summary>
|
||||
/// <param name="mailAddress">Mailaddress of user to log in.</param>
|
||||
/// <param name="mailAddress">Mail address of user to log in.</param>
|
||||
/// <param name="password">Password to log in.</param>
|
||||
/// <param name="deviceId">Id specifying user and hardware.</param>
|
||||
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
|
||||
|
@ -96,7 +96,7 @@ namespace TINK.Repository.Request
|
|||
/// <summary> Gets reservation request (synonym: reservation == request == reservieren). </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of the bike to reserve.</param>
|
||||
/// <returns>Requst to reserve bike.</returns>
|
||||
/// <returns>Request to reserve bike.</returns>
|
||||
public string DoReserve(string bikeId)
|
||||
=> "request=booking_request" +
|
||||
GetBikeIdParameter(bikeId) +
|
||||
|
@ -107,7 +107,7 @@ namespace TINK.Repository.Request
|
|||
/// <summary> Gets request to cancel reservation. </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of the bike to cancel reservation for.</param>
|
||||
/// <returns>Requst on cancel booking request.</returns>
|
||||
/// <returns>Request on cancel booking request.</returns>
|
||||
public string DoCancelReservation(string bikeId)
|
||||
=> "request=booking_cancel" +
|
||||
GetBikeIdParameter(bikeId) +
|
||||
|
@ -158,7 +158,7 @@ namespace TINK.Repository.Request
|
|||
UiIsoLanguageNameParameter;
|
||||
|
||||
|
||||
/// <summary> Gets booking request request (synonym: booking == renting == mieten). </summary>
|
||||
/// <summary> Gets booking request (synonym: booking == renting == mieten). </summary>
|
||||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of the bike to book.</param>
|
||||
/// <param name="guid">Used to publish GUID from app to copri. Used for initial setup of bike in copri.</param>
|
||||
|
@ -202,7 +202,7 @@ namespace TINK.Repository.Request
|
|||
/// <remarks> Operator specific call.</remarks>
|
||||
/// <param name="bikeId">Id of bike to return.</param>
|
||||
/// <param name="geolocation">Geolocation of lock when returning bike.</param>
|
||||
/// <returns>Requst on returning request.</returns>
|
||||
/// <returns>Request on returning request.</returns>
|
||||
public string DoReturn(string bikeId, LocationDto geolocation)
|
||||
=> "request=booking_update" +
|
||||
GetBikeIdParameter(bikeId) +
|
||||
|
@ -218,7 +218,7 @@ namespace TINK.Repository.Request
|
|||
/// <summary> Returns a bike and starts closing. </summary>
|
||||
/// <param name="bikeId">Id of the bike to return.</param>
|
||||
/// <param name="smartDevice">Provides info about hard and software.</param>
|
||||
/// <returns>Response to send to corpi.</returns>
|
||||
/// <returns>Response to send to copri.</returns>
|
||||
public string ReturnAndStartClosing(string bikeId)
|
||||
=> "request=booking_update" +
|
||||
GetBikeIdParameter(bikeId) +
|
||||
|
@ -258,7 +258,7 @@ namespace TINK.Repository.Request
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets request for submiting mini survey to copri server.
|
||||
/// Gets request for submitting mini survey to copri server.
|
||||
/// </summary>
|
||||
/// <param name="answers">Collection of answers.</param>
|
||||
public string DoSubmitMiniSurvey(IDictionary<string, string> answers)
|
||||
|
@ -313,7 +313,7 @@ namespace TINK.Repository.Request
|
|||
|
||||
/// <summary> Gets the geolocation parameter. </summary>
|
||||
/// <param name="geolocation">Geolocation or null.</param>
|
||||
/// <returns>Empty string if geoloction is null otherwise parmeter including latitude, longitude and age in a format which is urlencode invariant.</returns>
|
||||
/// <returns>Empty string if geolocation is null otherwise parameter including latitude, longitude and age in a format which is urlencode invariant.</returns>
|
||||
private static string GetLocationParameters(LocationDto geolocation)
|
||||
{
|
||||
if (geolocation == null)
|
||||
|
|
21
TINKLib/Repository/Response/Stations/Station/BikeGroup.cs
Normal file
21
TINKLib/Repository/Response/Stations/Station/BikeGroup.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Repository.Response.Stations.Station
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds a single bike group.
|
||||
/// </summary>
|
||||
[DataContract]
|
||||
public class BikeGroup
|
||||
{
|
||||
/// <summary> Holds the count of bikes for the group. </summary>
|
||||
[DataMember]
|
||||
public string bike_count { get; private set;}
|
||||
|
||||
/// <summary>
|
||||
/// Holds the group identifying the bike group type.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string bike_group { get; private set; }
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Repository.Response.Stations.Station
|
||||
|
@ -28,5 +29,17 @@ namespace TINK.Repository.Response.Stations.Station
|
|||
|
||||
[DataMember]
|
||||
public OperatorData operator_data { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the count of available bikes at the station.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public string bike_count { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the count type of station, i.e. which bikes are located at station.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public Dictionary<string, BikeGroup> station_type { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,5 +15,11 @@ namespace TINK.Repository.Response.Stations
|
|||
/// </summary>
|
||||
[DataMember]
|
||||
public Dictionary<string, StationInfo> stations { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary of bikes reserved (requested) and rented (occupied) by current user if user is logged in and has reserved or rented bikes.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public Dictionary<string, BikeInfoReservedOrBooked> bikes_occupied { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace TINK.Services.CopriApi
|
|||
}
|
||||
|
||||
/// <summary> Opens lock.</summary>
|
||||
/// <param name="corpiServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="cachedServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="bike">Bike object holding id of bike to open. Lock state of object is updated after open request.</param>
|
||||
public static async Task OpenAync(
|
||||
this ICachedCopriServer cachedServer,
|
||||
|
@ -70,11 +70,11 @@ namespace TINK.Services.CopriApi
|
|||
/// <summary>
|
||||
/// Books a bike and opens the lock.
|
||||
/// </summary>
|
||||
/// <param name="corpiServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="copriServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="bike">Bike to book and open.</param>
|
||||
/// <param name="mailAddress">Mail address of user which books bike.</param>
|
||||
public static async Task BookAndOpenAync(
|
||||
this ICopriServerBase corpiServer,
|
||||
this ICopriServerBase copriServer,
|
||||
IBikeInfoMutable bike,
|
||||
string mailAddress)
|
||||
{
|
||||
|
@ -83,13 +83,13 @@ namespace TINK.Services.CopriApi
|
|||
throw new ArgumentNullException(nameof(bike), "Can not book bike and open lock. No bike object available.");
|
||||
}
|
||||
|
||||
if (!(corpiServer is ICachedCopriServer cachedServer))
|
||||
throw new ArgumentNullException(nameof(corpiServer));
|
||||
if (!(copriServer is ICachedCopriServer cachedServer))
|
||||
throw new ArgumentNullException(nameof(copriServer));
|
||||
|
||||
// Send command to open lock
|
||||
var response = bike.State.Value == Model.State.InUseStateEnum.Disposable
|
||||
? (await corpiServer.BookAvailableAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id)
|
||||
: (await corpiServer.BookReservedAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id);
|
||||
? (await copriServer.BookAvailableAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id)
|
||||
: (await copriServer.BookReservedAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id);
|
||||
|
||||
// Upated locking state.
|
||||
var lockingState = await cachedServer.GetOccupiedBikeLockStateAsync(bike.Id);
|
||||
|
@ -128,17 +128,17 @@ namespace TINK.Services.CopriApi
|
|||
/// <summary>
|
||||
/// Returns a bike and closes the lock.
|
||||
/// </summary>
|
||||
/// <param name="corpiServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="copriServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="bike">Bike to close.</param>
|
||||
public static async Task CloseAync(
|
||||
this ICopriServerBase corpiServer,
|
||||
this ICopriServerBase copriServer,
|
||||
IBikeInfoMutable bike)
|
||||
{
|
||||
if (!(corpiServer is ICachedCopriServer cachedServer))
|
||||
throw new ArgumentNullException(nameof(corpiServer));
|
||||
if (!(copriServer is ICachedCopriServer cachedServer))
|
||||
throw new ArgumentNullException(nameof(copriServer));
|
||||
|
||||
// Send command to close lock
|
||||
await corpiServer.UpdateLockingStateAsync(
|
||||
await copriServer.UpdateLockingStateAsync(
|
||||
bike.Id,
|
||||
Repository.Request.lock_state.locking,
|
||||
bike.OperatorUri);
|
||||
|
@ -166,20 +166,20 @@ namespace TINK.Services.CopriApi
|
|||
/// <summary>
|
||||
/// Returns a bike and closes the lock.
|
||||
/// </summary>
|
||||
/// <param name="corpiServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="copriServer"> Instance to communicate with backend.</param>
|
||||
/// <param name="smartDevice">Smart device on which app runs on.</param>
|
||||
/// <param name="mailAddress">Mail address of user which books bike.</param>
|
||||
public static async Task<BookingFinishedModel> ReturnAndCloseAync(
|
||||
this ICopriServerBase corpiServer,
|
||||
this ICopriServerBase copriServer,
|
||||
ISmartDevice smartDevice,
|
||||
IBikeInfoMutable bike)
|
||||
{
|
||||
if (!(corpiServer is ICachedCopriServer cachedServer))
|
||||
throw new ArgumentNullException(nameof(corpiServer));
|
||||
if (!(copriServer is ICachedCopriServer cachedServer))
|
||||
throw new ArgumentNullException(nameof(copriServer));
|
||||
|
||||
// Send command to open lock
|
||||
DoReturnResponse response =
|
||||
await corpiServer.ReturnAndStartClosingAsync(bike.Id, bike.OperatorUri);
|
||||
await copriServer.ReturnAndStartClosingAsync(bike.Id, bike.OperatorUri);
|
||||
|
||||
// Upate booking state
|
||||
bike.Load(Model.Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None);
|
||||
|
@ -209,21 +209,21 @@ namespace TINK.Services.CopriApi
|
|||
/// <summary>
|
||||
/// Queries the locking state from copri.
|
||||
/// </summary>
|
||||
/// <param name="corpiServer">Service to use.</param>
|
||||
/// <param name="copriServer">Service to use.</param>
|
||||
/// <param name="bikeId">Bike id to query lock state for.</param>
|
||||
/// <returns>Locking state</returns>
|
||||
private static async Task<LockingState> GetLockStateAsync(
|
||||
this ICachedCopriServer corpiServer,
|
||||
this ICachedCopriServer copriServer,
|
||||
string bikeId)
|
||||
{
|
||||
// Querry reserved or booked bikes first for performance reasons.
|
||||
var bikeReservedOrBooked = (await corpiServer.GetBikesOccupied(false))?.Response.bikes_occupied?.Values?.FirstOrDefault(x => x.bike == bikeId);
|
||||
var bikeReservedOrBooked = (await copriServer.GetBikesOccupied(false))?.Response.bikes_occupied?.Values?.FirstOrDefault(x => x.bike == bikeId);
|
||||
if (bikeReservedOrBooked != null)
|
||||
{
|
||||
return bikeReservedOrBooked.GetCopriLockingState();
|
||||
}
|
||||
|
||||
var bikeAvailable = (await corpiServer.GetBikesAvailable(false))?.Response.bikes?.Values?.FirstOrDefault(x => x.bike == bikeId);
|
||||
var bikeAvailable = (await copriServer.GetBikesAvailable(false))?.Response.bikes?.Values?.FirstOrDefault(x => x.bike == bikeId);
|
||||
if (bikeAvailable != null)
|
||||
{
|
||||
return bikeAvailable.GetCopriLockingState();
|
||||
|
@ -235,14 +235,14 @@ namespace TINK.Services.CopriApi
|
|||
/// <summary>
|
||||
/// Queries the locking state of a occupied bike from copri.
|
||||
/// </summary>
|
||||
/// <param name="corpiServer">Service to use.</param>
|
||||
/// <param name="copriServer">Service to use.</param>
|
||||
/// <param name="bikeId">Bike id to query lock state for.</param>
|
||||
/// <returns>Locking state if bike is still occupied, null otherwise.</returns>
|
||||
private static async Task<LockingState?> GetOccupiedBikeLockStateAsync(
|
||||
this ICachedCopriServer corpiServer,
|
||||
this ICachedCopriServer copriServer,
|
||||
string bikeId)
|
||||
{
|
||||
var bikeReservedOrBooked = (await corpiServer.GetBikesOccupied(false))?.Response.bikes_occupied?.Values?.FirstOrDefault(x => x.bike == bikeId);
|
||||
var bikeReservedOrBooked = (await copriServer.GetBikesOccupied(false))?.Response.bikes_occupied?.Values?.FirstOrDefault(x => x.bike == bikeId);
|
||||
if (bikeReservedOrBooked != null)
|
||||
{
|
||||
return bikeReservedOrBooked.GetCopriLockingState();
|
||||
|
|
|
@ -3,15 +3,37 @@ using TINK.Model.Stations;
|
|||
|
||||
namespace TINK.Model.Services.CopriApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds stations and bikes.
|
||||
/// </summary>
|
||||
public class StationsAndBikesContainer
|
||||
{
|
||||
public StationsAndBikesContainer(StationDictionary stations, BikeCollection bikes)
|
||||
/// <summary>
|
||||
/// Holds station and bikes.
|
||||
/// </summary>
|
||||
/// <param name="stations">Stations information which contains some information about bikes available at each station (bike count, ...).</param>
|
||||
/// <param name="bikesOccupied"></param>
|
||||
public StationsAndBikesContainer(StationDictionary stations, BikeCollection bikesOccupied)
|
||||
{
|
||||
StationsAll = stations;
|
||||
Bikes = bikes;
|
||||
BikesOccupied = bikesOccupied;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds all stations.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Since copri version writing <see cref="StationType"/> (>= 4.1.23.03) stations contain bikes available information.
|
||||
/// Prior to this copri version bikes available were part of <see cref="BikesOccupied"/>
|
||||
/// </remarks>
|
||||
public StationDictionary StationsAll { get; }
|
||||
|
||||
public BikeCollection Bikes { get; }
|
||||
/// <summary>
|
||||
/// Holds bikes occupied (i.e. bike reserved or booked).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Up to copri version writing <see cref="StationType"/> (>= 4.1.23.03) bike available were contained beside bikes occupied.
|
||||
/// </remarks>
|
||||
public BikeCollection BikesOccupied { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,4 +84,7 @@
|
|||
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="TestShareeLib" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -101,7 +101,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
}
|
||||
|
||||
// Notify corpi about unlock action in order to start booking.
|
||||
// Notify copri about unlock action in order to start booking.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextRentingBike;
|
||||
IsConnected = IsConnectedDelegate();
|
||||
try
|
||||
|
|
|
@ -204,7 +204,7 @@ namespace TINK.ViewModel.Contact
|
|||
? $"{stationId}" // there is a station marker with index letter for given station id
|
||||
: "Open"; // there is no station marker. Use open marker.
|
||||
|
||||
var colorPartPrefix = GetRessourceNameColorPart(stationsColorList[pinIndex]);
|
||||
var colorPartPrefix = GetResourceNameColorPart(stationsColorList[pinIndex]);
|
||||
|
||||
var l_iName = $"{indexPartPrefix.ToString().PadLeft(2, '0')}_{colorPartPrefix}{(DeviceInfo.Platform == DevicePlatform.Android ? ".png" : string.Empty)}";
|
||||
try
|
||||
|
@ -234,7 +234,7 @@ namespace TINK.ViewModel.Contact
|
|||
/// <summary> Gets the color related part of the ressrouce name.</summary>
|
||||
/// <param name="color">Color to get name for.</param>
|
||||
/// <returns>Resource name.</returns>
|
||||
private static string GetRessourceNameColorPart(Color color)
|
||||
private static string GetResourceNameColorPart(Color color)
|
||||
{
|
||||
if (color == Color.Blue)
|
||||
{
|
||||
|
@ -395,7 +395,7 @@ namespace TINK.ViewModel.Contact
|
|||
|
||||
var colors = GetStationColors(
|
||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
||||
resultStationsAndBikes.Response.Bikes);
|
||||
resultStationsAndBikes.Response.BikesOccupied);
|
||||
|
||||
// Update pins color form count of bikes located at station.
|
||||
UpdatePinsColor(colors);
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace TINK.ViewModel.Contact
|
|||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
|
||||
/// <summary> Holds value wether site caching is on or off.</summary>
|
||||
/// <summary> Holds value whether site caching is on or off.</summary>
|
||||
bool IsSiteCachingOn { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -64,7 +64,7 @@ namespace TINK.ViewModel.Contact
|
|||
|
||||
/// <summary> Constructs view model.</summary>
|
||||
/// <param name="isSiteCachingOn">Set of user permissions</param>
|
||||
/// <param name="resourceProvider">Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
/// <param name="resourceProvider">Delegate to get embedded html resource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
/// <param name="query">Object to query resources path values if required.</param>
|
||||
public FeesAndBikesPageViewModel(
|
||||
string hostName,
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace TINK.ViewModel.Info
|
|||
/// <summary> Holds the name of the host.</summary>
|
||||
private string HostName { get; }
|
||||
|
||||
/// <summary> Holds value wether site caching is on or off.</summary>
|
||||
/// <summary> Holds value whether site caching is on or off.</summary>
|
||||
bool IsSiteCachingOn { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -74,11 +74,11 @@ namespace TINK.ViewModel.Info
|
|||
|
||||
/// <summary> Constructs Info view model</summary>
|
||||
/// <param name="hostName">Name of the host to get html resources from.</param>
|
||||
/// <param name="isSiteCachingOn">Holds value wether site caching is on or off.</param>
|
||||
/// <param name="agbResourcePath"> Agb resouce path received from backend.</param>
|
||||
/// <param name="privacyResourcePath"> Privacy resouce path received from backend.</param>
|
||||
/// <param name="impressResourcePath"> Impress resouce path received from backend.</param>
|
||||
/// <param name="resourceProvider">Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
/// <param name="isSiteCachingOn">Holds value whether site caching is on or off.</param>
|
||||
/// <param name="agbResourcePath"> Agb resource path received from backend.</param>
|
||||
/// <param name="privacyResourcePath"> Privacy resource path received from backend.</param>
|
||||
/// <param name="impressResourcePath"> Impress resource path received from backend.</param>
|
||||
/// <param name="resourceProvider">Delegate to get embedded html resource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
/// <param name="queryProvider">Object to query resources urls object from backend if required.</param>
|
||||
/// <param name="updateUrlsAction">Action to update shared resources urls object</param>
|
||||
public InfoPageViewModel(
|
||||
|
@ -102,7 +102,7 @@ namespace TINK.ViewModel.Info
|
|||
InfoAgb = new HtmlWebViewSource { Html = "<html>Loading...</html>" };
|
||||
|
||||
ResourceProvider = resourceProvider
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(InfoPageViewModel)}-object. No ressource provider centered.");
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(InfoPageViewModel)}-object. No resource provider centered.");
|
||||
}
|
||||
|
||||
/// <summary> Called when page is shown. </summary>
|
||||
|
@ -147,7 +147,7 @@ namespace TINK.ViewModel.Info
|
|||
|
||||
if (string.IsNullOrEmpty(PrivacyResourcePath))
|
||||
{
|
||||
// Information to access ressource is missing
|
||||
// Information to access resource is missing
|
||||
return new HtmlWebViewSource
|
||||
{
|
||||
Html = await Task.FromResult(ViewModelHelper.FromBody("No privacy resource available. Resource path is null or empty."))
|
||||
|
@ -172,7 +172,7 @@ namespace TINK.ViewModel.Info
|
|||
|
||||
if (string.IsNullOrEmpty(ImpressResourcePath))
|
||||
{
|
||||
// Information to access ressource is missing
|
||||
// Information to access resource is missing
|
||||
return new HtmlWebViewSource
|
||||
{
|
||||
Html = await Task.FromResult(ViewModelHelper.FromBody("No impress resource available. Resource path is null or empty."))
|
||||
|
|
|
@ -329,7 +329,7 @@ namespace TINK.ViewModel
|
|||
return;
|
||||
}
|
||||
|
||||
// Swich to map page
|
||||
// Switch to map page
|
||||
#if USEFLYOUT
|
||||
m_oViewService.ShowPage(ViewTypes.BikeInfoCarouselPage, AppResources.MarkingLoginInstructions);
|
||||
#else
|
||||
|
|
|
@ -22,11 +22,11 @@ using TINK.Services.Permissions;
|
|||
using Xamarin.Essentials;
|
||||
using System.Threading;
|
||||
using TINK.MultilingualResources;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Repository;
|
||||
using TINK.Services.Geolocation;
|
||||
using TINK.Model.State;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BC;
|
||||
using TINK.Model.Stations.StationNS;
|
||||
|
||||
#if !TRYNOTBACKSTYLE
|
||||
#endif
|
||||
|
@ -263,7 +263,7 @@ namespace TINK.ViewModel.Map
|
|||
? $"{stationId}" // there is a station marker with index letter for given station id
|
||||
: "Open"; // there is no station marker. Use open marker.
|
||||
|
||||
var colorPartPrefix = GetRessourceNameColorPart(stationsColorList[pinIndex]);
|
||||
var colorPartPrefix = GetResourceNameColorPart(stationsColorList[pinIndex]);
|
||||
var name = $"{indexPartPrefix.ToString().PadLeft(2, '0')}_{colorPartPrefix}{(DeviceInfo.Platform == DevicePlatform.Android ? ".png" : string.Empty)}";
|
||||
try
|
||||
{
|
||||
|
@ -306,7 +306,7 @@ namespace TINK.ViewModel.Map
|
|||
/// <summary> Gets the color related part of the ressrouce name.</summary>
|
||||
/// <param name="color">Color to get name for.</param>
|
||||
/// <returns>Resource name.</returns>
|
||||
private static string GetRessourceNameColorPart(Color color)
|
||||
private static string GetResourceNameColorPart(Color color)
|
||||
{
|
||||
if (color == Color.Blue)
|
||||
{
|
||||
|
@ -394,7 +394,8 @@ namespace TINK.ViewModel.Map
|
|||
|
||||
var colors = GetStationColors(
|
||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
||||
resultStationsAndBikes.Response.Bikes);
|
||||
resultStationsAndBikes.Response.StationsAll,
|
||||
resultStationsAndBikes.Response.BikesOccupied);
|
||||
|
||||
// Update pins color form count of bikes located at station.
|
||||
UpdatePinsColor(colors);
|
||||
|
@ -402,7 +403,7 @@ namespace TINK.ViewModel.Map
|
|||
Log.ForContext<MapPageViewModel>().Verbose("Update pins color done.");
|
||||
|
||||
// Load MyBikes Count -> MyBikes Icon/Button
|
||||
GetMyBikesCount(resultStationsAndBikes.Response.Bikes);
|
||||
GetMyBikesCount(resultStationsAndBikes.Response.BikesOccupied);
|
||||
|
||||
// Move and scale before getting stations and bikes which takes some time.
|
||||
ActionText = AppResources.ActivityTextCenterMap;
|
||||
|
@ -655,7 +656,7 @@ namespace TINK.ViewModel.Map
|
|||
}
|
||||
|
||||
// Load MyBikes Count -> MyBikes Icon/Button
|
||||
GetMyBikesCount(resultStationsAndBikes.Response.Bikes);
|
||||
GetMyBikesCount(resultStationsAndBikes.Response.BikesOccupied);
|
||||
|
||||
// Check if there are already any pins to the map.
|
||||
// If no initialize pins.
|
||||
|
@ -670,7 +671,8 @@ namespace TINK.ViewModel.Map
|
|||
// Set/ update pins colors.
|
||||
var l_oColors = GetStationColors(
|
||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
||||
resultStationsAndBikes.Response.Bikes);
|
||||
resultStationsAndBikes.Response.StationsAll,
|
||||
resultStationsAndBikes.Response.BikesOccupied);
|
||||
|
||||
// Update pins color form count of bikes located at station.
|
||||
TinkApp.PostAction(
|
||||
|
@ -758,10 +760,13 @@ namespace TINK.ViewModel.Map
|
|||
/// Gets the list of station color for all stations.
|
||||
/// </summary>
|
||||
/// <param name="stationsId">Station id list to get color for.</param>
|
||||
/// <param name="stations">Station object dictionary to get count of available bike from for each station.</param>
|
||||
/// <param name="bikesReserved">Bike collection to get count of reserved/ rented bikes from for each station.</param>
|
||||
/// <returns></returns>
|
||||
private static IList<Color> GetStationColors(
|
||||
internal static IList<Color> GetStationColors(
|
||||
IEnumerable<string> stationsId,
|
||||
BikeCollection bikesAll)
|
||||
IEnumerable<IStation> stations,
|
||||
IEnumerable<BikeInfo> bikesReserved)
|
||||
{
|
||||
if (stationsId == null)
|
||||
{
|
||||
|
@ -769,11 +774,14 @@ namespace TINK.ViewModel.Map
|
|||
return new List<Color>();
|
||||
}
|
||||
|
||||
if (bikesAll == null)
|
||||
if (stations == null)
|
||||
{
|
||||
// If object is null an error occurred querying bikes centered or bikes occupied which results in an unknown state.
|
||||
Log.ForContext<MapPageViewModel>().Error("No bikes available to determine pins color.");
|
||||
return new List<Color>(stationsId.Select(x => Color.Blue));
|
||||
Log.ForContext<MapPageViewModel>().Error("No stations info available to get count of bikes available to determine whether a pin is green or not.");
|
||||
}
|
||||
|
||||
if (bikesReserved == null)
|
||||
{
|
||||
Log.ForContext<MapPageViewModel>().Error("No bikes info available to determine whether a pins is light blue or not.");
|
||||
}
|
||||
|
||||
// Get state for each station.
|
||||
|
@ -781,15 +789,14 @@ namespace TINK.ViewModel.Map
|
|||
foreach (var stationId in stationsId)
|
||||
{
|
||||
// Get color of given station.
|
||||
var bikesAtStation = bikesAll.Where(x => x.StationId == stationId).ToList();
|
||||
if (bikesAtStation.FirstOrDefault(x => x.State.Value.IsOccupied()) != null)
|
||||
if (bikesReserved?.Where(x => x.StationId == stationId).Count() > 0)
|
||||
{
|
||||
// There is at least one requested or booked bike
|
||||
colors.Add(Color.LightBlue);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bikesAtStation.ToList().Count > 0)
|
||||
if (stations?.FirstOrDefault(x => x.Id == stationId)?.AvailableBikesCount > 0)
|
||||
{
|
||||
// There is at least one bike available
|
||||
colors.Add(Color.Green);
|
||||
|
@ -1030,7 +1037,8 @@ namespace TINK.ViewModel.Map
|
|||
Log.ForContext<MapPageViewModel>().Verbose("Starting update pins color on toggle...");
|
||||
var l_oColors = GetStationColors(
|
||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
||||
resultStationsAndBikes.Response.Bikes);
|
||||
resultStationsAndBikes.Response.StationsAll,
|
||||
resultStationsAndBikes.Response.BikesOccupied);
|
||||
|
||||
// Update pins color form count of bikes located at station.
|
||||
UpdatePinsColor(l_oColors);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
@ -66,12 +66,12 @@ namespace TINK.Model.Connector
|
|||
{
|
||||
NextActiveUri = new Uri(serverTextToUri.ContainsKey(value) ? serverTextToUri[value] : value);
|
||||
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CorpiServerUriDescription)));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CopriServerUriDescription)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Holds the description of the picker, i.e. binds to label Text.</summary>
|
||||
public string CorpiServerUriDescription
|
||||
public string CopriServerUriDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
|
@ -65,21 +65,21 @@ namespace TINK.ViewModel
|
|||
/// <summary> Reference on the tink app instance. </summary>
|
||||
private ITinkApp TinkApp { get; }
|
||||
|
||||
IServicesContainer<IGeolocationService> GeoloctionServicesContainer { get; }
|
||||
IServicesContainer<IGeolocationService> GeolocationServicesContainer { get; }
|
||||
|
||||
/// <summary> Constructs a settings page view model object.</summary>
|
||||
/// <param name="tinkApp"> Reference to tink app model.</param>
|
||||
/// <param name="geoloctionServicesContainer"></param>
|
||||
/// <param name="geolocationServicesContainer"></param>
|
||||
/// <param name="viewService">Interface to view</param>
|
||||
public SettingsPageViewModel(
|
||||
ITinkApp tinkApp,
|
||||
IServicesContainer<IGeolocationService> geoloctionServicesContainer,
|
||||
IServicesContainer<IGeolocationService> geolocationServicesContainer,
|
||||
IViewService viewService)
|
||||
{
|
||||
TinkApp = tinkApp
|
||||
?? throw new ArgumentException("Can not instantiate settings page view model- object. No tink app object available.");
|
||||
|
||||
GeoloctionServicesContainer = geoloctionServicesContainer
|
||||
GeolocationServicesContainer = geolocationServicesContainer
|
||||
?? throw new ArgumentException($"Can not instantiate {nameof(SettingsPageViewModel)}- object. Geolocation services container object must not be null.");
|
||||
|
||||
m_oViewService = viewService
|
||||
|
@ -175,14 +175,14 @@ namespace TINK.ViewModel
|
|||
TinkApp.LocksServices.Active.GetType().FullName));
|
||||
|
||||
GeolocationServices = new ServicesViewModel(
|
||||
GeoloctionServicesContainer.Select(x => x.GetType().FullName),
|
||||
GeolocationServicesContainer.Select(x => x.GetType().FullName),
|
||||
new Dictionary<string, string> {
|
||||
{ typeof(LastKnownGeolocationService).FullName, "LastKnowGeolocation" },
|
||||
{ typeof(GeolocationAccuracyMediumService).FullName, "Medium Accuracy" },
|
||||
{ typeof(GeolocationAccuracyHighService).FullName, "High Accuracy" },
|
||||
{ typeof(GeolocationAccuracyBestService).FullName, "Best Accuracy" },
|
||||
{ typeof(SimulatedGeolocationService).FullName, "Simulation-AlwaysSamePosition" } },
|
||||
GeoloctionServicesContainer.Active.GetType().FullName);
|
||||
GeolocationServicesContainer.Active.GetType().FullName);
|
||||
|
||||
StartupSettings = new PickerViewModel(
|
||||
new Dictionary<string, string> {
|
||||
|
@ -310,7 +310,7 @@ namespace TINK.ViewModel
|
|||
|
||||
TinkApp.LocksServices.SetActive(LocksServices.Services.Active);
|
||||
|
||||
GeoloctionServicesContainer.SetActive(GeolocationServices.Active);
|
||||
GeolocationServicesContainer.SetActive(GeolocationServices.Active);
|
||||
|
||||
TinkApp.LocksServices.SetTimeOut(TimeSpan.FromSeconds(LocksServices.ConnectTimeoutSec));
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ namespace TINK.ViewModel
|
|||
|
||||
}
|
||||
|
||||
/// <summary> Gets error message and handles aggegate exceptions. </summary>
|
||||
/// <summary> Gets error message and handles aggregate exceptions. </summary>
|
||||
public static string GetErrorMessage(this Exception exception)
|
||||
{
|
||||
if (exception == null)
|
||||
|
@ -239,8 +239,8 @@ namespace TINK.ViewModel
|
|||
|
||||
/// <summary> Called when page is shown. </summary>
|
||||
/// <param name="resourceUrl">Url to load data from.</param>
|
||||
/// <param name="isSiteCachingOn">Holds value wether site caching is on or off.</param>
|
||||
/// <param name="resourceProvider"> Provides resource from embedded ressources.</param>
|
||||
/// <param name="isSiteCachingOn">Holds value whether site caching is on or off.</param>
|
||||
/// <param name="resourceProvider"> Provides resource from embedded resources.</param>
|
||||
public static async Task<string> GetSource(
|
||||
string resourceUrl,
|
||||
bool isSiteCachingOn,
|
||||
|
@ -271,7 +271,7 @@ namespace TINK.ViewModel
|
|||
// An error occurred getting resource from web
|
||||
htmlContent = Barrel.Current.Exists(resourceUrl)
|
||||
? Barrel.Current.Get<string>(key: resourceUrl) // Get from MonkeyCache
|
||||
: resourceProvider != null ? resourceProvider() : $"<DOCTYPE html>Error loading {resourceUrl}."; // Get build in ressource.
|
||||
: resourceProvider != null ? resourceProvider() : $"<DOCTYPE html>Error loading {resourceUrl}."; // Get build in resource.
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -280,7 +280,7 @@ namespace TINK.ViewModel
|
|||
break;
|
||||
}
|
||||
|
||||
return htmlContent ?? FromBody("An error occurred loading html- ressource.");
|
||||
return htmlContent ?? FromBody("An error occurred loading html- resource.");
|
||||
}
|
||||
|
||||
public static string FromBody(string message) => $"<!DOCTYPE html><html lang=\"de\"><head><title>Error Information</title></head><body>{message}</body></html>";
|
||||
|
|
|
@ -16,13 +16,13 @@ namespace TINK.ViewModel.WhatsNew.Agb
|
|||
/// <summary> Holds the name of the host.</summary>
|
||||
private string HostName { get; }
|
||||
|
||||
/// <summary> Holds value wether site caching is on or off.</summary>
|
||||
/// <summary> Holds value whether site caching is on or off.</summary>
|
||||
bool IsSiteCachingOn { get; }
|
||||
|
||||
/// <summary> Constructs AGB view model</summary>
|
||||
/// <param name="isSiteCachingOn">Holds value wether site caching is on or off.</param>
|
||||
/// <param name="isSiteCachingOn">Holds value whether site caching is on or off.</param>
|
||||
/// <param name="uiIsoLangugageName">Two letter ISO language name.</param>
|
||||
/// <param name="resourceProvider">Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
/// <param name="resourceProvider">Delegate to get embedded html resource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
/// <param name="viewService">View service to close page.</param>
|
||||
public AgbViewModel(
|
||||
string hostName,
|
||||
|
@ -37,7 +37,7 @@ namespace TINK.ViewModel.WhatsNew.Agb
|
|||
?? throw new ArgumentException($"Can not instantiate {typeof(WhatsNewViewModel)}-object. No view available.");
|
||||
|
||||
ResourceProvider = resourceProvider
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(WhatsNewViewModel)}-object. No ressource provider centered.");
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(WhatsNewViewModel)}-object. No resource provider centered.");
|
||||
}
|
||||
|
||||
/// <summary> Gets the platfrom specific prefix. </summary>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue