mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2024-05-19 16:06:38 +02:00
Version 3.0.364
This commit is contained in:
parent
91d42552c7
commit
0b9196a78d
|
@ -3,9 +3,12 @@ Darmstadt
|
||||||
enum
|
enum
|
||||||
Freiburg
|
Freiburg
|
||||||
haveltec
|
haveltec
|
||||||
|
html
|
||||||
javaminister
|
javaminister
|
||||||
konrad
|
konrad
|
||||||
Mein
|
Mein
|
||||||
|
serilog
|
||||||
sharee
|
sharee
|
||||||
tink
|
tink
|
||||||
|
ui
|
||||||
xdoc
|
xdoc
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.363" android:versionCode="363">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.364" android:versionCode="364">
|
||||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
|
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
|
||||||
<!-- Google Maps related permissions -->
|
<!-- Google Maps related permissions -->
|
||||||
<!-- Permission to receive remote notifications from Google Play Services -->
|
<!-- Permission to receive remote notifications from Google Play Services -->
|
||||||
|
|
|
@ -56,8 +56,8 @@
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>LastenradBayern</string>
|
<string>LastenradBayern</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>363</string>
|
<string>364</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.0.363</string>
|
<string>3.0.364</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace TINK
|
||||||
var specialFolders = DependencyService.Get<ISpecialFolder>();
|
var specialFolders = DependencyService.Get<ISpecialFolder>();
|
||||||
var internalPersonalDir = specialFolders.GetInternalPersonalDir();
|
var internalPersonalDir = specialFolders.GetInternalPersonalDir();
|
||||||
|
|
||||||
// Delete attachtment from previous session.
|
// Delete attachment from previous session.
|
||||||
DeleteAttachment(internalPersonalDir);
|
DeleteAttachment(internalPersonalDir);
|
||||||
|
|
||||||
// Setup logger using default settings.
|
// Setup logger using default settings.
|
||||||
|
@ -109,11 +109,11 @@ namespace TINK
|
||||||
if (settings.MinimumLogEventLevel != Model.Settings.Settings.DEFAULTLOGGINLEVEL
|
if (settings.MinimumLogEventLevel != Model.Settings.Settings.DEFAULTLOGGINLEVEL
|
||||||
|| settings.LogToExternalFolder)
|
|| settings.LogToExternalFolder)
|
||||||
{
|
{
|
||||||
// Eigher
|
// Either
|
||||||
// - logging is not set to default value or
|
// - logging is not set to default value or
|
||||||
// - logging is performed to external folder.
|
// - logging is performed to external folder.
|
||||||
// Need to reconfigure.
|
// Need to reconfigure.
|
||||||
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing vialation occurs.
|
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing violation occurs.
|
||||||
|
|
||||||
TinkApp.SetupLogging(
|
TinkApp.SetupLogging(
|
||||||
new LoggingLevelSwitch(settings.MinimumLogEventLevel),
|
new LoggingLevelSwitch(settings.MinimumLogEventLevel),
|
||||||
|
@ -133,7 +133,7 @@ namespace TINK
|
||||||
{
|
{
|
||||||
// App versions newer than 3.0.173 stored geolocation service in configuration.
|
// App versions newer than 3.0.173 stored geolocation service in configuration.
|
||||||
// Version 3.0.290: Geolocation service "GeolocationService" is no more supported.
|
// Version 3.0.290: Geolocation service "GeolocationService" is no more supported.
|
||||||
// For this reasons a swich of geolocation service is forced when loading configurations from ealier versions.
|
// For this reasons a switch of geolocation service is forced when loading configurations from ealier versions.
|
||||||
LocationServicesContainer.SetActive(settings.ActiveGeolocationService);
|
LocationServicesContainer.SetActive(settings.ActiveGeolocationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ namespace TINK
|
||||||
|
|
||||||
const string MERCHANTID = "0000000000";
|
const string MERCHANTID = "0000000000";
|
||||||
|
|
||||||
// Create new app instnace.
|
// Create new app instance.
|
||||||
Log.Debug("Constructing main model...");
|
Log.Debug("Constructing main model...");
|
||||||
m_oModelRoot = new TinkApp(
|
m_oModelRoot = new TinkApp(
|
||||||
settings,
|
settings,
|
||||||
|
|
|
@ -71,8 +71,9 @@
|
||||||
Text="{x:Static resources:AppResources.ActionContactMailAppReleated}"
|
Text="{x:Static resources:AppResources.ActionContactMailAppReleated}"
|
||||||
IsEnabled="{Binding IsSendMailAvailable}"
|
IsEnabled="{Binding IsSendMailAvailable}"
|
||||||
Command="{Binding OnMailAppRelatedRequest}"/>
|
Command="{Binding OnMailAppRelatedRequest}"/>
|
||||||
<!--- Link to App Store -->
|
<!--- Link to App Store
|
||||||
<Label
|
inactivated since most feedback in App Store is not app-related-->
|
||||||
|
<!--<Label
|
||||||
Margin="0,10,0,0"
|
Margin="0,10,0,0"
|
||||||
TextType="Html"
|
TextType="Html"
|
||||||
HorizontalOptions="Center"
|
HorizontalOptions="Center"
|
||||||
|
@ -81,7 +82,7 @@
|
||||||
<Label.GestureRecognizers>
|
<Label.GestureRecognizers>
|
||||||
<TapGestureRecognizer Command="{Binding OnRateRequest}"/>
|
<TapGestureRecognizer Command="{Binding OnRateRequest}"/>
|
||||||
</Label.GestureRecognizers>
|
</Label.GestureRecognizers>
|
||||||
</Label>
|
</Label>-->
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Frame>
|
</Frame>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
|
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
|
||||||
#if USEFLYOUT
|
#if USEFLYOUT
|
||||||
|
@ -23,7 +23,7 @@ namespace TINK.View.Info.BikeInfo
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
ItemsSource = new BikeInfoViewModel(
|
ItemsSource = new BikeInfoViewModel(
|
||||||
resourceName => ImageSource.FromResource($"{ViewModelResourceHelper.RessourcePrefix}Images.{resourceName}"),
|
resourceName => ImageSource.FromResource($"{ViewModelResourceHelper.ResourcePrefix}Images.{resourceName}"),
|
||||||
this).CarouselItems;
|
this).CarouselItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,4 +126,4 @@ namespace TINK.View.Info.BikeInfo
|
||||||
public async Task<IUserFeedback> DisplayUserFeedbackPopup(IBattery battery = null, string co2Saving = null) => throw new NotSupportedException();
|
public async Task<IUserFeedback> DisplayUserFeedbackPopup(IBattery battery = null, string co2Saving = null) => throw new NotSupportedException();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Label
|
<Label
|
||||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||||
Text="{Binding CopriServerUriList.CorpiServerUriDescription}"/>
|
Text="{Binding CopriServerUriList.CopriServerUriDescription}"/>
|
||||||
<Picker
|
<Picker
|
||||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||||
ItemsSource="{Binding CopriServerUriList.ServerTextList}"
|
ItemsSource="{Binding CopriServerUriList.ServerTextList}"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
@ -7,8 +7,8 @@ namespace TINK.ViewModel
|
||||||
{
|
{
|
||||||
public static class ViewModelResourceHelper
|
public static class ViewModelResourceHelper
|
||||||
{
|
{
|
||||||
/// <summary> Get ressource prefix depending on platform.</summary>
|
/// <summary> Get resource prefix depending on platform.</summary>
|
||||||
public static string RessourcePrefix
|
public static string ResourcePrefix
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -24,19 +24,19 @@ namespace TINK.ViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets an an embedded html ressource.</summary>
|
/// <summary> Gets an embedded html resource.</summary>
|
||||||
/// <param name="resrouceName">Name of resource to get.</param>
|
/// <param name="resrouceName">Name of resource to get.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GetSource(string resrouceName)
|
public static string GetSource(string resrouceName)
|
||||||
{
|
{
|
||||||
var l_oRessourceName = RessourcePrefix + resrouceName;
|
var resourceName = ResourcePrefix + resrouceName;
|
||||||
Log.Verbose($"Using this resource prefix {RessourcePrefix}.");
|
Log.Verbose($"Using this resource prefix {ResourcePrefix}.");
|
||||||
// note that the prefix includes the trailing period '.' that is required
|
// note that the prefix includes the trailing period '.' that is required
|
||||||
var assembly = typeof(ViewModelResourceHelper).GetTypeInfo().Assembly;
|
var assembly = typeof(ViewModelResourceHelper).GetTypeInfo().Assembly;
|
||||||
var stream = assembly.GetManifestResourceStream(l_oRessourceName);
|
var stream = assembly.GetManifestResourceStream(resourceName);
|
||||||
return stream != null
|
return stream != null
|
||||||
? (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
|
? (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
|
||||||
: string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- ressource {0}.</body>", l_oRessourceName);
|
: string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- resource {0}.</body>", resourceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.363" android:versionCode="363">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.364" android:versionCode="364">
|
||||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
|
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
|
||||||
<!-- Google Maps related permissions -->
|
<!-- Google Maps related permissions -->
|
||||||
<!-- Permission to receive remote notifications from Google Play Services -->
|
<!-- Permission to receive remote notifications from Google Play Services -->
|
||||||
|
|
|
@ -56,8 +56,8 @@
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>Mein konrad</string>
|
<string>Mein konrad</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>363</string>
|
<string>364</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.0.363</string>
|
<string>3.0.364</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace TINK
|
||||||
var specialFolders = DependencyService.Get<ISpecialFolder>();
|
var specialFolders = DependencyService.Get<ISpecialFolder>();
|
||||||
var internalPersonalDir = specialFolders.GetInternalPersonalDir();
|
var internalPersonalDir = specialFolders.GetInternalPersonalDir();
|
||||||
|
|
||||||
// Delete attachtment from previous session.
|
// Delete attachment from previous session.
|
||||||
DeleteAttachment(internalPersonalDir);
|
DeleteAttachment(internalPersonalDir);
|
||||||
|
|
||||||
// Setup logger using default settings.
|
// Setup logger using default settings.
|
||||||
|
@ -108,11 +108,11 @@ namespace TINK
|
||||||
if (settings.MinimumLogEventLevel != Model.Settings.Settings.DEFAULTLOGGINLEVEL
|
if (settings.MinimumLogEventLevel != Model.Settings.Settings.DEFAULTLOGGINLEVEL
|
||||||
|| settings.LogToExternalFolder)
|
|| settings.LogToExternalFolder)
|
||||||
{
|
{
|
||||||
// Eigher
|
// Either
|
||||||
// - logging is not set to default value or
|
// - logging is not set to default value or
|
||||||
// - logging is performed to external folder.
|
// - logging is performed to external folder.
|
||||||
// Need to reconfigure.
|
// Need to reconfigure.
|
||||||
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing vialation occurs.
|
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing violation occurs.
|
||||||
|
|
||||||
TinkApp.SetupLogging(
|
TinkApp.SetupLogging(
|
||||||
new LoggingLevelSwitch(settings.MinimumLogEventLevel),
|
new LoggingLevelSwitch(settings.MinimumLogEventLevel),
|
||||||
|
@ -132,7 +132,7 @@ namespace TINK
|
||||||
{
|
{
|
||||||
// App versions newer than 3.0.173 stored geolocation service in configuration.
|
// App versions newer than 3.0.173 stored geolocation service in configuration.
|
||||||
// Version 3.0.290: Geolocation service "GeolocationService" is no more supported.
|
// Version 3.0.290: Geolocation service "GeolocationService" is no more supported.
|
||||||
// For this a swich of geolocation service is fored when loading configurations of older app versions.
|
// For this a switch of geolocation service is forced when loading configurations of older app versions.
|
||||||
LocationServicesContainer.SetActive(settings.ActiveGeolocationService);
|
LocationServicesContainer.SetActive(settings.ActiveGeolocationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace TINK
|
||||||
|
|
||||||
const string MERCHANTID = "0000000000";
|
const string MERCHANTID = "0000000000";
|
||||||
|
|
||||||
// Create new app instnace.
|
// Create new app instance.
|
||||||
Log.Debug("Constructing main model...");
|
Log.Debug("Constructing main model...");
|
||||||
m_oModelRoot = new TinkApp(
|
m_oModelRoot = new TinkApp(
|
||||||
settings,
|
settings,
|
||||||
|
|
|
@ -70,11 +70,13 @@
|
||||||
<Label FormattedText="{Binding LikeTinkApp}"/>
|
<Label FormattedText="{Binding LikeTinkApp}"/>
|
||||||
<!--- Mail to app- related support -->
|
<!--- Mail to app- related support -->
|
||||||
<Button
|
<Button
|
||||||
|
Style="{StaticResource SecondaryButton}"
|
||||||
Text="{x:Static resources:AppResources.ActionContactMailAppReleated}"
|
Text="{x:Static resources:AppResources.ActionContactMailAppReleated}"
|
||||||
IsEnabled="{Binding IsSendMailAvailable}"
|
IsEnabled="{Binding IsSendMailAvailable}"
|
||||||
Command="{Binding OnMailAppRelatedRequest}"/>
|
Command="{Binding OnMailAppRelatedRequest}"/>
|
||||||
<!--- Link to App Store -->
|
<!--- Link to App Store
|
||||||
<Label
|
inactivated since most feedback in App Store is not app-related-->
|
||||||
|
<!--<Label
|
||||||
Margin="0,10,0,0"
|
Margin="0,10,0,0"
|
||||||
TextType="Html"
|
TextType="Html"
|
||||||
HorizontalOptions="Center"
|
HorizontalOptions="Center"
|
||||||
|
@ -83,7 +85,7 @@
|
||||||
<Label.GestureRecognizers>
|
<Label.GestureRecognizers>
|
||||||
<TapGestureRecognizer Command="{Binding OnRateRequest}"/>
|
<TapGestureRecognizer Command="{Binding OnRateRequest}"/>
|
||||||
</Label.GestureRecognizers>
|
</Label.GestureRecognizers>
|
||||||
</Label>
|
</Label>-->
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Frame>
|
</Frame>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
|
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
|
||||||
#if USEFLYOUT
|
#if USEFLYOUT
|
||||||
|
@ -23,7 +23,7 @@ namespace TINK.View.Info.BikeInfo
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
ItemsSource = new BikeInfoViewModel(
|
ItemsSource = new BikeInfoViewModel(
|
||||||
resourceName => ImageSource.FromResource($"{ViewModelResourceHelper.RessourcePrefix}Images.{resourceName}"),
|
resourceName => ImageSource.FromResource($"{ViewModelResourceHelper.ResourcePrefix}Images.{resourceName}"),
|
||||||
this).CarouselItems;
|
this).CarouselItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,4 +126,4 @@ namespace TINK.View.Info.BikeInfo
|
||||||
public async Task<IUserFeedback> DisplayUserFeedbackPopup(IBattery battery = null, string co2Saving = null) => throw new NotSupportedException();
|
public async Task<IUserFeedback> DisplayUserFeedbackPopup(IBattery battery = null, string co2Saving = null) => throw new NotSupportedException();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Label
|
<Label
|
||||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||||
Text="{Binding CopriServerUriList.CorpiServerUriDescription}"/>
|
Text="{Binding CopriServerUriList.CopriServerUriDescription}"/>
|
||||||
<Picker
|
<Picker
|
||||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||||
ItemsSource="{Binding CopriServerUriList.ServerTextList}"
|
ItemsSource="{Binding CopriServerUriList.ServerTextList}"
|
||||||
|
|
|
@ -7,8 +7,8 @@ namespace TINK.ViewModel
|
||||||
{
|
{
|
||||||
public static class ViewModelResourceHelper
|
public static class ViewModelResourceHelper
|
||||||
{
|
{
|
||||||
/// <summary> Get ressource prefix depending on platform.</summary>
|
/// <summary> Get resource prefix depending on platform.</summary>
|
||||||
public static string RessourcePrefix
|
public static string ResourcePrefix
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -24,19 +24,19 @@ namespace TINK.ViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets an an embedded html ressource.</summary>
|
/// <summary> Gets an embedded html resource.</summary>
|
||||||
/// <param name="resrouceName">Name of resource to get.</param>
|
/// <param name="resrouceName">Name of resource to get.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GetEmbeddedResource(string resrouceName)
|
public static string GetEmbeddedResource(string resrouceName)
|
||||||
{
|
{
|
||||||
var ressourceName = RessourcePrefix + resrouceName;
|
var resourceName = ResourcePrefix + resrouceName;
|
||||||
Log.Verbose($"Using this resource prefix {RessourcePrefix}.");
|
Log.Verbose($"Using this resource prefix {ResourcePrefix}.");
|
||||||
// note that the prefix includes the trailing period '.' that is required
|
// note that the prefix includes the trailing period '.' that is required
|
||||||
var assembly = typeof(ViewModelResourceHelper).GetTypeInfo().Assembly;
|
var assembly = typeof(ViewModelResourceHelper).GetTypeInfo().Assembly;
|
||||||
var stream = assembly.GetManifestResourceStream(ressourceName);
|
var stream = assembly.GetManifestResourceStream(resourceName);
|
||||||
return stream != null
|
return stream != null
|
||||||
? (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
|
? (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
|
||||||
: string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- ressource {0}.</body>", ressourceName);
|
: string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- resource {0}.</body>", resourceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using TINK.MultilingualResources;
|
using TINK.MultilingualResources;
|
||||||
|
|
||||||
namespace ShareeSharedGuiLib.ViewModel
|
namespace ShareeSharedGuiLib.ViewModel
|
||||||
|
@ -74,7 +74,7 @@ namespace ShareeSharedGuiLib.ViewModel
|
||||||
public bool IsBatteryChargeLevelLabelVisible => Maximum.HasValue && Maximum.Value != 5;
|
public bool IsBatteryChargeLevelLabelVisible => Maximum.HasValue && Maximum.Value != 5;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets name of battery image ressource.
|
/// Gets name of battery image resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string BatteryChargeLevelImageSourceString => Current.HasValue && Maximum.HasValue && Maximum.Value == 5
|
public string BatteryChargeLevelImageSourceString => Current.HasValue && Maximum.HasValue && Maximum.Value == 5
|
||||||
? $"battery_{Current.Value}_{Maximum.Value}.png"
|
? $"battery_{Current.Value}_{Maximum.Value}.png"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.363" android:versionCode="363">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.364" android:versionCode="364">
|
||||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
|
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
|
||||||
<!-- Google Maps related permissions -->
|
<!-- Google Maps related permissions -->
|
||||||
<!-- Permission to receive remote notifications from Google Play Services -->
|
<!-- Permission to receive remote notifications from Google Play Services -->
|
||||||
|
|
|
@ -56,8 +56,8 @@
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>sharee.bike</string>
|
<string>sharee.bike</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>363</string>
|
<string>364</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.0.363</string>
|
<string>3.0.364</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace TINK
|
||||||
var specialFolders = DependencyService.Get<ISpecialFolder>();
|
var specialFolders = DependencyService.Get<ISpecialFolder>();
|
||||||
var internalPersonalDir = specialFolders.GetInternalPersonalDir();
|
var internalPersonalDir = specialFolders.GetInternalPersonalDir();
|
||||||
|
|
||||||
// Delete attachtment from previous session.
|
// Delete attachment from previous session.
|
||||||
DeleteAttachment(internalPersonalDir);
|
DeleteAttachment(internalPersonalDir);
|
||||||
|
|
||||||
// Setup logger using default settings.
|
// Setup logger using default settings.
|
||||||
|
@ -108,11 +108,11 @@ namespace TINK
|
||||||
if (settings.MinimumLogEventLevel != Model.Settings.Settings.DEFAULTLOGGINLEVEL
|
if (settings.MinimumLogEventLevel != Model.Settings.Settings.DEFAULTLOGGINLEVEL
|
||||||
|| settings.LogToExternalFolder)
|
|| settings.LogToExternalFolder)
|
||||||
{
|
{
|
||||||
// Eigher
|
// Either
|
||||||
// - logging is not set to default value or
|
// - logging is not set to default value or
|
||||||
// - logging is performed to external folder.
|
// - logging is performed to external folder.
|
||||||
// Need to reconfigure.
|
// Need to reconfigure.
|
||||||
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing vialation occurs.
|
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing violation occurs.
|
||||||
|
|
||||||
TinkApp.SetupLogging(
|
TinkApp.SetupLogging(
|
||||||
new LoggingLevelSwitch(settings.MinimumLogEventLevel),
|
new LoggingLevelSwitch(settings.MinimumLogEventLevel),
|
||||||
|
@ -132,7 +132,7 @@ namespace TINK
|
||||||
{
|
{
|
||||||
// App versions newer than 3.0.173 stored geolocation service in configuration.
|
// App versions newer than 3.0.173 stored geolocation service in configuration.
|
||||||
// Version 3.0.290: Geolocation service "GeolocationService" is no more supported.
|
// Version 3.0.290: Geolocation service "GeolocationService" is no more supported.
|
||||||
// For this reasons a swich of geolocation service is forced when loading configurations from ealier versions.
|
// For this reasons a switch of geolocation service is forced when loading configurations from ealier versions.
|
||||||
LocationServicesContainer.SetActive(settings.ActiveGeolocationService);
|
LocationServicesContainer.SetActive(settings.ActiveGeolocationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace TINK
|
||||||
|
|
||||||
const string MERCHANTID = "0000000000";
|
const string MERCHANTID = "0000000000";
|
||||||
|
|
||||||
// Create new app instnace.
|
// Create new app instance.
|
||||||
Log.Debug("Constructing main model...");
|
Log.Debug("Constructing main model...");
|
||||||
m_oModelRoot = new TinkApp(
|
m_oModelRoot = new TinkApp(
|
||||||
settings,
|
settings,
|
||||||
|
|
|
@ -69,11 +69,13 @@
|
||||||
<Label FormattedText="{Binding LikeTinkApp}"/>
|
<Label FormattedText="{Binding LikeTinkApp}"/>
|
||||||
<!--- Mail to app- related support -->
|
<!--- Mail to app- related support -->
|
||||||
<Button
|
<Button
|
||||||
|
Style="{StaticResource SecondaryButton}"
|
||||||
Text="{x:Static resources:AppResources.ActionContactMailAppReleated}"
|
Text="{x:Static resources:AppResources.ActionContactMailAppReleated}"
|
||||||
IsEnabled="{Binding IsSendMailAvailable}"
|
IsEnabled="{Binding IsSendMailAvailable}"
|
||||||
Command="{Binding OnMailAppRelatedRequest}"/>
|
Command="{Binding OnMailAppRelatedRequest}"/>
|
||||||
<!--- Link to App Store -->
|
<!--- Link to App Store
|
||||||
<Label
|
inactivated since most feedback in App Store is not app-related-->
|
||||||
|
<!--<Label
|
||||||
Margin="0,10,0,0"
|
Margin="0,10,0,0"
|
||||||
TextType="Html"
|
TextType="Html"
|
||||||
HorizontalOptions="Center"
|
HorizontalOptions="Center"
|
||||||
|
@ -82,7 +84,7 @@
|
||||||
<Label.GestureRecognizers>
|
<Label.GestureRecognizers>
|
||||||
<TapGestureRecognizer Command="{Binding OnRateRequest}"/>
|
<TapGestureRecognizer Command="{Binding OnRateRequest}"/>
|
||||||
</Label.GestureRecognizers>
|
</Label.GestureRecognizers>
|
||||||
</Label>
|
</Label>-->
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</Frame>
|
</Frame>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
|
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
|
||||||
#if USEFLYOUT
|
#if USEFLYOUT
|
||||||
|
@ -23,7 +23,7 @@ namespace TINK.View.Info.BikeInfo
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
ItemsSource = new BikeInfoViewModel(
|
ItemsSource = new BikeInfoViewModel(
|
||||||
resourceName => ImageSource.FromResource($"{ViewModelResourceHelper.RessourcePrefix}Images.{resourceName}"),
|
resourceName => ImageSource.FromResource($"{ViewModelResourceHelper.ResourcePrefix}Images.{resourceName}"),
|
||||||
this).CarouselItems;
|
this).CarouselItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,4 +126,4 @@ namespace TINK.View.Info.BikeInfo
|
||||||
public async Task<IUserFeedback> DisplayUserFeedbackPopup(IBattery battery = null, string co2Saving = null) => throw new NotSupportedException();
|
public async Task<IUserFeedback> DisplayUserFeedbackPopup(IBattery battery = null, string co2Saving = null) => throw new NotSupportedException();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Label
|
<Label
|
||||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||||
Text="{Binding CopriServerUriList.CorpiServerUriDescription}"/>
|
Text="{Binding CopriServerUriList.CopriServerUriDescription}"/>
|
||||||
<Picker
|
<Picker
|
||||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||||
ItemsSource="{Binding CopriServerUriList.ServerTextList}"
|
ItemsSource="{Binding CopriServerUriList.ServerTextList}"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
@ -7,8 +7,8 @@ namespace TINK.ViewModel
|
||||||
{
|
{
|
||||||
public static class ViewModelResourceHelper
|
public static class ViewModelResourceHelper
|
||||||
{
|
{
|
||||||
/// <summary> Get ressource prefix depending on platform.</summary>
|
/// <summary> Get resource prefix depending on platform.</summary>
|
||||||
public static string RessourcePrefix
|
public static string ResourcePrefix
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -24,19 +24,19 @@ namespace TINK.ViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets an an embedded html ressource.</summary>
|
/// <summary> Gets embedded html resource.</summary>
|
||||||
/// <param name="resrouceName">Name of resource to get.</param>
|
/// <param name="resrouceName">Name of resource to get.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string GetSource(string resrouceName)
|
public static string GetSource(string resrouceName)
|
||||||
{
|
{
|
||||||
var l_oRessourceName = RessourcePrefix + resrouceName;
|
var resourceName = ResourcePrefix + resrouceName;
|
||||||
Log.Verbose($"Using this resource prefix {RessourcePrefix}.");
|
Log.Verbose($"Using this resource prefix {ResourcePrefix}.");
|
||||||
// note that the prefix includes the trailing period '.' that is required
|
// note that the prefix includes the trailing period '.' that is required
|
||||||
var assembly = typeof(ViewModelResourceHelper).GetTypeInfo().Assembly;
|
var assembly = typeof(ViewModelResourceHelper).GetTypeInfo().Assembly;
|
||||||
var stream = assembly.GetManifestResourceStream(l_oRessourceName);
|
var stream = assembly.GetManifestResourceStream(resourceName);
|
||||||
return stream != null
|
return stream != null
|
||||||
? (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
|
? (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
|
||||||
: string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- ressource {0}.</body>", l_oRessourceName);
|
: string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- resource {0}.</body>", resourceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
|
||||||
public enum DataSource
|
public enum DataSource
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data source corpi.
|
/// Data source copri.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Copri,
|
Copri,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -7,6 +7,7 @@ using TINK.Model.Connector.Filter;
|
||||||
using TINK.Model.Services.CopriApi;
|
using TINK.Model.Services.CopriApi;
|
||||||
using TINK.Model.Stations;
|
using TINK.Model.Stations;
|
||||||
using TINK.Model.Stations.StationNS;
|
using TINK.Model.Stations.StationNS;
|
||||||
|
using TINK.Model.Stations.StationNS.Operator;
|
||||||
using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
|
using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
|
||||||
|
|
||||||
namespace TINK.Model.Connector
|
namespace TINK.Model.Connector
|
||||||
|
@ -92,11 +93,18 @@ namespace TINK.Model.Connector
|
||||||
var providerBikesAndStations = await m_oInnerQuery.GetBikesAndStationsAsync();
|
var providerBikesAndStations = await m_oInnerQuery.GetBikesAndStationsAsync();
|
||||||
|
|
||||||
// Do filtering.
|
// Do filtering.
|
||||||
var filteredStationsDictionary = new StationDictionary(providerBikesAndStations.Response.StationsAll.CopriVersion, DoFilter(providerBikesAndStations.Response.StationsAll, Filter));
|
var filteredStationsDictionary = new StationDictionary(
|
||||||
var filteredBikesDictionary = new BikeCollection(DoFilter(providerBikesAndStations.Response.Bikes, Filter));
|
providerBikesAndStations.Response.StationsAll.CopriVersion,
|
||||||
|
DoFilter(providerBikesAndStations.Response.StationsAll, Filter));
|
||||||
|
|
||||||
|
var filteredBikesOccupiedDictionary = new BikeCollection(
|
||||||
|
DoFilter(providerBikesAndStations.Response.BikesOccupied, Filter));
|
||||||
|
|
||||||
var filteredBikesAndStations = new Result<StationsAndBikesContainer>(
|
var filteredBikesAndStations = new Result<StationsAndBikesContainer>(
|
||||||
providerBikesAndStations.Source,
|
providerBikesAndStations.Source,
|
||||||
new StationsAndBikesContainer(filteredStationsDictionary, filteredBikesDictionary),
|
new StationsAndBikesContainer(
|
||||||
|
filteredStationsDictionary,
|
||||||
|
filteredBikesOccupiedDictionary),
|
||||||
providerBikesAndStations.GeneralData,
|
providerBikesAndStations.GeneralData,
|
||||||
providerBikesAndStations.Exception);
|
providerBikesAndStations.Exception);
|
||||||
|
|
||||||
|
@ -106,17 +114,25 @@ namespace TINK.Model.Connector
|
||||||
/// <summary> Filter bikes by group. </summary>
|
/// <summary> Filter bikes by group. </summary>
|
||||||
/// <param name="bikes">Bikes to filter.</param>
|
/// <param name="bikes">Bikes to filter.</param>
|
||||||
/// <returns>Filtered bikes.</returns>
|
/// <returns>Filtered bikes.</returns>
|
||||||
private static Dictionary<string, BikeInfo> DoFilter(BikeCollection bikes, IGroupFilter filter)
|
private static Dictionary<string, BikeInfo> DoFilter(BikeCollection bikes, IGroupFilter filter) =>
|
||||||
{
|
bikes
|
||||||
return bikes.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id);
|
.Where(x => filter.DoFilter(x.Group).Count() > 0)
|
||||||
}
|
.ToDictionary(x => x.Id);
|
||||||
|
|
||||||
/// <summary> Filter stations by group. </summary>
|
/// <summary> Filter stations by group and removes bike group collection entries which do not match group filter. </summary>
|
||||||
/// <returns></returns>
|
/// <returns>Matching stations.</returns>
|
||||||
private static Dictionary<string, IStation> DoFilter(StationDictionary stations, IGroupFilter filter)
|
private static Dictionary<string, IStation> DoFilter(StationDictionary stations, IGroupFilter filter) =>
|
||||||
{
|
stations
|
||||||
return stations.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id);
|
.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>(
|
return new Result<StationsAndBikesContainer>(
|
||||||
result.Source,
|
result.Source,
|
||||||
new StationsAndBikesContainer(
|
new StationsAndBikesContainer(
|
||||||
new StationDictionary(result.Response.StationsAll.CopriVersion, result.Response.StationsAll.ToDictionary(x => x.Id)),
|
new StationDictionary(
|
||||||
new BikeCollection(result.Response.Bikes.ToDictionary(x => x.Id))),
|
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.GeneralData,
|
||||||
result.Exception);
|
result.Exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,31 +41,19 @@ namespace TINK.Model.Connector
|
||||||
resultStations.Source,
|
resultStations.Source,
|
||||||
new StationsAndBikesContainer(
|
new StationsAndBikesContainer(
|
||||||
resultStations.Response.GetStationsAllMutable(),
|
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.GeneralData,
|
||||||
resultStations.Exception);
|
resultStations.Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultBikes = await server.GetBikesAvailable();
|
// Communication with copri succeeded.
|
||||||
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.
|
|
||||||
server.AddToCache(resultStations);
|
server.AddToCache(resultStations);
|
||||||
server.AddToCache(resultBikes);
|
|
||||||
|
|
||||||
return new Result<StationsAndBikesContainer>(
|
return new Result<StationsAndBikesContainer>(
|
||||||
resultStations.Source,
|
resultStations.Source,
|
||||||
new StationsAndBikesContainer(resultStations.Response.GetStationsAllMutable(), resultBikes.Response.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Copri)),
|
new StationsAndBikesContainer(
|
||||||
|
resultStations.Response.GetStationsAllMutable(),
|
||||||
|
new BikeCollection()),
|
||||||
resultStations.GeneralData);
|
resultStations.GeneralData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
@ -6,6 +7,7 @@ using TINK.Model.Bikes;
|
||||||
using TINK.Model.Connector.Updater;
|
using TINK.Model.Connector.Updater;
|
||||||
using TINK.Model.Services.CopriApi;
|
using TINK.Model.Services.CopriApi;
|
||||||
using TINK.Repository;
|
using TINK.Repository;
|
||||||
|
using TINK.Repository.Response;
|
||||||
|
|
||||||
namespace TINK.Model.Connector
|
namespace TINK.Model.Connector
|
||||||
{
|
{
|
||||||
|
@ -25,90 +27,47 @@ namespace TINK.Model.Connector
|
||||||
Server = copriServer as ICachedCopriServer;
|
Server = copriServer as ICachedCopriServer;
|
||||||
if (Server == null)
|
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>
|
/// <summary> Gets all stations including positions.</summary>
|
||||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
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();
|
var stationsResponse = await Server.GetStations();
|
||||||
|
|
||||||
if (stationsResponse.Source == typeof(CopriCallsMonkeyStore)
|
if (stationsResponse.Source == typeof(CopriCallsMonkeyStore)
|
||||||
|| stationsResponse.Exception != null)
|
|| 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>(
|
return new Result<StationsAndBikesContainer>(
|
||||||
stationsResponse.Source,
|
stationsResponse.Source,
|
||||||
new StationsAndBikesContainer(
|
new StationsAndBikesContainer(
|
||||||
stationsResponse.Response.GetStationsAllMutable(),
|
stationsResponse.Response.GetStationsAllMutable(),
|
||||||
BikeCollectionFactory.GetBikesAll(
|
GetBikeCollection(stationsResponse.Response.bikes_occupied?.Values, Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||||
(await Server.GetBikesAvailable(true)).Response?.bikes?.Values,
|
|
||||||
(await Server.GetBikesOccupied(true)).Response?.bikes_occupied?.Values,
|
|
||||||
Mail,
|
|
||||||
DateTimeProvider,
|
|
||||||
Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
|
||||||
stationsResponse.GeneralData,
|
stationsResponse.GeneralData,
|
||||||
stationsResponse.Exception);
|
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
|
// Both types bikes could read from copri => update cache
|
||||||
Server.AddToCache(stationsResponse);
|
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>(
|
return new Result<StationsAndBikesContainer>(
|
||||||
stationsResponse.Source,
|
stationsResponse.Source,
|
||||||
new StationsAndBikesContainer(stationsMutable, bikesMutable),
|
new StationsAndBikesContainer(
|
||||||
|
stationsResponse.Response.GetStationsAllMutable(),
|
||||||
|
GetBikeCollection(stationsResponse.Response.bikes_occupied?.Values, Bikes.BikeInfoNS.BC.DataSource.Copri)),
|
||||||
stationsResponse.GeneralData,
|
stationsResponse.GeneralData,
|
||||||
exceptions.Length > 0 ? new AggregateException(exceptions) : null);
|
stationsResponse?.Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Gets bikes occupied. </summary>
|
/// <summary> Gets bikes occupied. </summary>
|
||||||
|
|
|
@ -32,11 +32,12 @@ namespace TINK.Model.Connector
|
||||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||||
{
|
{
|
||||||
var stationsAllResponse = await server.GetStationsAsync();
|
var stationsAllResponse = await server.GetStationsAsync();
|
||||||
var bikesAvailableResponse = await server.GetBikesAvailableAsync();
|
|
||||||
|
|
||||||
return new Result<StationsAndBikesContainer>(
|
return new Result<StationsAndBikesContainer>(
|
||||||
typeof(CopriCallsMonkeyStore),
|
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());
|
stationsAllResponse.GetGeneralData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TINK.Model.Bikes;
|
using TINK.Model.Bikes;
|
||||||
using TINK.Model.Connector.Updater;
|
using TINK.Model.Connector.Updater;
|
||||||
using TINK.Model.Services.CopriApi;
|
using TINK.Model.Services.CopriApi;
|
||||||
using TINK.Repository;
|
using TINK.Repository;
|
||||||
|
using TINK.Repository.Response;
|
||||||
|
|
||||||
namespace TINK.Model.Connector
|
namespace TINK.Model.Connector
|
||||||
{
|
{
|
||||||
|
@ -34,16 +36,14 @@ namespace TINK.Model.Connector
|
||||||
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
public async Task<Result<StationsAndBikesContainer>> GetBikesAndStationsAsync()
|
||||||
{
|
{
|
||||||
var stationResponse = await server.GetStationsAsync();
|
var stationResponse = await server.GetStationsAsync();
|
||||||
var bikesAvailableResponse = await server.GetBikesAvailableAsync();
|
|
||||||
var bikesOccupiedResponse = await server.GetBikesOccupiedAsync();
|
|
||||||
|
|
||||||
return new Result<StationsAndBikesContainer>(
|
return new Result<StationsAndBikesContainer>(
|
||||||
typeof(CopriCallsMonkeyStore),
|
typeof(CopriCallsMonkeyStore),
|
||||||
new StationsAndBikesContainer(
|
new StationsAndBikesContainer(
|
||||||
stationResponse.GetStationsAllMutable(),
|
stationResponse.GetStationsAllMutable(),
|
||||||
BikeCollectionFactory.GetBikesAll(
|
BikeCollectionFactory.GetBikesAll(
|
||||||
bikesAvailableResponse?.bikes?.Values,
|
null, // Bikes available are no more of interest because count of available bikes at each given station is was added to station object.
|
||||||
bikesOccupiedResponse?.bikes_occupied?.Values,
|
stationResponse.bikes_occupied?.Values ?? new Dictionary<string, BikeInfoReservedOrBooked>().Values,
|
||||||
Mail,
|
Mail,
|
||||||
DateTimeProvider,
|
DateTimeProvider,
|
||||||
Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
Bikes.BikeInfoNS.BC.DataSource.Cache)),
|
||||||
|
|
|
@ -7,9 +7,12 @@ using Serilog;
|
||||||
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
|
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
|
||||||
using TINK.Model.Services.CopriApi.ServerUris;
|
using TINK.Model.Services.CopriApi.ServerUris;
|
||||||
using TINK.Model.State;
|
using TINK.Model.State;
|
||||||
|
using TINK.Model.Stations.StationNS;
|
||||||
|
using TINK.Model.Stations.StationNS.Operator;
|
||||||
using TINK.Repository.Exception;
|
using TINK.Repository.Exception;
|
||||||
using TINK.Repository.Response;
|
using TINK.Repository.Response;
|
||||||
using TINK.Repository.Response.Stations.Station;
|
using TINK.Repository.Response.Stations.Station;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace TINK.Model.Connector
|
namespace TINK.Model.Connector
|
||||||
{
|
{
|
||||||
|
@ -388,5 +391,52 @@ namespace TINK.Model.Connector
|
||||||
/// <param name="bike">Bike get to state from.</param>
|
/// <param name="bike">Bike get to state from.</param>
|
||||||
public static bool GetIsFeedbackPending(this BikeInfoAvailable bike)
|
public static bool GetIsFeedbackPending(this BikeInfoAvailable bike)
|
||||||
=> bike.co2saving != null;
|
=> 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>
|
/// <summary>
|
||||||
/// Gets all station for station provider and add them into station list.
|
/// Gets all station for station provider and add them into station list.
|
||||||
/// </summary>
|
/// </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)
|
public static StationDictionary GetStationsAllMutable(this StationsAvailableResponse stationsAllResponse)
|
||||||
{
|
{
|
||||||
// Get stations from Copri/ file/ memory, ....
|
// Get stations from Copri/ file/ memory, ....
|
||||||
|
@ -43,7 +43,7 @@ namespace TINK.Model.Connector.Updater
|
||||||
|
|
||||||
Version.TryParse(stationsAllResponse.copri_version, out Version copriVersion);
|
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)
|
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);
|
string.Format("Station id {0} is not unique.", station.Value.station), stationsAllResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
stations.Add(new Stations.StationNS.Station(
|
stations.Add(station.Value.GetStation());
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stations;
|
return stations;
|
||||||
|
|
|
@ -148,7 +148,7 @@ namespace TINK.Model.Settings
|
||||||
/// <returns>Logging level</returns>
|
/// <returns>Logging level</returns>
|
||||||
public static Uri GetCopriHostUri(this IDictionary<string, string> settingsJSON)
|
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)
|
if (!settingsJSON.TryGetValue(typeof(CopriServerUriList).ToString(), out string uriText)
|
||||||
|| string.IsNullOrEmpty(uriText))
|
|| string.IsNullOrEmpty(uriText))
|
||||||
{
|
{
|
||||||
|
@ -381,7 +381,7 @@ namespace TINK.Model.Settings
|
||||||
/// <returns>Active lock service name.</returns>
|
/// <returns>Active lock service name.</returns>
|
||||||
public static string GetActiveLockService(this IDictionary<string, string> settingsJSON)
|
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)
|
if (!settingsJSON.TryGetValue(typeof(ILocksService).Name, out string activeLockService)
|
||||||
|| string.IsNullOrEmpty(activeLockService))
|
|| string.IsNullOrEmpty(activeLockService))
|
||||||
{
|
{
|
||||||
|
@ -418,7 +418,7 @@ namespace TINK.Model.Settings
|
||||||
/// <returns>Active lock service name.</returns>
|
/// <returns>Active lock service name.</returns>
|
||||||
public static string GetActiveGeolocationService(this IDictionary<string, string> settingsJSON)
|
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)
|
if (!settingsJSON.TryGetValue(typeof(IGeolocationService).Name, out string activeGeolocationService)
|
||||||
|| string.IsNullOrEmpty(activeGeolocationService))
|
|| string.IsNullOrEmpty(activeGeolocationService))
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,19 +10,27 @@ namespace TINK.Model.Stations
|
||||||
/// <summary> Holds the list of stations. </summary>
|
/// <summary> Holds the list of stations. </summary>
|
||||||
private readonly IDictionary<string, IStation> m_oStationDictionary;
|
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>
|
/// <summary> Count of stations. </summary>
|
||||||
public int Count { get { return m_oStationDictionary.Count; } }
|
public int Count { get { return m_oStationDictionary.Count; } }
|
||||||
|
|
||||||
public Version CopriVersion { get; }
|
public Version CopriVersion { get; }
|
||||||
|
|
||||||
/// <summary> Constructs a station dictionary object. </summary>
|
/// <summary> Constructs a station dictionary object. </summary>
|
||||||
/// <param name="p_oVersion">Version of copri- service.</param>
|
/// <param name="version">Version of copri- service.</param>
|
||||||
public StationDictionary(Version p_oVersion = null, IDictionary<string, IStation> p_oStations = null)
|
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
|
CopriVersion = version != null
|
||||||
? new Version(p_oVersion.Major, p_oVersion.Minor, p_oVersion.Revision, p_oVersion.Build)
|
? new Version(version.Major, version.Minor, version.Revision, version.Build)
|
||||||
: new Version(0, 0, 0, 0);
|
: new Version(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@ using TINK.Model.Stations.StationNS.Operator;
|
||||||
|
|
||||||
namespace TINK.Model.Stations.StationNS
|
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
|
public interface IStation
|
||||||
{
|
{
|
||||||
/// <summary> Holds the unique id of the station.c</summary>
|
/// <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>
|
/// <summary> Holds operator related data.</summary>
|
||||||
IData OperatorData { get; }
|
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>
|
/// <summary> Holds operator related data.</summary>
|
||||||
public IData OperatorData => new Data();
|
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>
|
/// <param name="stationName">Name of the station.</param>
|
||||||
public Station(
|
public Station(
|
||||||
string id,
|
string id,
|
||||||
IEnumerable<string> group,
|
IEnumerable<string> group = null,
|
||||||
IPosition position,
|
IPosition position = null,
|
||||||
string stationName = "",
|
string stationName = "",
|
||||||
Data operatorData = null)
|
IData operatorData = null,
|
||||||
|
IBikeGroupCol bikeGropCol = null)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Group = group ?? throw new ArgumentException("Can not construct station object. Group of stations must not be null.");
|
Group = group ?? throw new ArgumentException("Can not construct station object. Group of stations must not be null.");
|
||||||
Position = position;
|
Position = position;
|
||||||
StationName = stationName ?? string.Empty;
|
StationName = stationName ?? string.Empty;
|
||||||
OperatorData = operatorData ?? new Data();
|
OperatorData = operatorData ?? new Data();
|
||||||
|
BikeGroups = bikeGropCol ?? new BikeGroupCol();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Holds the unique id of the station.c</summary>
|
/// <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>
|
/// <summary> Holds operator related info.</summary>
|
||||||
public IData OperatorData { get; }
|
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>
|
/// <summary> Holds available app themes.</summary>
|
||||||
public IServicesContainer<IGeolocationService> GeolocationServices { get; }
|
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; }
|
public AppFlavor Flavor { get; private set; }
|
||||||
|
|
||||||
/// <summary> Manages the different types of LocksService objects.</summary>
|
/// <summary> Manages the different types of LocksService objects.</summary>
|
||||||
|
@ -418,7 +418,7 @@ namespace TINK.Model
|
||||||
private LoggingLevelSwitch m_oLoggingLevelSwitch;
|
private LoggingLevelSwitch m_oLoggingLevelSwitch;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Object to allow swithing logging level
|
/// Object to allow switching logging level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LoggingLevelSwitch Level
|
public LoggingLevelSwitch Level
|
||||||
{
|
{
|
||||||
|
@ -448,7 +448,7 @@ namespace TINK.Model
|
||||||
return;
|
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;
|
Level.MinimumLevel = minimumLevel;
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ namespace TINK.Model
|
||||||
var sourceContex = e.Properties[Constants.SourceContextPropertyName].ToString();
|
var sourceContex = e.Properties[Constants.SourceContextPropertyName].ToString();
|
||||||
|
|
||||||
if ((e.Level == LogEventLevel.Information) &&
|
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. */ )))
|
|| sourceContex.Contains(typeof(ViewModel.Bikes.Bike.BluetoothLock.RequestHandler.Base).Namespace /* Log info-level messages to provide context for bluetooth log. */ )))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -687,6 +687,11 @@ namespace TINK.Model
|
||||||
AppResources.ChangeLog_3_0_363_MK_SB,
|
AppResources.ChangeLog_3_0_363_MK_SB,
|
||||||
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
|
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>
|
/// <summary> Manges the whats new information.</summary>
|
||||||
|
|
|
@ -1459,7 +1459,7 @@ namespace TINK.MultilingualResources {
|
||||||
///1. close app,
|
///1. close app,
|
||||||
///2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
|
///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.
|
///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>
|
/// </summary>
|
||||||
public static string ErrorBookedSearchMessageEscalationLevel2 {
|
public static string ErrorBookedSearchMessageEscalationLevel2 {
|
||||||
get {
|
get {
|
||||||
|
|
|
@ -761,7 +761,7 @@ Alternativ:
|
||||||
1. App schließen,
|
1. App schließen,
|
||||||
2. auf den Knopf oben am Schloss kurz drücken und sofort loslassen, sobald Knopf zu blinken beginnt,
|
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.
|
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>
|
||||||
<data name="ChangeLog3_0_278" xml:space="preserve">
|
<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>
|
<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>
|
<value>Starte Miete beenden...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExceptionTextWebConnectFailureException" xml:space="preserve">
|
<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>
|
||||||
<data name="ChangeLog3_0_289" xml:space="preserve">
|
<data name="ChangeLog3_0_289" xml:space="preserve">
|
||||||
<value>Flyout-Menü Überschift verschönert.</value>
|
<value>Flyout-Menü Überschift verschönert.</value>
|
||||||
|
|
|
@ -869,7 +869,7 @@ Alternative:
|
||||||
1. close app,
|
1. close app,
|
||||||
2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
|
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.
|
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>
|
||||||
<data name="ChangeLog3_0_278" xml:space="preserve">
|
<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>
|
<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">
|
<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">
|
<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>
|
<header>
|
||||||
|
@ -1026,14 +1026,14 @@ Alternative:
|
||||||
1. close app,
|
1. close app,
|
||||||
2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
|
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.
|
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!
|
<target state="translated">Es kann weiterhin keine Verbindung zwischen Ihrem mobilen Gerät und dem Schloss aufgebaut werden. Rufen Sie den Betreiber an!
|
||||||
|
|
||||||
Alternativ:
|
Alternativ:
|
||||||
1. App schließen,
|
1. App schließen,
|
||||||
2. auf den Knopf oben am Schloss kurz drücken und sofort loslassen, sobald Knopf zu blinken beginnt,
|
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.
|
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>
|
||||||
<trans-unit id="ChangeLog3_0_278" translate="yes" xml:space="preserve">
|
<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>
|
<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>
|
||||||
<trans-unit id="ExceptionTextWebConnectFailureException" translate="yes" xml:space="preserve">
|
<trans-unit id="ExceptionTextWebConnectFailureException" translate="yes" xml:space="preserve">
|
||||||
<source>Is WIFI/mobile network available and mobile data activated?</source>
|
<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>
|
||||||
<trans-unit id="ChangeLog3_0_289" translate="yes" xml:space="preserve">
|
<trans-unit id="ChangeLog3_0_289" translate="yes" xml:space="preserve">
|
||||||
<source>Flyout menu header improved.</source>
|
<source>Flyout menu header improved.</source>
|
||||||
|
@ -1631,4 +1631,4 @@ Außerdem:<br/>
|
||||||
</group>
|
</group>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using TINK.Model.Connector;
|
using TINK.Model.Connector;
|
||||||
using TINK.Repository.Response;
|
using TINK.Repository.Response;
|
||||||
|
@ -22,7 +22,7 @@ namespace TINK.Repository
|
||||||
|
|
||||||
public static Version UnsupportedVersionUpper => UNSUPPORTEDFUTURECOPRIVERSIONUPPER;
|
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>
|
/// <typeparam name="T">Type of response object.</typeparam>
|
||||||
/// <param name="response">Response JSON.</param>
|
/// <param name="response">Response JSON.</param>
|
||||||
/// <param name="emptyResponseFactory">Factory providing default delegate.</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>
|
/// <summary> Gets reservation request (synonym: reservation == request == reservieren). </summary>
|
||||||
/// <param name="bikeId">Id of the bike to reserve.</param>
|
/// <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);
|
string DoReserve(string bikeId);
|
||||||
|
|
||||||
/// <summary> Gets request to cancel reservation. </summary>
|
/// <summary> Gets request to cancel reservation. </summary>
|
||||||
/// <param name="bikeId">Id of the bike to cancel reservation for.</param>
|
/// <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);
|
string DoCancelReservation(string bikeId);
|
||||||
|
|
||||||
/// <summary> Request to get keys. </summary>
|
/// <summary> Request to get keys. </summary>
|
||||||
|
@ -96,17 +96,17 @@ namespace TINK.Repository.Request
|
||||||
/// <summary> Gets request for returning the bike. </summary>
|
/// <summary> Gets request for returning the bike. </summary>
|
||||||
/// <param name="bikeId">Id of the bike to return.</param>
|
/// <param name="bikeId">Id of the bike to return.</param>
|
||||||
/// <param name="location">Geolocation of lock when returning bike.</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);
|
string DoReturn(string bikeId, LocationDto location);
|
||||||
|
|
||||||
/// <summary> Returns a bike and starts closing. </summary>
|
/// <summary> Returns a bike and starts closing. </summary>
|
||||||
/// <param name="bikeId">Id of the bike to return.</param>
|
/// <param name="bikeId">Id of the bike to return.</param>
|
||||||
/// <param name="smartDevice">Provides info about hard and software.</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);
|
string ReturnAndStartClosing(string bikeId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets request for submiting feedback to copri server.
|
/// Gets request for submitting feedback to copri server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bikeId">Id of the bike to which the feedback is related to.</param>
|
/// <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>
|
/// <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);
|
bool isBikeBroken = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets request for submiting mini survey to copri server.
|
/// Gets request for submitting mini survey to copri server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="answers">Collection of answers.</param>
|
/// <param name="answers">Collection of answers.</param>
|
||||||
string DoSubmitMiniSurvey(IDictionary<string, string> answers);
|
string DoSubmitMiniSurvey(IDictionary<string, string> answers);
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace TINK.Repository.Request
|
||||||
/// <summary> Returns a bike and starts closing. </summary>
|
/// <summary> Returns a bike and starts closing. </summary>
|
||||||
/// <param name="bikeId">Id of the bike to return.</param>
|
/// <param name="bikeId">Id of the bike to return.</param>
|
||||||
/// <param name="smartDevice">Provides info about hard and software.</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)
|
public string ReturnAndStartClosing(string bikeId)
|
||||||
=> throw new NotSupportedException();
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ namespace TINK.Repository.Request
|
||||||
=> throw new NotSupportedException();
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets request for submiting mini survey to copri server.
|
/// Gets request for submitting mini survey to copri server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="answers">Collection of answers.</param>
|
/// <param name="answers">Collection of answers.</param>
|
||||||
public string DoSubmitMiniSurvey(IDictionary<string, string> answers) =>
|
public string DoSubmitMiniSurvey(IDictionary<string, string> answers) =>
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace TINK.Repository.Request
|
||||||
private ISmartDevice SmartDevice { get; }
|
private ISmartDevice SmartDevice { get; }
|
||||||
|
|
||||||
/// <summary> Gets request to log user in. </summary>
|
/// <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="password">Password to log in.</param>
|
||||||
/// <param name="deviceId">Id specifying user and hardware.</param>
|
/// <param name="deviceId">Id specifying user and hardware.</param>
|
||||||
/// <remarks>Response which holds auth cookie <see cref="ResponseBase.authcookie"/></remarks>
|
/// <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>
|
/// <summary> Gets reservation request (synonym: reservation == request == reservieren). </summary>
|
||||||
/// <remarks> Operator specific call.</remarks>
|
/// <remarks> Operator specific call.</remarks>
|
||||||
/// <param name="bikeId">Id of the bike to reserve.</param>
|
/// <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)
|
public string DoReserve(string bikeId)
|
||||||
=> "request=booking_request" +
|
=> "request=booking_request" +
|
||||||
GetBikeIdParameter(bikeId) +
|
GetBikeIdParameter(bikeId) +
|
||||||
|
@ -107,7 +107,7 @@ namespace TINK.Repository.Request
|
||||||
/// <summary> Gets request to cancel reservation. </summary>
|
/// <summary> Gets request to cancel reservation. </summary>
|
||||||
/// <remarks> Operator specific call.</remarks>
|
/// <remarks> Operator specific call.</remarks>
|
||||||
/// <param name="bikeId">Id of the bike to cancel reservation for.</param>
|
/// <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)
|
public string DoCancelReservation(string bikeId)
|
||||||
=> "request=booking_cancel" +
|
=> "request=booking_cancel" +
|
||||||
GetBikeIdParameter(bikeId) +
|
GetBikeIdParameter(bikeId) +
|
||||||
|
@ -158,7 +158,7 @@ namespace TINK.Repository.Request
|
||||||
UiIsoLanguageNameParameter;
|
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>
|
/// <remarks> Operator specific call.</remarks>
|
||||||
/// <param name="bikeId">Id of the bike to book.</param>
|
/// <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>
|
/// <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>
|
/// <remarks> Operator specific call.</remarks>
|
||||||
/// <param name="bikeId">Id of bike to return.</param>
|
/// <param name="bikeId">Id of bike to return.</param>
|
||||||
/// <param name="geolocation">Geolocation of lock when returning bike.</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)
|
public string DoReturn(string bikeId, LocationDto geolocation)
|
||||||
=> "request=booking_update" +
|
=> "request=booking_update" +
|
||||||
GetBikeIdParameter(bikeId) +
|
GetBikeIdParameter(bikeId) +
|
||||||
|
@ -218,7 +218,7 @@ namespace TINK.Repository.Request
|
||||||
/// <summary> Returns a bike and starts closing. </summary>
|
/// <summary> Returns a bike and starts closing. </summary>
|
||||||
/// <param name="bikeId">Id of the bike to return.</param>
|
/// <param name="bikeId">Id of the bike to return.</param>
|
||||||
/// <param name="smartDevice">Provides info about hard and software.</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)
|
public string ReturnAndStartClosing(string bikeId)
|
||||||
=> "request=booking_update" +
|
=> "request=booking_update" +
|
||||||
GetBikeIdParameter(bikeId) +
|
GetBikeIdParameter(bikeId) +
|
||||||
|
@ -258,7 +258,7 @@ namespace TINK.Repository.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets request for submiting mini survey to copri server.
|
/// Gets request for submitting mini survey to copri server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="answers">Collection of answers.</param>
|
/// <param name="answers">Collection of answers.</param>
|
||||||
public string DoSubmitMiniSurvey(IDictionary<string, string> answers)
|
public string DoSubmitMiniSurvey(IDictionary<string, string> answers)
|
||||||
|
@ -313,7 +313,7 @@ namespace TINK.Repository.Request
|
||||||
|
|
||||||
/// <summary> Gets the geolocation parameter. </summary>
|
/// <summary> Gets the geolocation parameter. </summary>
|
||||||
/// <param name="geolocation">Geolocation or null.</param>
|
/// <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)
|
private static string GetLocationParameters(LocationDto geolocation)
|
||||||
{
|
{
|
||||||
if (geolocation == null)
|
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;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace TINK.Repository.Response.Stations.Station
|
namespace TINK.Repository.Response.Stations.Station
|
||||||
|
@ -28,5 +29,17 @@ namespace TINK.Repository.Response.Stations.Station
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public OperatorData operator_data { get; private set; }
|
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>
|
/// </summary>
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public Dictionary<string, StationInfo> stations { get; private set; }
|
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>
|
/// <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>
|
/// <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(
|
public static async Task OpenAync(
|
||||||
this ICachedCopriServer cachedServer,
|
this ICachedCopriServer cachedServer,
|
||||||
|
@ -70,11 +70,11 @@ namespace TINK.Services.CopriApi
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Books a bike and opens the lock.
|
/// Books a bike and opens the lock.
|
||||||
/// </summary>
|
/// </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="bike">Bike to book and open.</param>
|
||||||
/// <param name="mailAddress">Mail address of user which books bike.</param>
|
/// <param name="mailAddress">Mail address of user which books bike.</param>
|
||||||
public static async Task BookAndOpenAync(
|
public static async Task BookAndOpenAync(
|
||||||
this ICopriServerBase corpiServer,
|
this ICopriServerBase copriServer,
|
||||||
IBikeInfoMutable bike,
|
IBikeInfoMutable bike,
|
||||||
string mailAddress)
|
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.");
|
throw new ArgumentNullException(nameof(bike), "Can not book bike and open lock. No bike object available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(corpiServer is ICachedCopriServer cachedServer))
|
if (!(copriServer is ICachedCopriServer cachedServer))
|
||||||
throw new ArgumentNullException(nameof(corpiServer));
|
throw new ArgumentNullException(nameof(copriServer));
|
||||||
|
|
||||||
// Send command to open lock
|
// Send command to open lock
|
||||||
var response = bike.State.Value == Model.State.InUseStateEnum.Disposable
|
var response = bike.State.Value == Model.State.InUseStateEnum.Disposable
|
||||||
? (await corpiServer.BookAvailableAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id)
|
? (await copriServer.BookAvailableAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id)
|
||||||
: (await corpiServer.BookReservedAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id);
|
: (await copriServer.BookReservedAndStartOpeningAsync(bike.Id, bike.OperatorUri)).GetIsBookingResponseOk(bike.Id);
|
||||||
|
|
||||||
// Upated locking state.
|
// Upated locking state.
|
||||||
var lockingState = await cachedServer.GetOccupiedBikeLockStateAsync(bike.Id);
|
var lockingState = await cachedServer.GetOccupiedBikeLockStateAsync(bike.Id);
|
||||||
|
@ -128,17 +128,17 @@ namespace TINK.Services.CopriApi
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a bike and closes the lock.
|
/// Returns a bike and closes the lock.
|
||||||
/// </summary>
|
/// </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>
|
/// <param name="bike">Bike to close.</param>
|
||||||
public static async Task CloseAync(
|
public static async Task CloseAync(
|
||||||
this ICopriServerBase corpiServer,
|
this ICopriServerBase copriServer,
|
||||||
IBikeInfoMutable bike)
|
IBikeInfoMutable bike)
|
||||||
{
|
{
|
||||||
if (!(corpiServer is ICachedCopriServer cachedServer))
|
if (!(copriServer is ICachedCopriServer cachedServer))
|
||||||
throw new ArgumentNullException(nameof(corpiServer));
|
throw new ArgumentNullException(nameof(copriServer));
|
||||||
|
|
||||||
// Send command to close lock
|
// Send command to close lock
|
||||||
await corpiServer.UpdateLockingStateAsync(
|
await copriServer.UpdateLockingStateAsync(
|
||||||
bike.Id,
|
bike.Id,
|
||||||
Repository.Request.lock_state.locking,
|
Repository.Request.lock_state.locking,
|
||||||
bike.OperatorUri);
|
bike.OperatorUri);
|
||||||
|
@ -166,20 +166,20 @@ namespace TINK.Services.CopriApi
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a bike and closes the lock.
|
/// Returns a bike and closes the lock.
|
||||||
/// </summary>
|
/// </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="smartDevice">Smart device on which app runs on.</param>
|
||||||
/// <param name="mailAddress">Mail address of user which books bike.</param>
|
/// <param name="mailAddress">Mail address of user which books bike.</param>
|
||||||
public static async Task<BookingFinishedModel> ReturnAndCloseAync(
|
public static async Task<BookingFinishedModel> ReturnAndCloseAync(
|
||||||
this ICopriServerBase corpiServer,
|
this ICopriServerBase copriServer,
|
||||||
ISmartDevice smartDevice,
|
ISmartDevice smartDevice,
|
||||||
IBikeInfoMutable bike)
|
IBikeInfoMutable bike)
|
||||||
{
|
{
|
||||||
if (!(corpiServer is ICachedCopriServer cachedServer))
|
if (!(copriServer is ICachedCopriServer cachedServer))
|
||||||
throw new ArgumentNullException(nameof(corpiServer));
|
throw new ArgumentNullException(nameof(copriServer));
|
||||||
|
|
||||||
// Send command to open lock
|
// Send command to open lock
|
||||||
DoReturnResponse response =
|
DoReturnResponse response =
|
||||||
await corpiServer.ReturnAndStartClosingAsync(bike.Id, bike.OperatorUri);
|
await copriServer.ReturnAndStartClosingAsync(bike.Id, bike.OperatorUri);
|
||||||
|
|
||||||
// Upate booking state
|
// Upate booking state
|
||||||
bike.Load(Model.Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None);
|
bike.Load(Model.Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.None);
|
||||||
|
@ -209,21 +209,21 @@ namespace TINK.Services.CopriApi
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the locking state from copri.
|
/// Queries the locking state from copri.
|
||||||
/// </summary>
|
/// </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>
|
/// <param name="bikeId">Bike id to query lock state for.</param>
|
||||||
/// <returns>Locking state</returns>
|
/// <returns>Locking state</returns>
|
||||||
private static async Task<LockingState> GetLockStateAsync(
|
private static async Task<LockingState> GetLockStateAsync(
|
||||||
this ICachedCopriServer corpiServer,
|
this ICachedCopriServer copriServer,
|
||||||
string bikeId)
|
string bikeId)
|
||||||
{
|
{
|
||||||
// Querry reserved or booked bikes first for performance reasons.
|
// 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)
|
if (bikeReservedOrBooked != null)
|
||||||
{
|
{
|
||||||
return bikeReservedOrBooked.GetCopriLockingState();
|
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)
|
if (bikeAvailable != null)
|
||||||
{
|
{
|
||||||
return bikeAvailable.GetCopriLockingState();
|
return bikeAvailable.GetCopriLockingState();
|
||||||
|
@ -235,14 +235,14 @@ namespace TINK.Services.CopriApi
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the locking state of a occupied bike from copri.
|
/// Queries the locking state of a occupied bike from copri.
|
||||||
/// </summary>
|
/// </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>
|
/// <param name="bikeId">Bike id to query lock state for.</param>
|
||||||
/// <returns>Locking state if bike is still occupied, null otherwise.</returns>
|
/// <returns>Locking state if bike is still occupied, null otherwise.</returns>
|
||||||
private static async Task<LockingState?> GetOccupiedBikeLockStateAsync(
|
private static async Task<LockingState?> GetOccupiedBikeLockStateAsync(
|
||||||
this ICachedCopriServer corpiServer,
|
this ICachedCopriServer copriServer,
|
||||||
string bikeId)
|
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)
|
if (bikeReservedOrBooked != null)
|
||||||
{
|
{
|
||||||
return bikeReservedOrBooked.GetCopriLockingState();
|
return bikeReservedOrBooked.GetCopriLockingState();
|
||||||
|
|
|
@ -3,15 +3,37 @@ using TINK.Model.Stations;
|
||||||
|
|
||||||
namespace TINK.Model.Services.CopriApi
|
namespace TINK.Model.Services.CopriApi
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds stations and bikes.
|
||||||
|
/// </summary>
|
||||||
public class StationsAndBikesContainer
|
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;
|
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 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>
|
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<InternalsVisibleTo Include="TestShareeLib" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</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;
|
BikesViewModel.ActionText = AppResources.ActivityTextRentingBike;
|
||||||
IsConnected = IsConnectedDelegate();
|
IsConnected = IsConnectedDelegate();
|
||||||
try
|
try
|
||||||
|
|
|
@ -204,7 +204,7 @@ namespace TINK.ViewModel.Contact
|
||||||
? $"{stationId}" // there is a station marker with index letter for given station id
|
? $"{stationId}" // there is a station marker with index letter for given station id
|
||||||
: "Open"; // there is no station marker. Use open marker.
|
: "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)}";
|
var l_iName = $"{indexPartPrefix.ToString().PadLeft(2, '0')}_{colorPartPrefix}{(DeviceInfo.Platform == DevicePlatform.Android ? ".png" : string.Empty)}";
|
||||||
try
|
try
|
||||||
|
@ -234,7 +234,7 @@ namespace TINK.ViewModel.Contact
|
||||||
/// <summary> Gets the color related part of the ressrouce name.</summary>
|
/// <summary> Gets the color related part of the ressrouce name.</summary>
|
||||||
/// <param name="color">Color to get name for.</param>
|
/// <param name="color">Color to get name for.</param>
|
||||||
/// <returns>Resource name.</returns>
|
/// <returns>Resource name.</returns>
|
||||||
private static string GetRessourceNameColorPart(Color color)
|
private static string GetResourceNameColorPart(Color color)
|
||||||
{
|
{
|
||||||
if (color == Color.Blue)
|
if (color == Color.Blue)
|
||||||
{
|
{
|
||||||
|
@ -395,7 +395,7 @@ namespace TINK.ViewModel.Contact
|
||||||
|
|
||||||
var colors = GetStationColors(
|
var colors = GetStationColors(
|
||||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
Pins.Select(x => x.Tag.ToString()).ToList(),
|
||||||
resultStationsAndBikes.Response.Bikes);
|
resultStationsAndBikes.Response.BikesOccupied);
|
||||||
|
|
||||||
// Update pins color form count of bikes located at station.
|
// Update pins color form count of bikes located at station.
|
||||||
UpdatePinsColor(colors);
|
UpdatePinsColor(colors);
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace TINK.ViewModel.Contact
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
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; }
|
bool IsSiteCachingOn { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -64,7 +64,7 @@ namespace TINK.ViewModel.Contact
|
||||||
|
|
||||||
/// <summary> Constructs view model.</summary>
|
/// <summary> Constructs view model.</summary>
|
||||||
/// <param name="isSiteCachingOn">Set of user permissions</param>
|
/// <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>
|
/// <param name="query">Object to query resources path values if required.</param>
|
||||||
public FeesAndBikesPageViewModel(
|
public FeesAndBikesPageViewModel(
|
||||||
string hostName,
|
string hostName,
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace TINK.ViewModel.Info
|
||||||
/// <summary> Holds the name of the host.</summary>
|
/// <summary> Holds the name of the host.</summary>
|
||||||
private string HostName { get; }
|
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; }
|
bool IsSiteCachingOn { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -74,11 +74,11 @@ namespace TINK.ViewModel.Info
|
||||||
|
|
||||||
/// <summary> Constructs Info view model</summary>
|
/// <summary> Constructs Info view model</summary>
|
||||||
/// <param name="hostName">Name of the host to get html resources from.</param>
|
/// <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="isSiteCachingOn">Holds value whether site caching is on or off.</param>
|
||||||
/// <param name="agbResourcePath"> Agb resouce path received from backend.</param>
|
/// <param name="agbResourcePath"> Agb resource path received from backend.</param>
|
||||||
/// <param name="privacyResourcePath"> Privacy resouce path received from backend.</param>
|
/// <param name="privacyResourcePath"> Privacy resource path received from backend.</param>
|
||||||
/// <param name="impressResourcePath"> Impress resouce path received from backend.</param>
|
/// <param name="impressResourcePath"> Impress resource 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="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="queryProvider">Object to query resources urls object from backend if required.</param>
|
||||||
/// <param name="updateUrlsAction">Action to update shared resources urls object</param>
|
/// <param name="updateUrlsAction">Action to update shared resources urls object</param>
|
||||||
public InfoPageViewModel(
|
public InfoPageViewModel(
|
||||||
|
@ -102,7 +102,7 @@ namespace TINK.ViewModel.Info
|
||||||
InfoAgb = new HtmlWebViewSource { Html = "<html>Loading...</html>" };
|
InfoAgb = new HtmlWebViewSource { Html = "<html>Loading...</html>" };
|
||||||
|
|
||||||
ResourceProvider = resourceProvider
|
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>
|
/// <summary> Called when page is shown. </summary>
|
||||||
|
@ -147,7 +147,7 @@ namespace TINK.ViewModel.Info
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(PrivacyResourcePath))
|
if (string.IsNullOrEmpty(PrivacyResourcePath))
|
||||||
{
|
{
|
||||||
// Information to access ressource is missing
|
// Information to access resource is missing
|
||||||
return new HtmlWebViewSource
|
return new HtmlWebViewSource
|
||||||
{
|
{
|
||||||
Html = await Task.FromResult(ViewModelHelper.FromBody("No privacy resource available. Resource path is null or empty."))
|
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))
|
if (string.IsNullOrEmpty(ImpressResourcePath))
|
||||||
{
|
{
|
||||||
// Information to access ressource is missing
|
// Information to access resource is missing
|
||||||
return new HtmlWebViewSource
|
return new HtmlWebViewSource
|
||||||
{
|
{
|
||||||
Html = await Task.FromResult(ViewModelHelper.FromBody("No impress resource available. Resource path is null or empty."))
|
Html = await Task.FromResult(ViewModelHelper.FromBody("No impress resource available. Resource path is null or empty."))
|
||||||
|
|
|
@ -329,7 +329,7 @@ namespace TINK.ViewModel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swich to map page
|
// Switch to map page
|
||||||
#if USEFLYOUT
|
#if USEFLYOUT
|
||||||
m_oViewService.ShowPage(ViewTypes.BikeInfoCarouselPage, AppResources.MarkingLoginInstructions);
|
m_oViewService.ShowPage(ViewTypes.BikeInfoCarouselPage, AppResources.MarkingLoginInstructions);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -22,11 +22,11 @@ using TINK.Services.Permissions;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using TINK.MultilingualResources;
|
using TINK.MultilingualResources;
|
||||||
using TINK.Services.BluetoothLock;
|
|
||||||
using TINK.Repository;
|
using TINK.Repository;
|
||||||
using TINK.Services.Geolocation;
|
using TINK.Services.Geolocation;
|
||||||
using TINK.Model.State;
|
using TINK.Model.State;
|
||||||
using TINK.ViewModel.Bikes;
|
using TINK.Model.Bikes.BikeInfoNS.BC;
|
||||||
|
using TINK.Model.Stations.StationNS;
|
||||||
|
|
||||||
#if !TRYNOTBACKSTYLE
|
#if !TRYNOTBACKSTYLE
|
||||||
#endif
|
#endif
|
||||||
|
@ -263,7 +263,7 @@ namespace TINK.ViewModel.Map
|
||||||
? $"{stationId}" // there is a station marker with index letter for given station id
|
? $"{stationId}" // there is a station marker with index letter for given station id
|
||||||
: "Open"; // there is no station marker. Use open marker.
|
: "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)}";
|
var name = $"{indexPartPrefix.ToString().PadLeft(2, '0')}_{colorPartPrefix}{(DeviceInfo.Platform == DevicePlatform.Android ? ".png" : string.Empty)}";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -306,7 +306,7 @@ namespace TINK.ViewModel.Map
|
||||||
/// <summary> Gets the color related part of the ressrouce name.</summary>
|
/// <summary> Gets the color related part of the ressrouce name.</summary>
|
||||||
/// <param name="color">Color to get name for.</param>
|
/// <param name="color">Color to get name for.</param>
|
||||||
/// <returns>Resource name.</returns>
|
/// <returns>Resource name.</returns>
|
||||||
private static string GetRessourceNameColorPart(Color color)
|
private static string GetResourceNameColorPart(Color color)
|
||||||
{
|
{
|
||||||
if (color == Color.Blue)
|
if (color == Color.Blue)
|
||||||
{
|
{
|
||||||
|
@ -394,7 +394,8 @@ namespace TINK.ViewModel.Map
|
||||||
|
|
||||||
var colors = GetStationColors(
|
var colors = GetStationColors(
|
||||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
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.
|
// Update pins color form count of bikes located at station.
|
||||||
UpdatePinsColor(colors);
|
UpdatePinsColor(colors);
|
||||||
|
@ -402,7 +403,7 @@ namespace TINK.ViewModel.Map
|
||||||
Log.ForContext<MapPageViewModel>().Verbose("Update pins color done.");
|
Log.ForContext<MapPageViewModel>().Verbose("Update pins color done.");
|
||||||
|
|
||||||
// Load MyBikes Count -> MyBikes Icon/Button
|
// 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.
|
// Move and scale before getting stations and bikes which takes some time.
|
||||||
ActionText = AppResources.ActivityTextCenterMap;
|
ActionText = AppResources.ActivityTextCenterMap;
|
||||||
|
@ -655,7 +656,7 @@ namespace TINK.ViewModel.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load MyBikes Count -> MyBikes Icon/Button
|
// Load MyBikes Count -> MyBikes Icon/Button
|
||||||
GetMyBikesCount(resultStationsAndBikes.Response.Bikes);
|
GetMyBikesCount(resultStationsAndBikes.Response.BikesOccupied);
|
||||||
|
|
||||||
// Check if there are already any pins to the map.
|
// Check if there are already any pins to the map.
|
||||||
// If no initialize pins.
|
// If no initialize pins.
|
||||||
|
@ -670,7 +671,8 @@ namespace TINK.ViewModel.Map
|
||||||
// Set/ update pins colors.
|
// Set/ update pins colors.
|
||||||
var l_oColors = GetStationColors(
|
var l_oColors = GetStationColors(
|
||||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
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.
|
// Update pins color form count of bikes located at station.
|
||||||
TinkApp.PostAction(
|
TinkApp.PostAction(
|
||||||
|
@ -758,10 +760,13 @@ namespace TINK.ViewModel.Map
|
||||||
/// Gets the list of station color for all stations.
|
/// Gets the list of station color for all stations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stationsId">Station id list to get color for.</param>
|
/// <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>
|
/// <returns></returns>
|
||||||
private static IList<Color> GetStationColors(
|
internal static IList<Color> GetStationColors(
|
||||||
IEnumerable<string> stationsId,
|
IEnumerable<string> stationsId,
|
||||||
BikeCollection bikesAll)
|
IEnumerable<IStation> stations,
|
||||||
|
IEnumerable<BikeInfo> bikesReserved)
|
||||||
{
|
{
|
||||||
if (stationsId == null)
|
if (stationsId == null)
|
||||||
{
|
{
|
||||||
|
@ -769,11 +774,14 @@ namespace TINK.ViewModel.Map
|
||||||
return new List<Color>();
|
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 stations info available to get count of bikes available to determine whether a pin is green or not.");
|
||||||
Log.ForContext<MapPageViewModel>().Error("No bikes available to determine pins color.");
|
}
|
||||||
return new List<Color>(stationsId.Select(x => Color.Blue));
|
|
||||||
|
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.
|
// Get state for each station.
|
||||||
|
@ -781,15 +789,14 @@ namespace TINK.ViewModel.Map
|
||||||
foreach (var stationId in stationsId)
|
foreach (var stationId in stationsId)
|
||||||
{
|
{
|
||||||
// Get color of given station.
|
// Get color of given station.
|
||||||
var bikesAtStation = bikesAll.Where(x => x.StationId == stationId).ToList();
|
if (bikesReserved?.Where(x => x.StationId == stationId).Count() > 0)
|
||||||
if (bikesAtStation.FirstOrDefault(x => x.State.Value.IsOccupied()) != null)
|
|
||||||
{
|
{
|
||||||
// There is at least one requested or booked bike
|
// There is at least one requested or booked bike
|
||||||
colors.Add(Color.LightBlue);
|
colors.Add(Color.LightBlue);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bikesAtStation.ToList().Count > 0)
|
if (stations?.FirstOrDefault(x => x.Id == stationId)?.AvailableBikesCount > 0)
|
||||||
{
|
{
|
||||||
// There is at least one bike available
|
// There is at least one bike available
|
||||||
colors.Add(Color.Green);
|
colors.Add(Color.Green);
|
||||||
|
@ -1030,7 +1037,8 @@ namespace TINK.ViewModel.Map
|
||||||
Log.ForContext<MapPageViewModel>().Verbose("Starting update pins color on toggle...");
|
Log.ForContext<MapPageViewModel>().Verbose("Starting update pins color on toggle...");
|
||||||
var l_oColors = GetStationColors(
|
var l_oColors = GetStationColors(
|
||||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
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.
|
// Update pins color form count of bikes located at station.
|
||||||
UpdatePinsColor(l_oColors);
|
UpdatePinsColor(l_oColors);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -66,12 +66,12 @@ namespace TINK.Model.Connector
|
||||||
{
|
{
|
||||||
NextActiveUri = new Uri(serverTextToUri.ContainsKey(value) ? serverTextToUri[value] : value);
|
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>
|
/// <summary> Holds the description of the picker, i.e. binds to label Text.</summary>
|
||||||
public string CorpiServerUriDescription
|
public string CopriServerUriDescription
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,21 +65,21 @@ namespace TINK.ViewModel
|
||||||
/// <summary> Reference on the tink app instance. </summary>
|
/// <summary> Reference on the tink app instance. </summary>
|
||||||
private ITinkApp TinkApp { get; }
|
private ITinkApp TinkApp { get; }
|
||||||
|
|
||||||
IServicesContainer<IGeolocationService> GeoloctionServicesContainer { get; }
|
IServicesContainer<IGeolocationService> GeolocationServicesContainer { get; }
|
||||||
|
|
||||||
/// <summary> Constructs a settings page view model object.</summary>
|
/// <summary> Constructs a settings page view model object.</summary>
|
||||||
/// <param name="tinkApp"> Reference to tink app model.</param>
|
/// <param name="tinkApp"> Reference to tink app model.</param>
|
||||||
/// <param name="geoloctionServicesContainer"></param>
|
/// <param name="geolocationServicesContainer"></param>
|
||||||
/// <param name="viewService">Interface to view</param>
|
/// <param name="viewService">Interface to view</param>
|
||||||
public SettingsPageViewModel(
|
public SettingsPageViewModel(
|
||||||
ITinkApp tinkApp,
|
ITinkApp tinkApp,
|
||||||
IServicesContainer<IGeolocationService> geoloctionServicesContainer,
|
IServicesContainer<IGeolocationService> geolocationServicesContainer,
|
||||||
IViewService viewService)
|
IViewService viewService)
|
||||||
{
|
{
|
||||||
TinkApp = tinkApp
|
TinkApp = tinkApp
|
||||||
?? throw new ArgumentException("Can not instantiate settings page view model- object. No tink app object available.");
|
?? 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.");
|
?? throw new ArgumentException($"Can not instantiate {nameof(SettingsPageViewModel)}- object. Geolocation services container object must not be null.");
|
||||||
|
|
||||||
m_oViewService = viewService
|
m_oViewService = viewService
|
||||||
|
@ -175,14 +175,14 @@ namespace TINK.ViewModel
|
||||||
TinkApp.LocksServices.Active.GetType().FullName));
|
TinkApp.LocksServices.Active.GetType().FullName));
|
||||||
|
|
||||||
GeolocationServices = new ServicesViewModel(
|
GeolocationServices = new ServicesViewModel(
|
||||||
GeoloctionServicesContainer.Select(x => x.GetType().FullName),
|
GeolocationServicesContainer.Select(x => x.GetType().FullName),
|
||||||
new Dictionary<string, string> {
|
new Dictionary<string, string> {
|
||||||
{ typeof(LastKnownGeolocationService).FullName, "LastKnowGeolocation" },
|
{ typeof(LastKnownGeolocationService).FullName, "LastKnowGeolocation" },
|
||||||
{ typeof(GeolocationAccuracyMediumService).FullName, "Medium Accuracy" },
|
{ typeof(GeolocationAccuracyMediumService).FullName, "Medium Accuracy" },
|
||||||
{ typeof(GeolocationAccuracyHighService).FullName, "High Accuracy" },
|
{ typeof(GeolocationAccuracyHighService).FullName, "High Accuracy" },
|
||||||
{ typeof(GeolocationAccuracyBestService).FullName, "Best Accuracy" },
|
{ typeof(GeolocationAccuracyBestService).FullName, "Best Accuracy" },
|
||||||
{ typeof(SimulatedGeolocationService).FullName, "Simulation-AlwaysSamePosition" } },
|
{ typeof(SimulatedGeolocationService).FullName, "Simulation-AlwaysSamePosition" } },
|
||||||
GeoloctionServicesContainer.Active.GetType().FullName);
|
GeolocationServicesContainer.Active.GetType().FullName);
|
||||||
|
|
||||||
StartupSettings = new PickerViewModel(
|
StartupSettings = new PickerViewModel(
|
||||||
new Dictionary<string, string> {
|
new Dictionary<string, string> {
|
||||||
|
@ -310,7 +310,7 @@ namespace TINK.ViewModel
|
||||||
|
|
||||||
TinkApp.LocksServices.SetActive(LocksServices.Services.Active);
|
TinkApp.LocksServices.SetActive(LocksServices.Services.Active);
|
||||||
|
|
||||||
GeoloctionServicesContainer.SetActive(GeolocationServices.Active);
|
GeolocationServicesContainer.SetActive(GeolocationServices.Active);
|
||||||
|
|
||||||
TinkApp.LocksServices.SetTimeOut(TimeSpan.FromSeconds(LocksServices.ConnectTimeoutSec));
|
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)
|
public static string GetErrorMessage(this Exception exception)
|
||||||
{
|
{
|
||||||
if (exception == null)
|
if (exception == null)
|
||||||
|
@ -239,8 +239,8 @@ namespace TINK.ViewModel
|
||||||
|
|
||||||
/// <summary> Called when page is shown. </summary>
|
/// <summary> Called when page is shown. </summary>
|
||||||
/// <param name="resourceUrl">Url to load data from.</param>
|
/// <param name="resourceUrl">Url to load data from.</param>
|
||||||
/// <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="resourceProvider"> Provides resource from embedded ressources.</param>
|
/// <param name="resourceProvider"> Provides resource from embedded resources.</param>
|
||||||
public static async Task<string> GetSource(
|
public static async Task<string> GetSource(
|
||||||
string resourceUrl,
|
string resourceUrl,
|
||||||
bool isSiteCachingOn,
|
bool isSiteCachingOn,
|
||||||
|
@ -271,7 +271,7 @@ namespace TINK.ViewModel
|
||||||
// An error occurred getting resource from web
|
// An error occurred getting resource from web
|
||||||
htmlContent = Barrel.Current.Exists(resourceUrl)
|
htmlContent = Barrel.Current.Exists(resourceUrl)
|
||||||
? Barrel.Current.Get<string>(key: resourceUrl) // Get from MonkeyCache
|
? 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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -280,7 +280,7 @@ namespace TINK.ViewModel
|
||||||
break;
|
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>";
|
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>
|
/// <summary> Holds the name of the host.</summary>
|
||||||
private string HostName { get; }
|
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; }
|
bool IsSiteCachingOn { get; }
|
||||||
|
|
||||||
/// <summary> Constructs AGB view model</summary>
|
/// <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="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>
|
/// <param name="viewService">View service to close page.</param>
|
||||||
public AgbViewModel(
|
public AgbViewModel(
|
||||||
string hostName,
|
string hostName,
|
||||||
|
@ -37,7 +37,7 @@ namespace TINK.ViewModel.WhatsNew.Agb
|
||||||
?? throw new ArgumentException($"Can not instantiate {typeof(WhatsNewViewModel)}-object. No view available.");
|
?? throw new ArgumentException($"Can not instantiate {typeof(WhatsNewViewModel)}-object. No view available.");
|
||||||
|
|
||||||
ResourceProvider = resourceProvider
|
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>
|
/// <summary> Gets the platfrom specific prefix. </summary>
|
||||||
|
|
|
@ -11,7 +11,7 @@ using TINK.Repository.Response;
|
||||||
using TINK.Repository.Response.Stations;
|
using TINK.Repository.Response.Stations;
|
||||||
using static TINK.Repository.CopriCallsMemory;
|
using static TINK.Repository.CopriCallsMemory;
|
||||||
|
|
||||||
namespace TestTINKLib.Mocks.Connector
|
namespace TestFramework.Repository
|
||||||
{
|
{
|
||||||
/// <summary> Allows use of memory for retrieving defined responses.</summary>
|
/// <summary> Allows use of memory for retrieving defined responses.</summary>
|
||||||
public class CopriCallsCacheMemory : ICopriCache
|
public class CopriCallsCacheMemory : ICopriCache
|
||||||
|
@ -111,7 +111,7 @@ namespace TestTINKLib.Mocks.Connector
|
||||||
public Task<DoReturnResponse> ReturnAndStartClosingAsync(
|
public Task<DoReturnResponse> ReturnAndStartClosingAsync(
|
||||||
string bikeId,
|
string bikeId,
|
||||||
Uri operatorUri)
|
Uri operatorUri)
|
||||||
=> throw new System.Exception("Rückgabe mit mit Schloss schließen Befehl Offlinemodus nicht möglich!");
|
=> throw new Exception("Rückgabe mit mit Schloss schließen Befehl Offlinemodus nicht möglich!");
|
||||||
|
|
||||||
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string bikeId, int? currentChargeBars, string message, bool isBikeBroken, Uri operatorUri)
|
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string bikeId, int? currentChargeBars, string message, bool isBikeBroken, Uri operatorUri)
|
||||||
=> throw new NotImplementedException();
|
=> throw new NotImplementedException();
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TestFramework.Repository;
|
|
||||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||||
using TINK.Model.Connector;
|
using TINK.Model.Connector;
|
||||||
using TINK.Model.Services.CopriApi;
|
using TINK.Model.Services.CopriApi;
|
||||||
|
@ -9,7 +8,7 @@ using TINK.Repository.Request;
|
||||||
using TINK.Repository.Response;
|
using TINK.Repository.Response;
|
||||||
using TINK.Repository.Response.Stations;
|
using TINK.Repository.Response.Stations;
|
||||||
|
|
||||||
namespace TestFramework.Services.CopriApi.Connector
|
namespace TestFramework.Repository
|
||||||
{
|
{
|
||||||
/// <summary> Allows use of memory for retrieving defined responses.</summary>
|
/// <summary> Allows use of memory for retrieving defined responses.</summary>
|
||||||
public class CopriCallsCacheMemory001 : ICopriCache
|
public class CopriCallsCacheMemory001 : ICopriCache
|
|
@ -0,0 +1,126 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||||
|
using TINK.Model.Connector;
|
||||||
|
using TINK.Repository.Request;
|
||||||
|
using TINK.Repository.Response.Stations;
|
||||||
|
using TINK.Repository.Response;
|
||||||
|
using TINK.Model.Services.CopriApi;
|
||||||
|
|
||||||
|
namespace TestFramework.Repository
|
||||||
|
{
|
||||||
|
public class CopriCallsCacheMemory001v2NotLoggedIn : ICopriCache
|
||||||
|
{
|
||||||
|
private CopriCallsMemory001v2NotLoggedIn server;
|
||||||
|
|
||||||
|
public CopriCallsCacheMemory001v2NotLoggedIn(string sessionCookie = null)
|
||||||
|
{
|
||||||
|
server = new CopriCallsMemory001v2NotLoggedIn(sessionCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsStationsExpired => true;
|
||||||
|
|
||||||
|
public bool IsBikesAvailableExpired => true;
|
||||||
|
|
||||||
|
public bool IsBikesOccupiedExpired => true;
|
||||||
|
|
||||||
|
public bool IsConnected => server.IsConnected;
|
||||||
|
|
||||||
|
public string SessionCookie => server.SessionCookie;
|
||||||
|
|
||||||
|
public string MerchantId => server.MerchantId;
|
||||||
|
|
||||||
|
public void AddToCache(StationsAvailableResponse stations)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddToCache(BikesAvailableResponse bikes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddToCache(BikesReservedOccupiedResponse bikes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<AuthorizationResponse> DoAuthorizationAsync(string p_strMailAddress, string p_strPassword, string p_strDeviceId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<AuthorizationoutResponse> DoAuthoutAsync()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ReservationBookingResponse> DoReserveAsync(string bikeId, Uri operatorUri)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ReservationCancelReturnResponse> DoCancelReservationAsync(string p_iBikeId, Uri operatorUri)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ReservationBookingResponse> CalculateAuthKeysAsync(string bikeId, Uri operatorUri)
|
||||||
|
=> throw new NotSupportedException();
|
||||||
|
|
||||||
|
public Task<ResponseBase> StartReturningBike(
|
||||||
|
string bikeId,
|
||||||
|
Uri operatorUri)
|
||||||
|
=> null;
|
||||||
|
|
||||||
|
public Task<ReservationBookingResponse> UpdateLockingStateAsync(
|
||||||
|
string bikeId,
|
||||||
|
lock_state state,
|
||||||
|
Uri operatorUri,
|
||||||
|
LocationDto geolocation,
|
||||||
|
double batteryPercentage,
|
||||||
|
IVersionInfo versionInfo)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Task<ReservationBookingResponse> DoBookAsync(Uri operatorUri, string bikeId, Guid guid, double batteryPercentage, LockingAction? nextAction = null)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Task<ReservationBookingResponse> BookAvailableAndStartOpeningAsync(string bikeId, Uri operatorUri)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Task<ReservationBookingResponse> BookReservedAndStartOpeningAsync(string bikeId, Uri operatorUri)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Task<DoReturnResponse> DoReturn(string bikeId, LocationDto location, Uri operatorUri)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Task<DoReturnResponse> ReturnAndStartClosingAsync(
|
||||||
|
string bikeId,
|
||||||
|
Uri operatorUri)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Task<SubmitFeedbackResponse> DoSubmitFeedback(string bikeId, int? currentChargeBars, string message, bool isBikeBroken, Uri operatorUri)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
/// <summary> Submits mini survey to copri server. </summary>
|
||||||
|
/// <param name="answers">Collection of answers.</param>
|
||||||
|
public Task<ResponseBase> DoSubmitMiniSurvey(IDictionary<string, string> answers)
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
|
public Task<BikesAvailableResponse> GetBikesAvailableAsync()
|
||||||
|
{
|
||||||
|
return server.GetBikesAvailableAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<BikesReservedOccupiedResponse> GetBikesOccupiedAsync()
|
||||||
|
{
|
||||||
|
return server.GetBikesOccupiedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<StationsAvailableResponse> GetStationsAsync()
|
||||||
|
{
|
||||||
|
return server.GetStationsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
TestFramework/Repository/CopriCallsMemory001v2.cs
Normal file
23
TestFramework/Repository/CopriCallsMemory001v2.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
using TINK.Repository;
|
||||||
|
|
||||||
|
namespace TestFramework.Repository
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds some COPRI responses for testing purposes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks> Holds some demo Mein konrad and LastenradBayern bikes
|
||||||
|
/// </remarks>
|
||||||
|
public class CopriCallsMemory001v2NotLoggedIn : CopriCallMemoryBase, ICopriServer
|
||||||
|
{
|
||||||
|
public CopriCallsMemory001v2NotLoggedIn(string sessionCookie = null, string merchantId = null) : base(
|
||||||
|
bikesAvailableResponseResource: "TestFramework.Repository.CopriCallsMemory001v2NotLoggedIn.BikesAvailableResponse.json",
|
||||||
|
bikesOccupiedResponseResoure: "TestFramework.Repository.CopriCallsMemory001v2NotLoggedIn.BikesOccupiedResponse.json",
|
||||||
|
authResponseResource: "TestFramework.Repository.CopriCallsMemory001v2NotLoggedIn.AuthorizationResponse.json",
|
||||||
|
authOutResponseResource: "TestFramework.Repository.CopriCallsMemory001v2NotLoggedIn.AuthoutResponse.json",
|
||||||
|
stationsResponseResource: "TestFramework.Repository.CopriCallsMemory001v2NotLoggedIn.StationsAvailable.json",
|
||||||
|
sessionCookie: sessionCookie,
|
||||||
|
merchantId: merchantId)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"shareejson": {
|
||||||
|
"clearing_cache": "0",
|
||||||
|
"privacy_html": "site/privacy.html",
|
||||||
|
"user_id": "javaminister@gmail.com",
|
||||||
|
"impress_html": "site/impress.html",
|
||||||
|
"tariff_info_html": "site/tariff_info_1.html",
|
||||||
|
"lang": "DE",
|
||||||
|
"last_used_operator": {
|
||||||
|
"operator_name": "sharee.bike | TeilRad GmbH",
|
||||||
|
"operator_hours": "B<>rozeiten: Montag, Mittwoch, Freitag 9-12 Uhr",
|
||||||
|
"operator_phone": "+49 761 45370097",
|
||||||
|
"operator_email": "hotline@sharee.bike",
|
||||||
|
"operator_color": "#009699"
|
||||||
|
},
|
||||||
|
"response": "authorization",
|
||||||
|
"agb_checked": "0",
|
||||||
|
"agb_html": "site/agb.html",
|
||||||
|
"response_text": "Herzlich willkommen im Fahrradmietsystem",
|
||||||
|
"bike_info_html": "site/bike_info.html",
|
||||||
|
"debuglevel": "1",
|
||||||
|
"uri_primary": "https://shareeapp-primary.copri.eu",
|
||||||
|
"response_state": "OK, nothing todo",
|
||||||
|
"new_authcoo": "1",
|
||||||
|
"user_tour": [],
|
||||||
|
"authcookie": "6103_112e96b36ba33de245943c5ffaf369cd_oiF2kahH",
|
||||||
|
"copri_version": "4.1.8.21",
|
||||||
|
"apiserver": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"user_group": []
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"shareejson": {
|
||||||
|
"copri_version": "4.1.8.21",
|
||||||
|
"authcookie": "1",
|
||||||
|
"user_tour": [],
|
||||||
|
"user_group": null,
|
||||||
|
"apiserver": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"debuglevel": "1",
|
||||||
|
"uri_primary": "https://shareeapp-primary.copri.eu",
|
||||||
|
"bike_info_html": "site/bike_info.html",
|
||||||
|
"response_state": "OK, logout",
|
||||||
|
"new_authcoo": "0",
|
||||||
|
"lang": "DE",
|
||||||
|
"last_used_operator": {
|
||||||
|
"operator_hours": "Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr",
|
||||||
|
"operator_name": "sharee.bike | TeilRad GmbH",
|
||||||
|
"operator_email": "hotline@sharee.bike",
|
||||||
|
"operator_phone": "+49 761 45370097",
|
||||||
|
"operator_color": "#009699"
|
||||||
|
},
|
||||||
|
"tariff_info_html": "site/tariff_info_1.html",
|
||||||
|
"impress_html": "site/impress.html",
|
||||||
|
"response_text": "Auf Wiedersehen.",
|
||||||
|
"agb_html": "site/agb.html",
|
||||||
|
"response": "authout",
|
||||||
|
"agb_checked": "0",
|
||||||
|
"privacy_html": "site/privacy.html",
|
||||||
|
"clearing_cache": "0",
|
||||||
|
"user_id": "javaminister@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,270 @@
|
||||||
|
{
|
||||||
|
"shareejson": {
|
||||||
|
"agb_checked": "1",
|
||||||
|
"response": "bikes_available",
|
||||||
|
"agb_html": "site/agb.html",
|
||||||
|
"impress_html": "site/impress.html",
|
||||||
|
"tariff_info_html": "site/tariff_info_1.html",
|
||||||
|
"lang": "DE",
|
||||||
|
"last_used_operator": {
|
||||||
|
"operator_color": "#008dd2",
|
||||||
|
"operator_email": "hotline@lastenraddemo.bayern",
|
||||||
|
"operator_phone": "+49 089 / 111111111",
|
||||||
|
"operator_name": "Lastenrad Bayern",
|
||||||
|
"operator_hours": "Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr",
|
||||||
|
"operator_logo": ""
|
||||||
|
},
|
||||||
|
"user_id": "ohauff@posteo.de",
|
||||||
|
"clearing_cache": "0",
|
||||||
|
"privacy_html": "site/privacy.html",
|
||||||
|
"bikes": {
|
||||||
|
// Entry manually created (copy-paste). Might contain dupe entries (2021-11-12).
|
||||||
|
"FR9999": {
|
||||||
|
"system": "Ilockit",
|
||||||
|
"gps": {
|
||||||
|
"longitude": "7.8255321",
|
||||||
|
"latitude": "47.9767121"
|
||||||
|
},
|
||||||
|
"lock_state": "locked",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-cc141a6f68bb",
|
||||||
|
"state": "available",
|
||||||
|
"tariff_description": {
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Tester Basic",
|
||||||
|
"eur_per_hour": "3.00",
|
||||||
|
"number": "5494",
|
||||||
|
"1543": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
},
|
||||||
|
"max_eur_per_day": "10.00"
|
||||||
|
},
|
||||||
|
"bike_group": [
|
||||||
|
"FR300103"
|
||||||
|
],
|
||||||
|
"station": "FR103",
|
||||||
|
"description": "Quest Carbon",
|
||||||
|
"Ilockit_ID": "ISHAREIT-9999999",
|
||||||
|
"authed": "1",
|
||||||
|
"bike": "FR9999",
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu"
|
||||||
|
},
|
||||||
|
// Entry manually created (copy-paste). Might contain dupe entries (2021-11-12).
|
||||||
|
"FR9998": {
|
||||||
|
"system": "Ilockit",
|
||||||
|
"gps": {
|
||||||
|
"longitude": "7.8255321",
|
||||||
|
"latitude": "47.9767121"
|
||||||
|
},
|
||||||
|
"lock_state": "locked",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-cc141a6f68bb",
|
||||||
|
"state": "available",
|
||||||
|
"tariff_description": {
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Bacchetta Giro",
|
||||||
|
"eur_per_hour": "3.00",
|
||||||
|
"number": "5494",
|
||||||
|
"1543": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
},
|
||||||
|
"max_eur_per_day": "10.00"
|
||||||
|
},
|
||||||
|
"bike_group": [
|
||||||
|
"FR300103"
|
||||||
|
],
|
||||||
|
"station": "FR103",
|
||||||
|
"description": "Quest Carbon",
|
||||||
|
"Ilockit_ID": "ISHAREIT-9999999",
|
||||||
|
"authed": "1",
|
||||||
|
"bike": "FR9998",
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu"
|
||||||
|
},
|
||||||
|
"FR1543": {
|
||||||
|
"system": "Ilockit",
|
||||||
|
"gps": {
|
||||||
|
"longitude": "7.8255321",
|
||||||
|
"latitude": "47.9767121"
|
||||||
|
},
|
||||||
|
"lock_state": "locked",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-cc141a6f68bb",
|
||||||
|
"state": "available",
|
||||||
|
"tariff_description": {
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Tester Basic",
|
||||||
|
"eur_per_hour": "3.00",
|
||||||
|
"number": "5494",
|
||||||
|
"1543": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
},
|
||||||
|
"max_eur_per_day": "10.00"
|
||||||
|
},
|
||||||
|
"bike_group": [
|
||||||
|
"FR300103"
|
||||||
|
],
|
||||||
|
"station": "FR101",
|
||||||
|
"description": "Contributor-bike Dominik",
|
||||||
|
"Ilockit_ID": "ISHAREIT-2200543",
|
||||||
|
"authed": "1",
|
||||||
|
"bike": "FR1543",
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu"
|
||||||
|
},
|
||||||
|
"FR1003": {
|
||||||
|
"bike": "FR1003",
|
||||||
|
"authed": "1",
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"bike_group": [
|
||||||
|
"FR300101"
|
||||||
|
],
|
||||||
|
"Ilockit_ID": "ISHAREIT-2200545",
|
||||||
|
"station": "FR101",
|
||||||
|
"description": "Stadtrad",
|
||||||
|
"tariff_description": {
|
||||||
|
"max_eur_per_day": "10.00",
|
||||||
|
"number": "5491",
|
||||||
|
"eur_per_hour": "2.00",
|
||||||
|
"1003": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
},
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Vauban Basic"
|
||||||
|
},
|
||||||
|
"state": "available",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-e38bf9d32234",
|
||||||
|
"system": "Ilockit",
|
||||||
|
"gps": {
|
||||||
|
"longitude": "7.8255772",
|
||||||
|
"latitude": "47.9765188"
|
||||||
|
},
|
||||||
|
"lock_state": "locked"
|
||||||
|
},
|
||||||
|
"FR1540": {
|
||||||
|
"bike_group": [
|
||||||
|
"FR300103"
|
||||||
|
],
|
||||||
|
"Ilockit_ID": "ISHAREIT-2200540",
|
||||||
|
"description": "Contributor-bike Dieter",
|
||||||
|
"station": "FR101",
|
||||||
|
"bike": "FR1540",
|
||||||
|
"authed": "1",
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-fc3c002a2add",
|
||||||
|
"system": "Ilockit",
|
||||||
|
"gps": {
|
||||||
|
"longitude": "7.8256267",
|
||||||
|
"latitude": "47.976803"
|
||||||
|
},
|
||||||
|
"lock_state": "locked",
|
||||||
|
"tariff_description": {
|
||||||
|
"1540": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
},
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Tester Basic",
|
||||||
|
"max_eur_per_day": "10.00",
|
||||||
|
"eur_per_hour": "3.00",
|
||||||
|
"number": "5494"
|
||||||
|
},
|
||||||
|
"state": "available"
|
||||||
|
},
|
||||||
|
"FR1002": {
|
||||||
|
"bike_group": [
|
||||||
|
"FR300101"
|
||||||
|
],
|
||||||
|
"description": "Lasten-Dreirad",
|
||||||
|
"station": "FR101",
|
||||||
|
"Ilockit_ID": "ISHAREIT-2200539",
|
||||||
|
"authed": "1",
|
||||||
|
"bike": "FR1002",
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"gps": {
|
||||||
|
"latitude": "47.976552",
|
||||||
|
"longitude": "7.8255068"
|
||||||
|
},
|
||||||
|
"system": "Ilockit",
|
||||||
|
"lock_state": "locked",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-f0b4a692e169",
|
||||||
|
"state": "available",
|
||||||
|
"tariff_description": {
|
||||||
|
"max_eur_per_day": "10.00",
|
||||||
|
"1002": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
},
|
||||||
|
"eur_per_hour": "2.00",
|
||||||
|
"number": "5491",
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Vauban Basic"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"FR1538": {
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"authed": "1",
|
||||||
|
"bike": "FR1538",
|
||||||
|
"station": "FR105",
|
||||||
|
"description": "Contributor-bike Rainer",
|
||||||
|
"Ilockit_ID": "ISHAREIT-2200538",
|
||||||
|
"bike_group": [
|
||||||
|
"FR300103"
|
||||||
|
],
|
||||||
|
"state": "available",
|
||||||
|
"tariff_description": {
|
||||||
|
"max_eur_per_day": "10.00",
|
||||||
|
"eur_per_hour": "3.00",
|
||||||
|
"number": "5494",
|
||||||
|
"1538": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
},
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Tester Basic"
|
||||||
|
},
|
||||||
|
"gps": {
|
||||||
|
"latitude": "47.9275957",
|
||||||
|
"longitude": "7.973976"
|
||||||
|
},
|
||||||
|
"lock_state": "locked",
|
||||||
|
"system": "Ilockit",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-db0319a2555b"
|
||||||
|
},
|
||||||
|
"FR1001": {
|
||||||
|
"bike_group": [
|
||||||
|
"FR300101"
|
||||||
|
],
|
||||||
|
"station": "FR101",
|
||||||
|
"description": "Lastenrad",
|
||||||
|
"Ilockit_ID": "ISHAREIT-2200536",
|
||||||
|
"authed": "1",
|
||||||
|
"bike": "FR1001",
|
||||||
|
"uri_operator": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"lock_state": "locked",
|
||||||
|
"gps": {
|
||||||
|
"latitude": "47.9765091",
|
||||||
|
"longitude": "7.8255631"
|
||||||
|
},
|
||||||
|
"system": "Ilockit",
|
||||||
|
"Ilockit_GUID": "00000000-0000-0000-0000-caa87760e53e",
|
||||||
|
"state": "available",
|
||||||
|
"tariff_description": {
|
||||||
|
"free_hours": "0.50",
|
||||||
|
"name": "Vauban Basic",
|
||||||
|
"eur_per_hour": "2.00",
|
||||||
|
"number": "5491",
|
||||||
|
"max_eur_per_day": "10.00",
|
||||||
|
"1001": {
|
||||||
|
"operator_agb": "Mit der Mietrad Anmietung wird folgender Betreiber <a href='https://shareeapp-fr01.copri.eu/site/agb.html'>AGB</a> zugestimmt (als Demo sharee AGB)."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user_group": [
|
||||||
|
"FR300103",
|
||||||
|
"FR300101"
|
||||||
|
],
|
||||||
|
"apiserver": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"user_tour": [],
|
||||||
|
"authcookie": "6103_112e96b36ba33de245943c5ffaf369cd_oiF2kahH",
|
||||||
|
"copri_version": "4.1.8.21",
|
||||||
|
"response_state": "OK, nothing todo",
|
||||||
|
"new_authcoo": "0",
|
||||||
|
"bike_info_html": "site/bike_info.html",
|
||||||
|
"debuglevel": "1",
|
||||||
|
"uri_primary": "https://shareeapp-primary.copri.eu"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"shareejson": {
|
||||||
|
"authcookie": "6103_112e96b36ba33de245943c5ffaf369cd_oiF2kahH",
|
||||||
|
"copri_version": "4.1.8.21",
|
||||||
|
"user_tour": [],
|
||||||
|
"user_group": [
|
||||||
|
"FR300103",
|
||||||
|
"FR300101"
|
||||||
|
],
|
||||||
|
"bikes_occupied": {
|
||||||
|
},
|
||||||
|
"apiserver": "https://shareeapp-fr01.copri.eu",
|
||||||
|
"uri_primary": "https://shareeapp-primary.copri.eu",
|
||||||
|
"debuglevel": "1",
|
||||||
|
"bike_info_html": "site/bike_info.html",
|
||||||
|
"new_authcoo": "0",
|
||||||
|
"response_state": "OK, nothing todo",
|
||||||
|
"last_used_operator": {
|
||||||
|
"operator_color": "#008dd2",
|
||||||
|
"operator_phone": "+49 089 / 111111111",
|
||||||
|
"operator_email": "hotline@lastenraddemo.bayern",
|
||||||
|
"operator_hours": "B<>rozeiten: Montag, Mittwoch, Freitag 9-12 Uhr",
|
||||||
|
"operator_name": "Lastenrad Bayern",
|
||||||
|
"operator_logo": ""
|
||||||
|
},
|
||||||
|
"lang": "DE",
|
||||||
|
"impress_html": "site/impress.html",
|
||||||
|
"tariff_info_html": "site/tariff_info_1.html",
|
||||||
|
"agb_html": "site/agb.html",
|
||||||
|
"response": "user_bikes_occupied",
|
||||||
|
"agb_checked": "1",
|
||||||
|
"privacy_html": "site/privacy.html",
|
||||||
|
"clearing_cache": "0",
|
||||||
|
"user_id": "ohauff@posteo.de"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
@ -6,6 +6,12 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Remove="Repository\CopriCallsMemory001v2NotLoggedIn\AuthorizationResponse.json" />
|
||||||
|
<None Remove="Repository\CopriCallsMemory001v2NotLoggedIn\AuthoutResponse.json" />
|
||||||
|
<None Remove="Repository\CopriCallsMemory001v2NotLoggedIn\BikesAvailableResponse.json" />
|
||||||
|
<None Remove="Repository\CopriCallsMemory001v2NotLoggedIn\BikesOccupiedResponse.json" />
|
||||||
|
<None Remove="Repository\CopriCallsMemory001v2NotLoggedIn\StationsAvailable.json" />
|
||||||
|
<None Remove="Repository\CopriCallsMemory001v2NotLoggedIn\StationsAvailableNotLoggedIn.json" />
|
||||||
<None Remove="Repository\CopriCallsMemory001\AuthorizationResponse.json" />
|
<None Remove="Repository\CopriCallsMemory001\AuthorizationResponse.json" />
|
||||||
<None Remove="Repository\CopriCallsMemory001\AuthoutResponse.json" />
|
<None Remove="Repository\CopriCallsMemory001\AuthoutResponse.json" />
|
||||||
<None Remove="Repository\CopriCallsMemory001\BikesOccupiedResponse.json" />
|
<None Remove="Repository\CopriCallsMemory001\BikesOccupiedResponse.json" />
|
||||||
|
@ -13,6 +19,11 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Repository\CopriCallsMemory001v2NotLoggedIn\AuthorizationResponse.json" />
|
||||||
|
<EmbeddedResource Include="Repository\CopriCallsMemory001v2NotLoggedIn\AuthoutResponse.json" />
|
||||||
|
<EmbeddedResource Include="Repository\CopriCallsMemory001v2NotLoggedIn\BikesAvailableResponse.json" />
|
||||||
|
<EmbeddedResource Include="Repository\CopriCallsMemory001v2NotLoggedIn\BikesOccupiedResponse.json" />
|
||||||
|
<EmbeddedResource Include="Repository\CopriCallsMemory001v2NotLoggedIn\StationsAvailable.json" />
|
||||||
<EmbeddedResource Include="Repository\CopriCallsMemory001\AuthorizationResponse.json" />
|
<EmbeddedResource Include="Repository\CopriCallsMemory001\AuthorizationResponse.json" />
|
||||||
<EmbeddedResource Include="Repository\CopriCallsMemory001\AuthoutResponse.json" />
|
<EmbeddedResource Include="Repository\CopriCallsMemory001\AuthoutResponse.json" />
|
||||||
<EmbeddedResource Include="Repository\CopriCallsMemory001\BikesAvailableResponse.json" />
|
<EmbeddedResource Include="Repository\CopriCallsMemory001\BikesAvailableResponse.json" />
|
||||||
|
@ -24,7 +35,6 @@
|
||||||
<Folder Include="Model\Device\" />
|
<Folder Include="Model\Device\" />
|
||||||
<Folder Include="Model\User\Account\" />
|
<Folder Include="Model\User\Account\" />
|
||||||
<Folder Include="Services\BluetoothLock\" />
|
<Folder Include="Services\BluetoothLock\" />
|
||||||
<Folder Include="Services\CopriApi\" />
|
|
||||||
<Folder Include="Services\Geolocation\" />
|
<Folder Include="Services\Geolocation\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ namespace TestShareeLib.Model.Connector
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreate_Available_CorpiLock_FeedbackPending()
|
public void TestCreate_Available_CopriLock_FeedbackPending()
|
||||||
{
|
{
|
||||||
var bikeInfoResponse = JsonConvert.DeserializeObject<BikeInfoAvailable>(
|
var bikeInfoResponse = JsonConvert.DeserializeObject<BikeInfoAvailable>(
|
||||||
@"{
|
@"{
|
||||||
|
|
|
@ -32,17 +32,31 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
|
|
||||||
private const string STATIONSALL = @"{
|
/// <summary>
|
||||||
|
/// Holds the response on stations_available request.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks> V1: Did not hold station_type entry.</remarks>
|
||||||
|
private const string STATIONSALLV2 = @"{
|
||||||
""copri_version"" : ""4.1.0.0"",
|
""copri_version"" : ""4.1.0.0"",
|
||||||
""stations"" : {
|
""stations"" : {
|
||||||
""5"" : {
|
""9"" : {
|
||||||
""station"" : ""5"",
|
""station"" : ""9"",
|
||||||
""bike_soll"" : ""0"",
|
""bike_soll"" : ""0"",
|
||||||
""bike_ist"" : ""7"",
|
""bike_ist"" : ""7"",
|
||||||
""station_group"" : [ ""TINK"" ],
|
""station_group"" : [ ""TINK"" ],
|
||||||
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
||||||
""state"" : ""available"",
|
""state"" : ""available"",
|
||||||
""description"" : """"
|
""description"" : """",
|
||||||
|
""station_type"": {
|
||||||
|
""Cargobike"": {
|
||||||
|
""bike_count"": ""1"",
|
||||||
|
""bike_group"": ""TINK""
|
||||||
|
},
|
||||||
|
""Citybike"": {
|
||||||
|
""bike_count"": ""0"",
|
||||||
|
""bike_group"": ""FR300103""
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
""13"" : {
|
""13"" : {
|
||||||
""station"" : ""13"",
|
""station"" : ""13"",
|
||||||
|
@ -91,53 +105,19 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
|
||||||
var server = Substitute.For<ICachedCopriServer>();
|
var server = Substitute.For<ICachedCopriServer>();
|
||||||
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
||||||
typeof(CopriCallsMonkeyStore),
|
typeof(CopriCallsMonkeyStore),
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
|
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2),
|
||||||
new GeneralData(),
|
new GeneralData(),
|
||||||
new System.Exception("Bang when getting stations..."))));
|
new System.Exception("Bang when getting stations..."))));
|
||||||
|
|
||||||
server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
var result = await new CachedQuery(server).GetBikesAndStationsAsync();
|
var result = await new CachedQuery(server).GetBikesAndStationsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
||||||
Assert.AreEqual(1, result.Response.Bikes.Count);
|
Assert.AreEqual(1, result.Response.StationsAll["9"].BikeGroups.AvailableCount);
|
||||||
|
Assert.AreEqual(0, result.Response.BikesOccupied.Count);
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
||||||
Assert.AreEqual("Bang when getting stations...", result.Exception.Message);
|
Assert.AreEqual("Bang when getting stations...", result.Exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public async Task TestGetStations_BikesAvailableFromCache()
|
|
||||||
{
|
|
||||||
var server = Substitute.For<ICachedCopriServer>();
|
|
||||||
|
|
||||||
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
||||||
typeof(CopriCallsHttps),
|
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLEMPTY),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
||||||
new GeneralData(),
|
|
||||||
new System.Exception("Bang when getting bikes..."))));
|
|
||||||
|
|
||||||
server.GetStations(true).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
var result = await new CachedQuery(server).GetBikesAndStationsAsync();
|
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
|
||||||
Assert.AreEqual(1, result.Response.Bikes.Count);
|
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
|
||||||
Assert.AreEqual("Bang when getting bikes...", result.Exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestGetStations()
|
public async Task TestGetStations()
|
||||||
{
|
{
|
||||||
|
@ -145,18 +125,14 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
|
||||||
|
|
||||||
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
||||||
typeof(CopriCallsHttps),
|
typeof(CopriCallsHttps),
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
|
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2),
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsHttps),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
||||||
new GeneralData())));
|
new GeneralData())));
|
||||||
|
|
||||||
var result = await new CachedQuery(server).GetBikesAndStationsAsync();
|
var result = await new CachedQuery(server).GetBikesAndStationsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
||||||
Assert.AreEqual(1, result.Response.Bikes.Count);
|
Assert.AreEqual(1, result.Response.StationsAll["9"].BikeGroups.AvailableCount);
|
||||||
|
Assert.AreEqual(0, result.Response.BikesOccupied.Count, "There are no reserved or occupied bikes.");
|
||||||
Assert.AreEqual(typeof(CopriCallsHttps), result.Source);
|
Assert.AreEqual(typeof(CopriCallsHttps), result.Source);
|
||||||
Assert.IsNull(result.Exception);
|
Assert.IsNull(result.Exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,6 +398,72 @@ namespace TestShareeLib.Model.Connector
|
||||||
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
||||||
}";
|
}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Response updated (manually edited) combining JSON form responses <see cref="STATIONSALL"/> and <see cref="BIKESOCCUPIED"/>
|
||||||
|
/// </summary>
|
||||||
|
private const string STATIONSALLV2 = @"{
|
||||||
|
""copri_version"" : ""4.1.0.0"",
|
||||||
|
""stations"" : {
|
||||||
|
""5"" : {
|
||||||
|
""station"" : ""5"",
|
||||||
|
""bike_soll"" : ""0"",
|
||||||
|
""bike_ist"" : ""7"",
|
||||||
|
""station_group"" : [ ""TINK"" ],
|
||||||
|
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : """"
|
||||||
|
},
|
||||||
|
""13"" : {
|
||||||
|
""station"" : ""13"",
|
||||||
|
""bike_soll"" : ""4"",
|
||||||
|
""bike_ist"" : ""1"",
|
||||||
|
""station_group"" : [ ""TINK"" ],
|
||||||
|
""gps"" : { ""latitude"": ""47.657756"", ""longitude"": ""9.176084"" },
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : """"
|
||||||
|
},
|
||||||
|
""30"" : {
|
||||||
|
""station"" : ""30"",
|
||||||
|
""bike_soll"" : ""5"",
|
||||||
|
""bike_ist"" : ""0"",
|
||||||
|
""station_group"" : [ ""TINK"", ""Konrad"" ],
|
||||||
|
""gps"" : { ""latitude"": ""47.657766"", ""longitude"": ""9.176094"" },
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : ""Test für Stadtradstation""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""bikes_occupied"" : {
|
||||||
|
""89004"" : {
|
||||||
|
""start_time"" : ""2018-01-27 17:33:00.989464+01"",
|
||||||
|
""station"" : ""9"",
|
||||||
|
""unit_price"" : ""2.00"",
|
||||||
|
""tariff_description"": {
|
||||||
|
""free_hours"" : ""0.5"",
|
||||||
|
""name"" : ""TINK Tarif"",
|
||||||
|
""max_eur_per_day"" : ""9.00""
|
||||||
|
},
|
||||||
|
""timeCode"" : ""2061"",
|
||||||
|
""description"" : ""Cargo Long"",
|
||||||
|
""bike"" : ""4"",
|
||||||
|
""total_price"" : ""20.00"",
|
||||||
|
""state"" : ""requested"",
|
||||||
|
""real_hours"" : ""66.05"",
|
||||||
|
""bike_group"" : [ ""TINK"" ],
|
||||||
|
""now_time"" : ""2018-01-30 11:36:45"",
|
||||||
|
""request_time"" : ""2018-01-27 17:33:00.989464+01"",
|
||||||
|
""computed_hours"" : ""10.0""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
""user_group"" : [ ""Konrad"", ""TINK"" ],
|
||||||
|
""response_state"" : ""OK"",
|
||||||
|
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
||||||
|
""debuglevel"" : ""2"",
|
||||||
|
""response"" : ""stations_all"",
|
||||||
|
""user_id"" : ""javaminister@gmail.com"",
|
||||||
|
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
||||||
|
}";
|
||||||
|
|
||||||
private const string STATIONSALLEMPTY = @"{
|
private const string STATIONSALLEMPTY = @"{
|
||||||
""copri_version"" : ""4.1.0.0"",
|
""copri_version"" : ""4.1.0.0"",
|
||||||
""stations"" : {
|
""stations"" : {
|
||||||
|
@ -418,101 +484,18 @@ namespace TestShareeLib.Model.Connector
|
||||||
|
|
||||||
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
||||||
typeof(CopriCallsMonkeyStore),
|
typeof(CopriCallsMonkeyStore),
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
|
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2),
|
||||||
new GeneralData(),
|
new GeneralData(),
|
||||||
new System.Exception("Bang when getting stations..."))));
|
new Exception("Bang when getting stations..."))));
|
||||||
|
|
||||||
server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesOccupied(true).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
||||||
Assert.AreEqual(2, result.Response.Bikes.Count);
|
Assert.AreEqual(1, result.Response.BikesOccupied.Count);
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
||||||
Assert.AreEqual("Bang when getting stations...", result.Exception.Message);
|
Assert.AreEqual("Bang when getting stations...", result.Exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public async Task TestGetStations_BikesAvailableFromCache()
|
|
||||||
{
|
|
||||||
var server = Substitute.For<ICachedCopriServer>();
|
|
||||||
|
|
||||||
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
||||||
typeof(CopriCallsHttps),
|
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLEMPTY),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
||||||
new GeneralData(),
|
|
||||||
new System.Exception("Bang when getting bikes..."))));
|
|
||||||
|
|
||||||
server.GetBikesOccupied(true).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetStations(true).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
|
||||||
Assert.AreEqual(2, result.Response.Bikes.Count);
|
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
|
||||||
Assert.AreEqual("Bang when getting bikes...", result.Exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public async Task TestGetStations_BikesOccupiedFromCache()
|
|
||||||
{
|
|
||||||
var server = Substitute.For<ICachedCopriServer>();
|
|
||||||
|
|
||||||
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
||||||
typeof(CopriCallsHttps),
|
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLEMPTY),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsHttps),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLEEMPTY),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesOccupied(false).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
||||||
new GeneralData(),
|
|
||||||
new System.Exception("Bang when getting bikes occupied..."))));
|
|
||||||
|
|
||||||
server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetStations(true).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
|
||||||
typeof(CopriCallsMonkeyStore),
|
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
|
||||||
Assert.AreEqual(2, result.Response.Bikes.Count);
|
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
|
||||||
Assert.AreEqual("Bang when getting bikes occupied...", result.Exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestGetStations()
|
public async Task TestGetStations()
|
||||||
{
|
{
|
||||||
|
@ -520,23 +503,13 @@ namespace TestShareeLib.Model.Connector
|
||||||
|
|
||||||
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
|
||||||
typeof(CopriCallsHttps),
|
typeof(CopriCallsHttps),
|
||||||
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
|
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2),
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
|
|
||||||
typeof(CopriCallsHttps),
|
|
||||||
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
|
|
||||||
new GeneralData())));
|
|
||||||
|
|
||||||
server.GetBikesOccupied(false).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
|
|
||||||
typeof(CopriCallsHttps),
|
|
||||||
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
|
|
||||||
new GeneralData())));
|
new GeneralData())));
|
||||||
|
|
||||||
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
||||||
Assert.AreEqual(2, result.Response.Bikes.Count);
|
Assert.AreEqual(1, result.Response.BikesOccupied.Count);
|
||||||
Assert.AreEqual(typeof(CopriCallsHttps), result.Source);
|
Assert.AreEqual(typeof(CopriCallsHttps), result.Source);
|
||||||
Assert.IsNull(result.Exception);
|
Assert.IsNull(result.Exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,17 +29,31 @@ namespace TestTINKLib.Fixtures.ObjectTests.Query
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
|
|
||||||
private const string STATIONSALL = @"{
|
/// <summary>
|
||||||
|
/// Holds the response on stations_available request.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks> V1: Did not hold station_type entry.</remarks>
|
||||||
|
private const string STATIONSALLV2 = @"{
|
||||||
""copri_version"" : ""4.1.0.0"",
|
""copri_version"" : ""4.1.0.0"",
|
||||||
""stations"" : {
|
""stations"" : {
|
||||||
""5"" : {
|
""9"" : {
|
||||||
""station"" : ""5"",
|
""station"" : ""9"",
|
||||||
""bike_soll"" : ""0"",
|
""bike_soll"" : ""0"",
|
||||||
""bike_ist"" : ""7"",
|
""bike_ist"" : ""7"",
|
||||||
""station_group"" : [ ""TINK"" ],
|
""station_group"" : [ ""TINK"" ],
|
||||||
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
||||||
""state"" : ""available"",
|
""state"" : ""available"",
|
||||||
""description"" : """"
|
""description"" : """",
|
||||||
|
""station_type"": {
|
||||||
|
""Cargobike"": {
|
||||||
|
""bike_count"": ""1"",
|
||||||
|
""bike_group"": ""TINK""
|
||||||
|
},
|
||||||
|
""Citybike"": {
|
||||||
|
""bike_count"": ""0"",
|
||||||
|
""bike_group"": ""FR300103""
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
""13"" : {
|
""13"" : {
|
||||||
""station"" : ""13"",
|
""station"" : ""13"",
|
||||||
|
@ -74,13 +88,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.Query
|
||||||
{
|
{
|
||||||
var server = Substitute.For<ICopriServer>();
|
var server = Substitute.For<ICopriServer>();
|
||||||
|
|
||||||
server.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL)));
|
server.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2)));
|
||||||
server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
|
|
||||||
|
|
||||||
var result = await new TINK.Model.Connector.Query(server).GetBikesAndStationsAsync();
|
var result = await new TINK.Model.Connector.Query(server).GetBikesAndStationsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
||||||
Assert.AreEqual(1, result.Response.Bikes.Count);
|
Assert.AreEqual(1, result.Response.StationsAll["9"].BikeGroups.AvailableCount);
|
||||||
|
Assert.AreEqual(0, result.Response.BikesOccupied.Count);
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
||||||
Assert.IsNull(result.Exception);
|
Assert.IsNull(result.Exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ using TINK.Repository.Response.Stations;
|
||||||
namespace TestTINKLib.Fixtures.ObjectTests.Connector
|
namespace TestTINKLib.Fixtures.ObjectTests.Connector
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestQueryLoggedIn
|
public class TestQueryLoggedIn
|
||||||
{
|
{
|
||||||
private const string BIKESAVAILABLE = @"{
|
private const string BIKESAVAILABLE = @"{
|
||||||
""copri_version"" : ""4.1.0.0"",
|
""copri_version"" : ""4.1.0.0"",
|
||||||
""bikes"" : {},
|
""bikes"" : {},
|
||||||
""response_state"" : ""OK"",
|
""response_state"" : ""OK"",
|
||||||
|
@ -31,7 +31,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
|
|
||||||
private const string BIKESOCCUPIED = @"{
|
private const string BIKESOCCUPIED = @"{
|
||||||
""copri_version"" : ""4.1.0.0"",
|
""copri_version"" : ""4.1.0.0"",
|
||||||
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
||||||
""debuglevel"" : ""2"",
|
""debuglevel"" : ""2"",
|
||||||
|
@ -65,17 +65,31 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
|
||||||
}
|
}
|
||||||
}";
|
}";
|
||||||
|
|
||||||
private const string STATIONSALL = @"{
|
/// <summary>
|
||||||
|
/// Holds the response on stations_available request.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks> V1: Did not hold station_type entry.</remarks>
|
||||||
|
private const string STATIONSALLV2 = @"{
|
||||||
""copri_version"" : ""4.1.0.0"",
|
""copri_version"" : ""4.1.0.0"",
|
||||||
""stations"" : {
|
""stations"" : {
|
||||||
""5"" : {
|
""9"" : {
|
||||||
""station"" : ""5"",
|
""station"" : ""9"",
|
||||||
""bike_soll"" : ""0"",
|
""bike_soll"" : ""0"",
|
||||||
""bike_ist"" : ""7"",
|
""bike_ist"" : ""7"",
|
||||||
""station_group"" : [ ""TINK"" ],
|
""station_group"" : [ ""TINK"" ],
|
||||||
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
|
||||||
""state"" : ""available"",
|
""state"" : ""available"",
|
||||||
""description"" : """"
|
""description"" : """",
|
||||||
|
""station_type"": {
|
||||||
|
""Cargobike"": {
|
||||||
|
""bike_count"": ""1"",
|
||||||
|
""bike_group"": ""TINK""
|
||||||
|
},
|
||||||
|
""Citybike"": {
|
||||||
|
""bike_count"": ""0"",
|
||||||
|
""bike_group"": ""FR300103""
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
""13"" : {
|
""13"" : {
|
||||||
""station"" : ""13"",
|
""station"" : ""13"",
|
||||||
|
@ -95,7 +109,29 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
|
||||||
""state"" : ""available"",
|
""state"" : ""available"",
|
||||||
""description"" : ""Test für Stadtradstation""
|
""description"" : ""Test für Stadtradstation""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
""bikes_occupied"" : {
|
||||||
|
""89004"" : {
|
||||||
|
""start_time"" : ""2018-01-27 17:33:00.989464+01"",
|
||||||
|
""station"" : ""9"",
|
||||||
|
""unit_price"" : ""2.00"",
|
||||||
|
""tariff_description"": {
|
||||||
|
""free_hours"" : ""0.5"",
|
||||||
|
""name"" : ""TINK Tarif"",
|
||||||
|
""max_eur_per_day"" : ""9.00""
|
||||||
|
},
|
||||||
|
""timeCode"" : ""2061"",
|
||||||
|
""description"" : ""Cargo Long"",
|
||||||
|
""bike"" : ""4"",
|
||||||
|
""total_price"" : ""20.00"",
|
||||||
|
""state"" : ""requested"",
|
||||||
|
""real_hours"" : ""66.05"",
|
||||||
|
""bike_group"" : [ ""TINK"" ],
|
||||||
|
""now_time"" : ""2018-01-30 11:36:45"",
|
||||||
|
""request_time"" : ""2018-01-27 17:33:00.989464+01"",
|
||||||
|
""computed_hours"" : ""10.0""
|
||||||
|
}
|
||||||
|
},
|
||||||
""user_group"" : [ ""Konrad"", ""TINK"" ],
|
""user_group"" : [ ""Konrad"", ""TINK"" ],
|
||||||
""response_state"" : ""OK"",
|
""response_state"" : ""OK"",
|
||||||
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
|
||||||
|
@ -105,52 +141,51 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
|
||||||
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
""apiserver"" : ""https://tinkwwp.copri-bike.de""
|
||||||
}";
|
}";
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestGetStations()
|
public async Task TestGetStations()
|
||||||
{
|
{
|
||||||
var server = Substitute.For<ICopriServer>();
|
var server = Substitute.For<ICopriServer>();
|
||||||
|
|
||||||
server.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL)));
|
server.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLV2)));
|
||||||
server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
|
|
||||||
server.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
|
|
||||||
|
|
||||||
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
|
||||||
|
|
||||||
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
Assert.AreEqual(3, result.Response.StationsAll.Count);
|
||||||
Assert.AreEqual(2, result.Response.Bikes.Count);
|
Assert.AreEqual(1, result.Response.StationsAll["9"].BikeGroups.AvailableCount);
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
Assert.AreEqual(1, result.Response.BikesOccupied.Count);
|
||||||
Assert.IsNull(result.Exception);
|
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
||||||
}
|
Assert.IsNull(result.Exception);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestGetBikes()
|
public async Task TestGetBikes()
|
||||||
{
|
{
|
||||||
var server = Substitute.For<ICopriServer>();
|
var server = Substitute.For<ICopriServer>();
|
||||||
|
|
||||||
server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
|
server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
|
||||||
server.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
|
server.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
|
||||||
|
|
||||||
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();
|
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();
|
||||||
|
|
||||||
Assert.AreEqual(2, result.Response.Count);
|
Assert.AreEqual(2, result.Response.Count);
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
||||||
Assert.IsNull(result.Exception);
|
Assert.IsNull(result.Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestGetBikesOccupied()
|
public async Task TestGetBikesOccupied()
|
||||||
{
|
{
|
||||||
var server = Substitute.For<ICopriServer>();
|
var server = Substitute.For<ICopriServer>();
|
||||||
|
|
||||||
server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>("{}")));
|
server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>("{}")));
|
||||||
|
|
||||||
server.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
|
server.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
|
||||||
|
|
||||||
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesOccupiedAsync();
|
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesOccupiedAsync();
|
||||||
|
|
||||||
Assert.AreEqual(1, result.Response.Count);
|
Assert.AreEqual(1, result.Response.Count);
|
||||||
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
|
||||||
Assert.IsNull(result.Exception);
|
Assert.IsNull(result.Exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,998 @@
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using TINK.Repository.Response.Stations;
|
||||||
|
|
||||||
|
namespace TestShareeLib.Repository.Response.Stations
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestStationsAvailableResponse
|
||||||
|
{
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestStationsAvailableBikesOccupiedBikes()
|
||||||
|
{
|
||||||
|
var response = JsonConvert.DeserializeObject<StationsAvailableResponse>(TestStationAvailalbeResponseCopriVer4_1_23_03_alpha);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
response.bikes_occupied.Count,
|
||||||
|
Is.EqualTo(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestStationsAvailableAvailableBikes()
|
||||||
|
{
|
||||||
|
var response = JsonConvert.DeserializeObject<StationsAvailableResponse>(TestStationAvailalbeResponseCopriVer4_1_23_03);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
response.stations["FR101"].bike_count,
|
||||||
|
Is.EqualTo("11"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
response.stations["FR101"].station_type.FirstOrDefault(x => x.Key == "Citybike").Value.bike_count,
|
||||||
|
Is.EqualTo("1"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
response.stations["FR101"].station_type.FirstOrDefault(x => x.Key == "Citybike").Value.bike_group,
|
||||||
|
Is.EqualTo("FR300103"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
response.stations["FR101"].station_type.FirstOrDefault(x => x.Key == "Cargobike").Value.bike_count,
|
||||||
|
Is.EqualTo("10"));
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
response.stations["FR101"].station_type.FirstOrDefault(x => x.Key == "Cargobike").Value.bike_group,
|
||||||
|
Is.EqualTo("FR300101"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds a a response on stations available response.
|
||||||
|
/// </summary>
|
||||||
|
private const string TestStationAvailalbeResponseCopriVer4_1_23_03 = @"{ ""clearing_cache"" : ""0"",
|
||||||
|
""tariff_info_html"" : ""site/tariff_info.html"",
|
||||||
|
""aowner"" : ""186"",
|
||||||
|
""bike_info_html"" : ""site/bike_info_sharee_1.html"",
|
||||||
|
""last_used_operator"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr""
|
||||||
|
},
|
||||||
|
""bikes_occupied"" : {},
|
||||||
|
""user_group"" : [],
|
||||||
|
""new_authcoo"" : ""0"",
|
||||||
|
""agb_checked"" : ""1"",
|
||||||
|
""uri_primary"" : ""https://shareeapp-primary.copri.eu"",
|
||||||
|
""authcookie"" : ""5781_f172cf59108fe53e7524c841847fee69_shoo0faiNg"",
|
||||||
|
""user_tour"" : [],
|
||||||
|
""impress_html"" : ""site/impress_1.html"",
|
||||||
|
""response_state"" : ""OK, nothing todo"",
|
||||||
|
""user_id"" : ""ohauff@posteo.de"",
|
||||||
|
""agb_html"" : ""site/agb_sharee_2.html"",
|
||||||
|
""merchant_id"" : ""shoo0faiNg"",
|
||||||
|
""apiserver"" : ""https://shareeapp-primary.copri.eu"",
|
||||||
|
""project_id"" : ""Freiburg"",
|
||||||
|
""init_map"" : {
|
||||||
|
""center"" : {
|
||||||
|
""latitude"" : ""47.976634"",
|
||||||
|
""longitude"" : ""7.825490""
|
||||||
|
},
|
||||||
|
""radius"" : ""2.9""
|
||||||
|
},
|
||||||
|
""privacy_html"" : ""site/privacy_sharee_2.html"",
|
||||||
|
""debuglevel"" : ""72"",
|
||||||
|
""copri_version"" : ""4.1.23.03"",
|
||||||
|
""lang"" : ""de"",
|
||||||
|
""stations"" : {
|
||||||
|
""FR105"" : {
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""station"" : ""FR105"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.973855"",
|
||||||
|
""latitude"" : ""47.927738""
|
||||||
|
},
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""bike_group"" : ""FR300101""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""description"" : ""Contributor-Station Rainer"",
|
||||||
|
""state"" : ""available""
|
||||||
|
},
|
||||||
|
""FR107"" : {
|
||||||
|
""station"" : ""FR107"",
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.888761798157405"",
|
||||||
|
""latitude"" : ""47.98830177263789""
|
||||||
|
},
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_group"" : ""FR300101"",
|
||||||
|
""bike_count"" : ""0""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""description"" : ""Contributor-Station Svenja"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
""BVB9001"" : {
|
||||||
|
""state"" : ""available"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""48.004394"",
|
||||||
|
""longitude"" : ""7.840146""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-bvb.copri.eu"",
|
||||||
|
""description"" : ""Unicarré"",
|
||||||
|
""station_group"" : [
|
||||||
|
""BVB300101""
|
||||||
|
],
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_count"" : ""2"",
|
||||||
|
""bike_group"" : ""BVB300101""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""gps_radius"" : ""75"",
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""station"" : ""BVB9001"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""bike_count"" : ""2"",
|
||||||
|
""authed"" : ""1""
|
||||||
|
},
|
||||||
|
""BVB9002"" : {
|
||||||
|
""station"" : ""BVB9002"",
|
||||||
|
""gps_radius"" : ""75"",
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""bike_count"" : ""2"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-bvb.copri.eu"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""48.005352"",
|
||||||
|
""longitude"" : ""7.823005""
|
||||||
|
},
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_group"" : ""BVB300101"",
|
||||||
|
""bike_count"" : ""2""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""description"" : ""Idinger-Hof"",
|
||||||
|
""station_group"" : [
|
||||||
|
""BVB300101""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
""FR102"" : {
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""station"" : ""FR102"",
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""bike_group"" : ""FR300101""
|
||||||
|
},
|
||||||
|
""Citybike"" : {
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""bike_group"" : ""FR300103""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101"",
|
||||||
|
""FR300103""
|
||||||
|
],
|
||||||
|
""description"" : ""Ferdinand-Weiß-Str 5"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""47.994371"",
|
||||||
|
""longitude"" : ""7.835669""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""FR9010"" : {
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097""
|
||||||
|
},
|
||||||
|
""station"" : ""FR9010"",
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""bike_group"" : ""FR300101""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""description"" : ""Contributor-Station Ilockit"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""52.406693917129175"",
|
||||||
|
""longitude"" : ""12.569934014209514""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""FR108"" : {
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : ""Contributor-Station Anja"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""bike_group"" : ""FR300101""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.885837789049421"",
|
||||||
|
""latitude"" : ""48.070487906373515""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""station"" : ""FR108"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""bike_count"" : ""1""
|
||||||
|
},
|
||||||
|
""BVB9003"" : {
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""gps_radius"" : ""75"",
|
||||||
|
""station"" : ""BVB9003"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""bike_count"" : ""2"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.8269763"",
|
||||||
|
""latitude"" : ""48.0137631""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-bvb.copri.eu"",
|
||||||
|
""station_group"" : [
|
||||||
|
""BVB300101""
|
||||||
|
],
|
||||||
|
""description"" : ""Carl-Sieder-Hof"",
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_group"" : ""BVB300101"",
|
||||||
|
""bike_count"" : ""2""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""REN9002"" : {
|
||||||
|
""station_group"" : [
|
||||||
|
""REN300101"",
|
||||||
|
""REN300103""
|
||||||
|
],
|
||||||
|
""description"" : ""Bikerei-IN"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""11.441289676268319"",
|
||||||
|
""latitude"" : ""48.75089095677469""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-ren.copri.eu"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""withpub"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""täglich von 10:00 bis 20:00Uhr"",
|
||||||
|
""operator_phone"" : ""+491774126214"",
|
||||||
|
""operator_name"" : ""Rentamania-Bikes"",
|
||||||
|
""operator_email"" : ""verleih@rentamania.de""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""capacity"" : ""7"",
|
||||||
|
""station"" : ""REN9002""
|
||||||
|
},
|
||||||
|
""REN9001"" : {
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""täglich von 10:00 bis 20:00Uhr"",
|
||||||
|
""operator_name"" : ""Rentamania-Bikes"",
|
||||||
|
""operator_phone"" : ""+491774126214"",
|
||||||
|
""operator_email"" : ""verleih@rentamania.de""
|
||||||
|
},
|
||||||
|
""withpub"" : ""1"",
|
||||||
|
""station"" : ""REN9001"",
|
||||||
|
""capacity"" : ""8"",
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""description"" : ""Rentamania-EI"",
|
||||||
|
""station_group"" : [
|
||||||
|
""REN300101"",
|
||||||
|
""REN300103""
|
||||||
|
],
|
||||||
|
""uri_operator"" : ""https://shareeapp-ren.copri.eu"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""48.8975726"",
|
||||||
|
""longitude"" : ""11.170959""
|
||||||
|
},
|
||||||
|
""state"" : ""available""
|
||||||
|
},
|
||||||
|
""FR104"" : {
|
||||||
|
""description"" : ""fahrradspezialitäten"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101"",
|
||||||
|
""FR300103""
|
||||||
|
],
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_group"" : ""FR300101"",
|
||||||
|
""bike_count"" : ""0""
|
||||||
|
},
|
||||||
|
""Citybike"" : {
|
||||||
|
""bike_group"" : ""FR300103"",
|
||||||
|
""bike_count"" : ""0""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.837621"",
|
||||||
|
""latitude"" : ""47.989807""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""station"" : ""FR104""
|
||||||
|
},
|
||||||
|
""FR101"" : {
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""capacity"" : ""3"",
|
||||||
|
""station"" : ""FR101"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""bike_count"" : ""11"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101"",
|
||||||
|
""FR300103""
|
||||||
|
],
|
||||||
|
""description"" : ""Villaban sharee Station"",
|
||||||
|
""station_type"" : {
|
||||||
|
""Citybike"" : {
|
||||||
|
""bike_group"" : ""FR300103"",
|
||||||
|
""bike_count"" : ""1""
|
||||||
|
},
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_group"" : ""FR300101"",
|
||||||
|
""bike_count"" : ""10""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""47.976634"",
|
||||||
|
""longitude"" : ""7.825490""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu""
|
||||||
|
},
|
||||||
|
""FR103"" : {
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""capacity"" : ""3"",
|
||||||
|
""station"" : ""FR103"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""bike_count"" : ""2"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""47.997922"",
|
||||||
|
""longitude"" : ""7.784941""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""description"" : ""Contributor-Station Oliver"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""station_type"" : {
|
||||||
|
""Cargobike"" : {
|
||||||
|
""bike_group"" : ""FR300101"",
|
||||||
|
""bike_count"" : ""2""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""response"" : ""stations_available"",
|
||||||
|
""uri_operator_array"" : [
|
||||||
|
""https://shareeapp-thu.copri.eu"",
|
||||||
|
""https://shareeapp-demo.copri.eu"",
|
||||||
|
""https://shareeapp-lv.copri.eu"",
|
||||||
|
""https://shareeapp-ren.copri.eu"",
|
||||||
|
""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""https://shareeapp-bvb.copri.eu""
|
||||||
|
]
|
||||||
|
}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds a a response on stations available response.
|
||||||
|
/// </summary>
|
||||||
|
private const string TestStationAvailalbeResponseCopriVer4_1_23_03_alpha = @"{
|
||||||
|
""uri_operator_array"" : [
|
||||||
|
""https://shareeapp-bvb.copri.eu"",
|
||||||
|
""https://shareeapp-thu.copri.eu"",
|
||||||
|
""https://shareeapp-lv.copri.eu"",
|
||||||
|
""https://shareeapp-ren.copri.eu"",
|
||||||
|
""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""https://shareeapp-demo.copri.eu""
|
||||||
|
],
|
||||||
|
""agb_html"" : ""site/agb_sharee_2.html"",
|
||||||
|
""lang"" : ""de"",
|
||||||
|
""apiserver"" : ""https://shareeapp-primary.copri.eu"",
|
||||||
|
""project_id"" : ""Freiburg"",
|
||||||
|
""debuglevel"" : ""72"",
|
||||||
|
""privacy_html"" : ""site/privacy_sharee_2.html"",
|
||||||
|
""last_used_operator"" : {
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH""
|
||||||
|
},
|
||||||
|
""user_id"" : ""ohauff@posteo.de"",
|
||||||
|
""stations"" : {
|
||||||
|
""FR104"" : {
|
||||||
|
""station"" : ""FR104"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.837621"",
|
||||||
|
""latitude"" : ""47.989807""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101"",
|
||||||
|
""FR300103""
|
||||||
|
],
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""description"" : ""fahrradspezialitäten"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""withpub"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""authed"" : ""1""
|
||||||
|
},
|
||||||
|
""FR9010"" : {
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""description"" : ""Contributor-Station Ilockit"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""12.569934014209514"",
|
||||||
|
""latitude"" : ""52.406693917129175""
|
||||||
|
},
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""station"" : ""FR9010""
|
||||||
|
},
|
||||||
|
""BVB9003"" : {
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-bvb.copri.eu"",
|
||||||
|
""description"" : ""Carl-Sieder-Hof"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""station_group"" : [
|
||||||
|
""BVB300101""
|
||||||
|
],
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""gps_radius"" : ""75"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.8269763"",
|
||||||
|
""latitude"" : ""48.0137631""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""station"" : ""BVB9003""
|
||||||
|
},
|
||||||
|
""BVB9001"" : {
|
||||||
|
""station"" : ""BVB9001"",
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""station_group"" : [
|
||||||
|
""BVB300101""
|
||||||
|
],
|
||||||
|
""gps_radius"" : ""75"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""48.004394"",
|
||||||
|
""longitude"" : ""7.840146""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-bvb.copri.eu"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097""
|
||||||
|
},
|
||||||
|
""description"" : ""Unicarré"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""authed"" : ""1""
|
||||||
|
},
|
||||||
|
""FR103"" : {
|
||||||
|
""station"" : ""FR103"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""47.997922"",
|
||||||
|
""longitude"" : ""7.784941""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""capacity"" : ""3"",
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""description"" : ""Contributor-Station Oliver"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""authed"" : ""1""
|
||||||
|
},
|
||||||
|
""REN9001"" : {
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""station_group"" : [
|
||||||
|
""REN300101"",
|
||||||
|
""REN300103""
|
||||||
|
],
|
||||||
|
""capacity"" : ""8"",
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""48.8975726"",
|
||||||
|
""longitude"" : ""11.170959""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""station"" : ""REN9001"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""withpub"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_name"" : ""Rentamania-Bikes"",
|
||||||
|
""operator_phone"" : ""+491774126214"",
|
||||||
|
""operator_hours"" : ""täglich von 10:00 bis 20:00Uhr"",
|
||||||
|
""operator_email"" : ""verleih@rentamania.de""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-ren.copri.eu"",
|
||||||
|
""description"" : ""Rentamania-EI"",
|
||||||
|
""state"" : ""available""
|
||||||
|
},
|
||||||
|
""FR107"" : {
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : ""Contributor-Station Svenja"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""station"" : ""FR107"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.888761798157405"",
|
||||||
|
""latitude"" : ""47.98830177263789""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""bike_count"" : ""0""
|
||||||
|
},
|
||||||
|
""BVB9002"" : {
|
||||||
|
""station_group"" : [
|
||||||
|
""BVB300101""
|
||||||
|
],
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""capacity"" : ""2"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""48.005352"",
|
||||||
|
""longitude"" : ""7.823005""
|
||||||
|
},
|
||||||
|
""gps_radius"" : ""75"",
|
||||||
|
""station"" : ""BVB9002"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-bvb.copri.eu"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : ""Idinger-Hof""
|
||||||
|
},
|
||||||
|
""FR102"" : {
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101"",
|
||||||
|
""FR300103""
|
||||||
|
],
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.835669"",
|
||||||
|
""latitude"" : ""47.994371""
|
||||||
|
},
|
||||||
|
""station"" : ""FR102"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH""
|
||||||
|
},
|
||||||
|
""withpub"" : ""1"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""description"" : ""Ferdinand-Weiß-Str 5"",
|
||||||
|
""state"" : ""available""
|
||||||
|
},
|
||||||
|
""FR105"" : {
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH""
|
||||||
|
},
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""description"" : ""Contributor-Station Rainer"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""47.927738"",
|
||||||
|
""longitude"" : ""7.973855""
|
||||||
|
},
|
||||||
|
""station"" : ""FR105""
|
||||||
|
},
|
||||||
|
""FR108"" : {
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""withpub"" : ""0"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""hotline@sharee.bike"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH""
|
||||||
|
},
|
||||||
|
""description"" : ""Contributor-Station Anja"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""station"" : ""FR108"",
|
||||||
|
""capacity"" : ""1"",
|
||||||
|
""bike_count"" : ""1"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""48.070487906373515"",
|
||||||
|
""longitude"" : ""7.885837789049421""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""FR101"" : {
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""withpub"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_phone"" : ""+49 761 45370097"",
|
||||||
|
""operator_name"" : ""TeilRad GmbH"",
|
||||||
|
""operator_hours"" : ""Bürozeiten: Montag, Mittwoch, Freitag 9-12 Uhr"",
|
||||||
|
""operator_email"" : ""hotline@sharee.bike""
|
||||||
|
},
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : ""Villaban sharee Station"",
|
||||||
|
""capacity"" : ""3"",
|
||||||
|
""station_group"" : [
|
||||||
|
""FR300101"",
|
||||||
|
""FR300103""
|
||||||
|
],
|
||||||
|
""bike_count"" : ""5"",
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""47.976634"",
|
||||||
|
""longitude"" : ""7.825490""
|
||||||
|
},
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps_radius"" : ""50"",
|
||||||
|
""station"" : ""FR101""
|
||||||
|
},
|
||||||
|
""REN9002"" : {
|
||||||
|
""authed"" : ""1"",
|
||||||
|
""state"" : ""available"",
|
||||||
|
""description"" : ""Bikerei-IN"",
|
||||||
|
""withpub"" : ""1"",
|
||||||
|
""operator_data"" : {
|
||||||
|
""operator_email"" : ""verleih@rentamania.de"",
|
||||||
|
""operator_hours"" : ""täglich von 10:00 bis 20:00Uhr"",
|
||||||
|
""operator_name"" : ""Rentamania-Bikes"",
|
||||||
|
""operator_phone"" : ""+491774126214""
|
||||||
|
},
|
||||||
|
""uri_operator"" : ""https://shareeapp-ren.copri.eu"",
|
||||||
|
""cached"" : ""1"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""11.441289676268319"",
|
||||||
|
""latitude"" : ""48.75089095677469""
|
||||||
|
},
|
||||||
|
""gps_radius"" : ""100"",
|
||||||
|
""station_group"" : [
|
||||||
|
""REN300101"",
|
||||||
|
""REN300103""
|
||||||
|
],
|
||||||
|
""bike_count"" : ""0"",
|
||||||
|
""capacity"" : ""7"",
|
||||||
|
""station"" : ""REN9002""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""response"" : ""stations_available"",
|
||||||
|
""bike_info_html"" : ""site/bike_info_sharee_1.html"",
|
||||||
|
""clearing_cache"" : ""0"",
|
||||||
|
""authcookie"" : ""5781_f172cf59108fe53e7524c841847fee69_shoo0faiNg"",
|
||||||
|
""agb_checked"" : ""1"",
|
||||||
|
""impress_html"" : ""site/impress_1.html"",
|
||||||
|
""init_map"" : {
|
||||||
|
""center"" : {
|
||||||
|
""longitude"" : ""7.825490"",
|
||||||
|
""latitude"" : ""47.976634""
|
||||||
|
},
|
||||||
|
""radius"" : ""2.9""
|
||||||
|
},
|
||||||
|
""response_state"" : ""OK, nothing todo"",
|
||||||
|
""merchant_id"" : ""shoo0faiNg"",
|
||||||
|
""new_authcoo"" : ""0"",
|
||||||
|
""tariff_info_html"" : ""site/tariff_info.html"",
|
||||||
|
""user_group"" : [],
|
||||||
|
""aowner"" : ""186"",
|
||||||
|
""copri_version"" : ""4.1.23.03"",
|
||||||
|
""bikes_occupied"" : {
|
||||||
|
""159154"" : {
|
||||||
|
""gps"" : {
|
||||||
|
""latitude"" : ""47.997873374261"",
|
||||||
|
""longitude"" : ""7.78480782173574""
|
||||||
|
},
|
||||||
|
""request_time"" : ""2023-03-24 19:06:27.110484+01"",
|
||||||
|
""end_time"" : ""2023-03-24 19:06:00+01"",
|
||||||
|
""bike"" : ""FR1011"",
|
||||||
|
""bike_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
],
|
||||||
|
""rentalog"" : """",
|
||||||
|
""tariff_description"" : {
|
||||||
|
""eur_per_hour"" : ""0.00"",
|
||||||
|
""number"" : ""5533"",
|
||||||
|
""name"" : ""E-Lastenrad private"",
|
||||||
|
""max_eur_per_day"" : ""24.00""
|
||||||
|
},
|
||||||
|
""system"" : ""Ilockit"",
|
||||||
|
""station"" : ""FR103"",
|
||||||
|
""unit_price"" : ""2.00"",
|
||||||
|
""total_price"" : ""0.00"",
|
||||||
|
""rental_description"" : {
|
||||||
|
""name"" : ""E-Lastenrad private"",
|
||||||
|
""id"" : ""5533"",
|
||||||
|
""reserve_timerange"" : ""15"",
|
||||||
|
""tarif_elements"" : {
|
||||||
|
""4"" : [
|
||||||
|
""Max. Gebühr"",
|
||||||
|
""24,00 € / Tag""
|
||||||
|
],
|
||||||
|
""1"" : [
|
||||||
|
""Mietgebühr"",
|
||||||
|
""2,00 € / 30 Min ""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""real_clock"" : ""00:00"",
|
||||||
|
""discount"" : """",
|
||||||
|
""bike_type"" : {
|
||||||
|
""wheels"" : ""2"",
|
||||||
|
""category"" : ""cargo""
|
||||||
|
},
|
||||||
|
""lock_state"" : ""locked"",
|
||||||
|
""freed_time"" : """",
|
||||||
|
""start_time"" : ""2023-03-24 19:06:27.110484+01"",
|
||||||
|
""description"" : ""Lastenrad Oliver Pieper"",
|
||||||
|
""state"" : ""requested"",
|
||||||
|
""computed_hours"" : ""0"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""Ilockit_ID"" : ""ISHAREIT-2200536""
|
||||||
|
},
|
||||||
|
""159155"" : {
|
||||||
|
""description"" : ""Contributor-bike devel"",
|
||||||
|
""state"" : ""occupied"",
|
||||||
|
""computed_hours"" : ""0"",
|
||||||
|
""freed_time"" : """",
|
||||||
|
""start_time"" : ""2023-03-24 19:06:51.881632+01"",
|
||||||
|
""Ilockit_ID"" : ""ISHAREIT-2309492"",
|
||||||
|
""uri_operator"" : ""https://shareeapp-fr01.copri.eu"",
|
||||||
|
""discount"" : """",
|
||||||
|
""bike_type"" : {
|
||||||
|
""wheels"" : ""2"",
|
||||||
|
""category"" : ""cargo""
|
||||||
|
},
|
||||||
|
""lock_state"" : ""unlocked"",
|
||||||
|
""unit_price"" : ""2.00"",
|
||||||
|
""station"" : ""FR103"",
|
||||||
|
""tariff_description"" : {
|
||||||
|
""number"" : ""5533"",
|
||||||
|
""eur_per_hour"" : ""0.00"",
|
||||||
|
""max_eur_per_day"" : ""24.00"",
|
||||||
|
""name"" : ""E-Lastenrad private""
|
||||||
|
},
|
||||||
|
""system"" : ""Ilockit"",
|
||||||
|
""rental_description"" : {
|
||||||
|
""id"" : ""5533"",
|
||||||
|
""tarif_elements"" : {
|
||||||
|
""4"" : [
|
||||||
|
""Max. Gebühr"",
|
||||||
|
""24,00 € / Tag""
|
||||||
|
],
|
||||||
|
""1"" : [
|
||||||
|
""Mietgebühr"",
|
||||||
|
""2,00 € / 30 Min ""
|
||||||
|
],
|
||||||
|
""7"" : [
|
||||||
|
""Aktuelle Mietzeit"",
|
||||||
|
""1 Min ""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
""reserve_timerange"" : ""15"",
|
||||||
|
""name"" : ""E-Lastenrad private""
|
||||||
|
},
|
||||||
|
""real_clock"" : ""00:01"",
|
||||||
|
""total_price"" : ""0.00"",
|
||||||
|
""request_time"" : ""2023-03-24 19:06:43.046977+01"",
|
||||||
|
""bike"" : ""FR1012"",
|
||||||
|
""end_time"" : ""2023-03-24 19:08:04"",
|
||||||
|
""gps"" : {
|
||||||
|
""longitude"" : ""7.784874"",
|
||||||
|
""latitude"" : ""47.998028""
|
||||||
|
},
|
||||||
|
""rentalog"" : """",
|
||||||
|
""bike_group"" : [
|
||||||
|
""FR300101""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
""uri_primary"" : ""https://shareeapp-primary.copri.eu"",
|
||||||
|
""user_tour"" : []
|
||||||
|
}";
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ using TestFramework.Model.Services.Geolocation;
|
||||||
using TestFramework.Model.User.Account;
|
using TestFramework.Model.User.Account;
|
||||||
using TestFramework.Repository;
|
using TestFramework.Repository;
|
||||||
using TestFramework.Services.BluetoothLock;
|
using TestFramework.Services.BluetoothLock;
|
||||||
using TestFramework.Services.CopriApi.Connector;
|
|
||||||
using TINK.Model;
|
using TINK.Model;
|
||||||
using TINK.Model.Connector;
|
using TINK.Model.Connector;
|
||||||
using TINK.Model.Services.CopriApi;
|
using TINK.Model.Services.CopriApi;
|
||||||
|
|
|
@ -344,7 +344,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
)); ;
|
)); ;
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x => throw new WebConnectFailureException("Context info", new Exception("hoppla")));
|
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x => throw new WebConnectFailureException("Context info", new Exception("hoppla")));
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
throw notAtStationException);
|
throw notAtStationException);
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -557,7 +557,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
throw noGPSDataException);
|
throw noGPSDataException);
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -625,7 +625,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
throw new ReturnBikeException(JsonConvert.DeserializeObject<DoReturnResponse>(@"{ ""response_text"" : ""Some invalid data received!""}"), "Outer message."));
|
throw new ReturnBikeException(JsonConvert.DeserializeObject<DoReturnResponse>(@"{ ""response_text"" : ""Some invalid data received!""}"), "Outer message."));
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -692,7 +692,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x => throw new Exception("Exception message."));
|
connector.Command.DoReturn(bike, Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
connector.Command.DoReserve(bike).Returns(x => throw new BookingDeclinedException(7)); // Booking must be performed
|
connector.Command.DoReserve(bike).Returns(x => throw new BookingDeclinedException(7)); // Booking must be performed
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
connector.Command.DoReserve(bike).Returns<Task>(x => throw new WebConnectFailureException("Context info.", new Exception("chub")));
|
connector.Command.DoReserve(bike).Returns<Task>(x => throw new WebConnectFailureException("Context info.", new Exception("chub")));
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
connector.Command.DoReserve(bike).Returns<Task>(x => throw new Exception("Exception message."));
|
connector.Command.DoReserve(bike).Returns<Task>(x => throw new Exception("Exception message."));
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
locks.TimeOut.Returns(timeOuts);
|
locks.TimeOut.Returns(timeOuts);
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
locks.TimeOut.Returns(timeOuts);
|
locks.TimeOut.Returns(timeOuts);
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||||
|
|
||||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||||
|
|
||||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new InvalidAuthorizationResponseException("mustermann@server.de", response));
|
connector.Command.DoCancelReservation(bike).Returns(x => throw new InvalidAuthorizationResponseException("mustermann@server.de", response));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||||
|
|
||||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new WebConnectFailureException("Context info.", new Exception("chub")));
|
connector.Command.DoCancelReservation(bike).Returns(x => throw new WebConnectFailureException("Context info.", new Exception("chub")));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||||
|
|
||||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new Exception("Exception message."));
|
connector.Command.DoCancelReservation(bike).Returns(x => throw new Exception("Exception message."));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Closed); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Closed); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
|
|
||||||
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
viewService.DisplayAlert(string.Empty, string.Format("Cancel reservation for bike {0}?", "Nr. 0"), "Yes", "No").Returns(Task.FromResult(true));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Disposable); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
|
|
||||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new InvalidAuthorizationResponseException("mustermann@server.de", l_oResponse));
|
connector.Command.DoCancelReservation(bike).Returns(x => throw new InvalidAuthorizationResponseException("mustermann@server.de", l_oResponse));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
|
|
||||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("chub")));
|
connector.Command.DoCancelReservation(bike).Returns(x => throw new WebConnectFailureException("Context info", new Exception("chub")));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
|
|
||||||
connector.Command.DoCancelReservation(bike).Returns(x => throw new Exception("Exception message."));
|
connector.Command.DoCancelReservation(bike).Returns(x => throw new Exception("Exception message."));
|
||||||
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Reserved); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.UnknownDisconnected); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
|
||||||
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
|
viewService.DisplayAlert(string.Empty, "Rad Nr. 0 abschließen und zurückgeben oder Rad mieten?", "Zurückgeben", "Mieten").Returns(Task.FromResult(false));
|
||||||
|
|
||||||
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
bike.State.Value.Returns(InUseStateEnum.Booked); // Reqesthandler factory queries state to create appropriate request handler object.
|
||||||
bike.LockInfo.State.Returns(LockingState.Open); // Requsthandler factory queries lock state to create appropriate request handler object.
|
bike.LockInfo.State.Returns(LockingState.Open); // Requesthandler factory queries lock state to create appropriate request handler object.
|
||||||
|
|
||||||
var subsequent = handler.HandleRequestOption1().Result;
|
var subsequent = handler.HandleRequestOption1().Result;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ using TestFramework.Model.Device;
|
||||||
using TestFramework.Model.Services.Geolocation;
|
using TestFramework.Model.Services.Geolocation;
|
||||||
using TestFramework.Model.User.Account;
|
using TestFramework.Model.User.Account;
|
||||||
using TestFramework.Repository;
|
using TestFramework.Repository;
|
||||||
using TestFramework.Services.CopriApi.Connector;
|
|
||||||
using TINK.Model;
|
using TINK.Model;
|
||||||
using TINK.Model.Connector;
|
using TINK.Model.Connector;
|
||||||
using TINK.Model.Device;
|
using TINK.Model.Device;
|
||||||
|
|
|
@ -10,11 +10,14 @@ using TestFramework.Model.Services.Geolocation;
|
||||||
using TestFramework.Model.User.Account;
|
using TestFramework.Model.User.Account;
|
||||||
using TestFramework.Repository;
|
using TestFramework.Repository;
|
||||||
using TestFramework.Services.BluetoothLock;
|
using TestFramework.Services.BluetoothLock;
|
||||||
using TestFramework.Services.CopriApi.Connector;
|
|
||||||
using TINK.Model;
|
using TINK.Model;
|
||||||
|
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||||
|
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
|
||||||
|
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
|
||||||
using TINK.Model.Connector;
|
using TINK.Model.Connector;
|
||||||
using TINK.Model.Services.CopriApi;
|
using TINK.Model.Services.CopriApi;
|
||||||
using TINK.Model.Settings;
|
using TINK.Model.Settings;
|
||||||
|
using TINK.Model.Stations.StationNS;
|
||||||
using TINK.Repository;
|
using TINK.Repository;
|
||||||
using TINK.Repository.Exception;
|
using TINK.Repository.Exception;
|
||||||
using TINK.Services;
|
using TINK.Services;
|
||||||
|
@ -24,6 +27,8 @@ using TINK.View;
|
||||||
using TINK.ViewModel.Map;
|
using TINK.ViewModel.Map;
|
||||||
using TINK.ViewModel.Settings;
|
using TINK.ViewModel.Settings;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
using TINK.Model.Bikes.BikeInfoNS;
|
||||||
|
using TINK.Model.Stations.StationNS.Operator;
|
||||||
|
|
||||||
namespace TestShareeLib.UseCases.Startup
|
namespace TestShareeLib.UseCases.Startup
|
||||||
{
|
{
|
||||||
|
@ -46,7 +51,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||||
new StoreMock(),
|
new StoreMock(),
|
||||||
isConnectedFunc: () => true,
|
isConnectedFunc: () => true,
|
||||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
|
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
|
||||||
merchantId: "MyMerchId",
|
merchantId: "MyMerchId",
|
||||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||||
|
@ -85,11 +90,11 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
// Verify pins on map
|
// Verify pins on map
|
||||||
Assert.AreEqual(27, viewModel.Pins.Count); // Were 8 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
Assert.AreEqual(27, viewModel.Pins.Count); // Were 8 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green")).Tag,
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag,
|
||||||
Is.EqualTo("FR101"),
|
Is.EqualTo("FR101"),
|
||||||
"Station FR105 must be marked green because there is are bike.");
|
"Station FR105 must be marked green because there are bikes.");
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red")).Tag,
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag,
|
||||||
Is.EqualTo("KN12"),
|
Is.EqualTo("KN12"),
|
||||||
"Station KN12 must be marked red because there is no bike."); // Was station id 31
|
"Station KN12 must be marked red because there is no bike."); // Was station id 31
|
||||||
|
|
||||||
|
@ -127,7 +132,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||||
new StoreMock(),
|
new StoreMock(),
|
||||||
isConnectedFunc: () => true,
|
isConnectedFunc: () => true,
|
||||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
|
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
|
||||||
merchantId: "MyMerchId",
|
merchantId: "MyMerchId",
|
||||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||||
|
@ -151,8 +156,8 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
var viewModel = new MapPageViewModel(
|
var viewModel = new MapPageViewModel(
|
||||||
tinkApp,
|
tinkApp,
|
||||||
locationPermission,
|
locationPermission,
|
||||||
NSubstitute.Substitute.For<Plugin.BLE.Abstractions.Contracts.IBluetoothLE>(),
|
Substitute.For<IBluetoothLE>(),
|
||||||
NSubstitute.Substitute.For<IGeolocationService>(),
|
Substitute.For<IGeolocationService>(),
|
||||||
(mapspan) => { },
|
(mapspan) => { },
|
||||||
viewService,
|
viewService,
|
||||||
navigationService);
|
navigationService);
|
||||||
|
@ -166,11 +171,11 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
// Verify pins on map
|
// Verify pins on map
|
||||||
Assert.AreEqual(21, viewModel.Pins.Count); // Were 2 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
Assert.AreEqual(21, viewModel.Pins.Count); // Were 2 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green")).Tag, // Was station 5
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station 5
|
||||||
Is.EqualTo("FR103"),
|
Is.EqualTo("FR103"),
|
||||||
"Station FR101 must be marked green because there is are bike.");
|
"Station FR101 must be marked green because there is are bike.");
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red")).Tag, // Was station 14
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was station 14
|
||||||
Is.EqualTo("KN12"),
|
Is.EqualTo("KN12"),
|
||||||
"Station KN12 must be marked red because there is no bike.");
|
"Station KN12 must be marked red because there is no bike.");
|
||||||
|
|
||||||
|
@ -205,7 +210,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||||
new StoreMock(),
|
new StoreMock(),
|
||||||
isConnectedFunc: () => true,
|
isConnectedFunc: () => true,
|
||||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
|
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
|
||||||
merchantId: "MyMerchId",
|
merchantId: "MyMerchId",
|
||||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||||
|
@ -242,11 +247,11 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
// Verify pins on map
|
// Verify pins on map
|
||||||
Assert.AreEqual(21, viewModel.Pins.Count); // Were 2 when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
Assert.AreEqual(21, viewModel.Pins.Count); // Were 2 when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green")).Tag, // Was station id 31
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station id 31
|
||||||
Is.EqualTo("FR103"),
|
Is.EqualTo("FR103"),
|
||||||
"Station FR101 must be marked green because there is are bike.");
|
"Station FR101 must be marked green because there is are bike.");
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red")).Tag, // Was 14
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 14
|
||||||
Is.EqualTo("KN12"),
|
Is.EqualTo("KN12"),
|
||||||
"Station KN12 must be marked red because there is no bike.");
|
"Station KN12 must be marked red because there is no bike.");
|
||||||
|
|
||||||
|
@ -278,7 +283,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||||
new StoreMock(),
|
new StoreMock(),
|
||||||
isConnectedFunc: () => true,
|
isConnectedFunc: () => true,
|
||||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
|
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
|
||||||
merchantId: "MyMerchId",
|
merchantId: "MyMerchId",
|
||||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||||
|
@ -315,11 +320,11 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
// Verify pins on map
|
// Verify pins on map
|
||||||
Assert.AreEqual(27, viewModel.Pins.Count); // Were 8 pin when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
Assert.AreEqual(27, viewModel.Pins.Count); // Were 8 pin when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green")).Tag,
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag,
|
||||||
Is.EqualTo("FR101"), // Was station id 4
|
Is.EqualTo("FR101"), // Was station id 4
|
||||||
"Station FR101 must be marked green because there is are bike.");
|
"Station FR101 must be marked green because there is are bike.");
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red")).Tag, // Was 31
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 31
|
||||||
Is.EqualTo("KN12"), // Was station id 31
|
Is.EqualTo("KN12"), // Was station id 31
|
||||||
"Station KN12 must be marked red because there is no bike.");
|
"Station KN12 must be marked red because there is no bike.");
|
||||||
|
|
||||||
|
@ -351,7 +356,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
activeGeolocationService: typeof(GeolocationMock).FullName),
|
activeGeolocationService: typeof(GeolocationMock).FullName),
|
||||||
new StoreMock(),
|
new StoreMock(),
|
||||||
isConnectedFunc: () => false,
|
isConnectedFunc: () => false,
|
||||||
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001(sessionCookie)),
|
connectorFactory: (isConnected, uri, sessionCookie, mail, expiresAfter) => new ConnectorCache(new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), null /*UI language */, sessionCookie, mail, server: new CopriCallsMemory001v2NotLoggedIn(sessionCookie)),
|
||||||
merchantId: "MyMerchId",
|
merchantId: "MyMerchId",
|
||||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||||
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
locationPermissionsService: Substitute.For<ILocationPermission>(),
|
||||||
|
@ -373,7 +378,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
var viewModel = new MapPageViewModel(
|
var viewModel = new MapPageViewModel(
|
||||||
tinkApp,
|
tinkApp,
|
||||||
locationPermission,
|
locationPermission,
|
||||||
Substitute.For<Plugin.BLE.Abstractions.Contracts.IBluetoothLE>(),
|
Substitute.For<IBluetoothLE>(),
|
||||||
Substitute.For<IGeolocationService>(),
|
Substitute.For<IGeolocationService>(),
|
||||||
(mapspan) => { },
|
(mapspan) => { },
|
||||||
viewService,
|
viewService,
|
||||||
|
@ -388,11 +393,11 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
// Verify pins on map
|
// Verify pins on map
|
||||||
Assert.AreEqual(27, viewModel.Pins.Count); // Were 8 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
Assert.AreEqual(27, viewModel.Pins.Count); // Were 8 pins when loading from CopriCallsMemory(SampleSets.Set2, 1, sessionCookie)
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green")).Tag, // Was station id 4
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station id 4
|
||||||
Is.EqualTo("FR101"),
|
Is.EqualTo("FR101"),
|
||||||
"Station FR101 must be marked green because there is are bike.");
|
"Station FR101 must be marked green because there is are bike.");
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red")).Tag, // Was 31
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 31
|
||||||
Is.EqualTo("KN12"),
|
Is.EqualTo("KN12"),
|
||||||
"Station KN12 must be marked red because there is no bike.");
|
"Station KN12 must be marked red because there is no bike.");
|
||||||
|
|
||||||
|
@ -439,7 +444,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||||
null /*UI language */,
|
null /*UI language */,
|
||||||
sessionCookie: sessionCookie,
|
sessionCookie: sessionCookie,
|
||||||
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
|
cacheServer: new CopriCallsCacheMemory001v2NotLoggedIn(sessionCookie: sessionCookie),
|
||||||
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source expection."))))),
|
httpsServer: new ExceptionServer((msg) => new WebConnectFailureException(msg, new Exception("Source expection."))))),
|
||||||
merchantId: "MyMerchId",
|
merchantId: "MyMerchId",
|
||||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||||
|
@ -479,11 +484,11 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
// Verify pins on map
|
// Verify pins on map
|
||||||
Assert.AreEqual(27, viewModel.Pins.Count);
|
Assert.AreEqual(27, viewModel.Pins.Count);
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green")).Tag, // Was station id 4
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Green"))?.Tag, // Was station id 4
|
||||||
Is.EqualTo("FR101"),
|
Is.EqualTo("FR101"),
|
||||||
"Station FR101 must be marked green because there is are bike.");
|
"Station FR101 must be marked green because there is are bike.");
|
||||||
Assert.That(
|
Assert.That(
|
||||||
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red")).Tag, // Was 31
|
viewModel.Pins.FirstOrDefault(pin => pin.Icon.Id.Contains("Open_Red"))?.Tag, // Was 31
|
||||||
Is.EqualTo("KN12"),
|
Is.EqualTo("KN12"),
|
||||||
"Station KN12 must be marked red because there is no bike.");
|
"Station KN12 must be marked red because there is no bike.");
|
||||||
|
|
||||||
|
@ -529,7 +534,7 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)),
|
||||||
null /*UI language */,
|
null /*UI language */,
|
||||||
sessionCookie: sessionCookie,
|
sessionCookie: sessionCookie,
|
||||||
cacheServer: new CopriCallsCacheMemory001(sessionCookie: sessionCookie),
|
cacheServer: new CopriCallsCacheMemory001v2NotLoggedIn(sessionCookie: sessionCookie),
|
||||||
httpsServer: new ExceptionServer((msg) => new Exception(msg)))),
|
httpsServer: new ExceptionServer((msg) => new Exception(msg)))),
|
||||||
merchantId: "MyMerchId",
|
merchantId: "MyMerchId",
|
||||||
bluetoothService: Substitute.For<IBluetoothLE>(),
|
bluetoothService: Substitute.For<IBluetoothLE>(),
|
||||||
|
@ -591,5 +596,116 @@ namespace TestShareeLib.UseCases.Startup
|
||||||
await viewModel.OnDisappearing();
|
await viewModel.OnDisappearing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetStationColors()
|
||||||
|
{
|
||||||
|
var stationIds = new List<string>() { "FR101", "BVB9003", "BVB9001" };
|
||||||
|
|
||||||
|
var bikeGroupFr101 = Substitute.For<IBikeGroupCol>();
|
||||||
|
var bikeGroupBVB9003 = Substitute.For<IBikeGroupCol>();
|
||||||
|
var bikeGroupBVB9001 = Substitute.For<IBikeGroupCol>();
|
||||||
|
|
||||||
|
bikeGroupFr101.AvailableCount.Returns(1);
|
||||||
|
bikeGroupBVB9003.AvailableCount.Returns(7);
|
||||||
|
bikeGroupBVB9001.AvailableCount.Returns(0);
|
||||||
|
|
||||||
|
var stations = new List<Station>
|
||||||
|
{
|
||||||
|
new Station("FR101", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupFr101),
|
||||||
|
new Station("BVB9003", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupBVB9003),
|
||||||
|
new Station("BVB9001", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol : bikeGroupBVB9001)
|
||||||
|
};
|
||||||
|
|
||||||
|
var bikes = new List<TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo> {
|
||||||
|
// Add a reserved bike to station "FR101"
|
||||||
|
new BikeInfo(
|
||||||
|
new Bike("Id1", LockModel.ILockIt),
|
||||||
|
new Drive(),
|
||||||
|
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
|
||||||
|
123, // Lock id
|
||||||
|
new Guid(),
|
||||||
|
new byte[0],
|
||||||
|
new byte[0],
|
||||||
|
new byte[0],
|
||||||
|
DateTime.Parse("2023-03-26 15:19"),
|
||||||
|
"a@b",
|
||||||
|
"FR101",
|
||||||
|
new Uri("https://1.2.3.4"),
|
||||||
|
new RentalDescription(),
|
||||||
|
() => DateTime.Now)
|
||||||
|
};
|
||||||
|
|
||||||
|
var colorList = MapPageViewModel.GetStationColors(stationIds, stations, bikes);
|
||||||
|
|
||||||
|
Assert.That(colorList[0], Is.EqualTo(Color.LightBlue), "1 bike reserved/ rented.");
|
||||||
|
Assert.That(colorList[1], Is.EqualTo(Color.Green), "7 available bikes.");
|
||||||
|
Assert.That(colorList[2], Is.EqualTo(Color.Red), "No bike");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetStationColorsNullIds()
|
||||||
|
{
|
||||||
|
var colorList = MapPageViewModel.GetStationColors(null, null, null);
|
||||||
|
|
||||||
|
Assert.That(colorList.Count, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetStationColorsNoStations()
|
||||||
|
{
|
||||||
|
var stationIds = new List<string>() { "FR101", "BVB9003", "BVB9001" };
|
||||||
|
|
||||||
|
var bikes = new List<TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo> {
|
||||||
|
// Add a reserved bike to station "FR101"
|
||||||
|
new BikeInfo(
|
||||||
|
new Bike("Id1", LockModel.ILockIt),
|
||||||
|
new Drive(),
|
||||||
|
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
|
||||||
|
123, // Lock id
|
||||||
|
new Guid(),
|
||||||
|
new byte[0],
|
||||||
|
new byte[0],
|
||||||
|
new byte[0],
|
||||||
|
DateTime.Parse("2023-03-26 15:19"),
|
||||||
|
"a@b",
|
||||||
|
"FR101",
|
||||||
|
new Uri("https://1.2.3.4"),
|
||||||
|
new RentalDescription(),
|
||||||
|
() => DateTime.Now)
|
||||||
|
};
|
||||||
|
|
||||||
|
var colorList = MapPageViewModel.GetStationColors(stationIds, null, bikes);
|
||||||
|
|
||||||
|
Assert.That(colorList[0], Is.EqualTo(Color.LightBlue), "1 bike reserved/ rented.");
|
||||||
|
Assert.That(colorList[1], Is.EqualTo(Color.Red), "No bike.");
|
||||||
|
Assert.That(colorList[2], Is.EqualTo(Color.Red), "No bike");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGetStationColorsNoBikes()
|
||||||
|
{
|
||||||
|
var stationIds = new List<string>() { "FR101", "BVB9003", "BVB9001" };
|
||||||
|
var bikeGroupFr101 = Substitute.For<IBikeGroupCol>();
|
||||||
|
var bikeGroupBVB9003 = Substitute.For<IBikeGroupCol>();
|
||||||
|
var bikeGroupBVB9001 = Substitute.For<IBikeGroupCol>();
|
||||||
|
|
||||||
|
bikeGroupFr101.AvailableCount.Returns(1);
|
||||||
|
bikeGroupBVB9003.AvailableCount.Returns(7);
|
||||||
|
bikeGroupBVB9001.AvailableCount.Returns(0);
|
||||||
|
|
||||||
|
var stations = new List<Station>
|
||||||
|
{
|
||||||
|
new Station("FR101", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupFr101),
|
||||||
|
new Station("BVB9003", new List<string>() /* group */, Substitute.For<IPosition>(),bikeGropCol: bikeGroupBVB9003),
|
||||||
|
new Station("BVB9001", new List<string>() /* group */, Substitute.For<IPosition>(), bikeGropCol: bikeGroupBVB9001)
|
||||||
|
};
|
||||||
|
|
||||||
|
var colorList = MapPageViewModel.GetStationColors(stationIds, stations, null);
|
||||||
|
|
||||||
|
Assert.That(colorList[0], Is.EqualTo(Color.Green), "No bike reserved/ rented.");
|
||||||
|
Assert.That(colorList[1], Is.EqualTo(Color.Green), "7 available bikes.");
|
||||||
|
Assert.That(colorList[2], Is.EqualTo(Color.Red), "No bike");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ using TestFramework.Model.Device;
|
||||||
using TestFramework.Model.Services.Geolocation;
|
using TestFramework.Model.Services.Geolocation;
|
||||||
using TestFramework.Model.User.Account;
|
using TestFramework.Model.User.Account;
|
||||||
using TestFramework.Repository;
|
using TestFramework.Repository;
|
||||||
using TestTINKLib.Mocks.Connector;
|
|
||||||
using TINK.Model;
|
using TINK.Model;
|
||||||
using TINK.Model.Connector;
|
using TINK.Model.Connector;
|
||||||
using TINK.Model.Device;
|
using TINK.Model.Device;
|
||||||
|
|
|
@ -14,8 +14,10 @@ https
|
||||||
Namespace
|
Namespace
|
||||||
offline
|
offline
|
||||||
ok
|
ok
|
||||||
|
pedelecs
|
||||||
popup
|
popup
|
||||||
pwd
|
pwd
|
||||||
|
refactored
|
||||||
uri
|
uri
|
||||||
uris
|
uris
|
||||||
Url
|
Url
|
||||||
|
|
Loading…
Reference in a new issue