Version 3.0.357

This commit is contained in:
Anja 2023-01-18 14:22:51 +01:00
parent 5980410182
commit 5c0b2e70c9
84 changed files with 1012 additions and 449 deletions

View file

@ -1,5 +1,5 @@
<?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.356" android:versionCode="356">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.357" android:versionCode="357">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
<!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services -->

View file

@ -56,8 +56,8 @@
<key>CFBundleDisplayName</key>
<string>LastenradBayern</string>
<key>CFBundleVersion</key>
<string>356</string>
<string>357</string>
<key>CFBundleShortVersionString</key>
<string>3.0.356</string>
<string>3.0.357</string>
</dict>
</plist>

View file

@ -97,7 +97,7 @@
<!--While process is running-->
<sharedGui:RunningProcessViewBay
IsVisible="{Binding IsRunning}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.Row="1"/>
</Grid>

View file

@ -36,8 +36,8 @@
FontSize="Small"
VerticalOptions="Center"
HorizontalOptions="FillAndExpand"/>
<ActivityIndicator IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}"
<ActivityIndicator IsRunning="{Binding IsProcessWithRunningProcessView}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
HeightRequest="20"
VerticalOptions="CenterAndExpand"
HorizontalOptions="End">

View file

@ -1,4 +1,4 @@

using System.Globalization;
using Serilog;
using TINK.ViewModel.CopriWebView;
@ -48,4 +48,4 @@ namespace TINK.View.CopriWebView
App.ModelRoot.NextActiveUri.Host);
}
}
}
}

View file

@ -58,7 +58,7 @@
<!--While process is running-->
<sharedGui:RunningProcessViewBay
Grid.Row="0"
IsVisible="{Binding IsRunning}"/>
IsVisible="{Binding IsProcessWithRunningProcessView}"/>
</Grid>

View file

@ -93,8 +93,8 @@
<ActivityIndicator
Grid.RowSpan="4"
Grid.ColumnSpan="3"
IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}"
IsRunning="{Binding IsProcessWithRunningProcessView}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Scale="2"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"

View file

@ -55,7 +55,7 @@
<!--While process is running-->
<sharedGui:RunningProcessViewBay
Grid.Row="0"
IsVisible="{Binding IsRunning}"/>
IsVisible="{Binding IsProcessWithRunningProcessView}"/>
</Grid>

View file

@ -1,4 +1,4 @@
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
namespace TINK.Services.BluetoothLock.Exception
{
@ -11,7 +11,9 @@ namespace TINK.Services.BluetoothLock.Exception
/// </remarks>
public class BluetoothDisconnectedException : StateAwareException
{
public BluetoothDisconnectedException() : base(LockingState.UnknownDisconnected, MultilingualResources.Resources.ErrorBluetoothDisconnectedException)
public BluetoothDisconnectedException() : base(
LockingState.UnknownDisconnected,
MultilingualResources.Resources.ErrorBluetoothDisconnectedException)
{
}
}

View file

@ -1,5 +1,5 @@
<?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.356" android:versionCode="356">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.357" android:versionCode="357">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
<!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services -->

View file

@ -56,8 +56,8 @@
<key>CFBundleDisplayName</key>
<string>Mein konrad</string>
<key>CFBundleVersion</key>
<string>356</string>
<string>357</string>
<key>CFBundleShortVersionString</key>
<string>3.0.356</string>
<string>3.0.357</string>
</dict>
</plist>

View file

@ -26,6 +26,9 @@
<!--TogglePasswortEntry-->
<x:String x:Key="EyeOpen">&#xf06e;</x:String>
<x:String x:Key="EyeClose">&#xf070;</x:String>
<!--Triangle exclamation-->
<x:String x:Key="Attention">&#xf071;</x:String>
<!-- Add more resources here -->
<ResourceDictionary.MergedDictionaries>

View file

@ -75,6 +75,25 @@
IsVisible="{Binding IsLockitButtonVisible}"
IsEnabled="{Binding IsIdle}"
Command="{Binding OnLockitButtonClicked}"/>
<!--Hint for Cache Daten.-->
<StackLayout
Orientation="Horizontal"
HorizontalOptions="CenterAndExpand"
IsVisible="{Binding IsDataFromCache}">
<Image>
<Image.Source>
<FontImageSource
Glyph="{StaticResource Attention}"
Color="Red"
FontFamily="FA-S"
Size="Small"/>
</Image.Source>
</Image>
<Label
TextColor="Red"
FontSize="Small"
Text="{x:Static resources:AppResources.MarkingDataIsFromCache}"/>
</StackLayout>
<!-- Rental description (tarif name, options and rental info -->
<Grid
RowSpacing="0"

View file

@ -61,7 +61,10 @@
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
<!--No Bikes-->
<Label Grid.Row="1"
@ -72,7 +75,7 @@
<Label
Grid.Row="2"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
@ -114,7 +117,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.Row="0"/>
</Grid>

View file

@ -118,7 +118,7 @@
Grid.Row="3"
Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
@ -126,7 +126,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.RowSpan="4"
Grid.ColumnSpan="3"/>

View file

@ -52,7 +52,10 @@
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
</StackLayout>
@ -60,7 +63,7 @@
<Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
@ -72,7 +75,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
Grid.Row="0"
IsVisible="{Binding IsRunning}"/>
IsVisible="{Binding IsProcessWithRunningProcessView}"/>
</Grid>

View file

@ -100,7 +100,7 @@
Grid.Row="3"
Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
@ -108,7 +108,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.RowSpan="4"
Grid.ColumnSpan="3"/>

View file

@ -43,7 +43,10 @@
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
<!--No Bikes-->
<Label
@ -55,7 +58,7 @@
<Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
@ -67,7 +70,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
Grid.Row="0"
IsVisible="{Binding IsRunning}"/>
IsVisible="{Binding IsProcessWithRunningProcessView}"/>
</Grid>

View file

@ -35,7 +35,7 @@
<!--Spinner-->
<ActivityIndicator
IsRunning="{Binding IsRunning}"
IsRunning="{Binding IsProcessWithRunningProcessView}"
Scale="2"
VerticalOptions="Center"
HorizontalOptions="Center"

View file

@ -25,8 +25,8 @@
<!--Spinner-->
<ActivityIndicator
Grid.Row="0"
IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}"
IsRunning="{Binding IsProcessWithRunningProcessView}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Scale="2"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"

View file

@ -1,5 +1,5 @@
<?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.356" android:versionCode="356">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.357" android:versionCode="357">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
<!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services -->

View file

@ -56,8 +56,8 @@
<key>CFBundleDisplayName</key>
<string>sharee.bike</string>
<key>CFBundleVersion</key>
<string>356</string>
<string>357</string>
<key>CFBundleShortVersionString</key>
<string>3.0.356</string>
<string>3.0.357</string>
</dict>
</plist>

View file

@ -26,6 +26,9 @@
<!--TogglePasswortEntry-->
<x:String x:Key="EyeOpen">&#xf06e;</x:String>
<x:String x:Key="EyeClose">&#xf070;</x:String>
<!--Triangle exclamation-->
<x:String x:Key="Attention">&#xf071;</x:String>
<!-- Add more resources here -->
<ResourceDictionary.MergedDictionaries>

View file

@ -51,25 +51,42 @@
</StackLayout>
</Grid>
<!-- Rental state -->
<Label
<Label
Text="{Binding StateText}"
TextColor="{Binding StateColor}"/>
<Label
<Label
Text="{Binding ErrorText}"
IsVisible="{Binding ErrorText, Converter={StaticResource Label_Converter}}"
TextColor="Red"/>
<Button
Text="{Binding ButtonText}"
IsVisible="{Binding IsButtonVisible}"
IsEnabled="{Binding IsIdle}"
Command="{Binding OnButtonClicked}"/>
<Button
Style="{StaticResource SecondaryButton}"
Text="{Binding LockitButtonText}"
IsVisible="{Binding IsLockitButtonVisible}"
IsEnabled="{Binding IsIdle}"
Command="{Binding OnLockitButtonClicked}"/>
<!-- Rental description (tarif name, options and rental info -->
<!--Hint for Cache Daten.-->
<StackLayout
Orientation="Horizontal"
HorizontalOptions="CenterAndExpand"
IsVisible="{Binding IsDataFromCache}">
<Image>
<Image.Source>
<FontImageSource
Glyph="{StaticResource Attention}"
Color="Red"
FontFamily="FA-S"
Size="Small"/>
</Image.Source>
</Image>
<Label
TextColor="Red"
FontSize="Small"
Text="{x:Static resources:AppResources.MarkingDataIsFromCache}"/>
</StackLayout>
<!-- Rental description (tarif name, options and rental info -->
<Grid
RowSpacing="0"
IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}">

View file

@ -8,14 +8,14 @@
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
Shell.FlyoutBehavior="Disabled"
Shell.NavBarIsVisible="{Binding IsIdle}">
<Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}"
Text="{Binding Title}"/>
</Grid>
</Shell.TitleView>
<ContentPage.Resources>
<ResourceDictionary>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
@ -61,7 +61,10 @@
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
<!--No Bikes-->
<Label Grid.Row="1"
@ -72,7 +75,7 @@
<Label
Grid.Row="2"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
@ -114,7 +117,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.Row="0"/>
</Grid>

View file

@ -117,7 +117,7 @@
Grid.Row="3"
Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
@ -125,7 +125,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.RowSpan="4"
Grid.ColumnSpan="3"/>

View file

@ -1,4 +1,4 @@

using System.Globalization;
using Serilog;
using TINK.ViewModel.CopriWebView;
@ -48,4 +48,4 @@ namespace TINK.View.CopriWebView
App.ModelRoot.NextActiveUri.Host);
}
}
}
}

View file

@ -34,26 +34,29 @@
<!--Search bike-->
<StackLayout Grid.Row="0">
<Entry
Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
IsVisible="{Binding IsSelectBikeVisible}"
MaxLength="10"
CursorPosition="0"
Text="{Binding BikeIdUserInput}"/>
Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
IsVisible="{Binding IsSelectBikeVisible}"
MaxLength="10"
CursorPosition="0"
Text="{Binding BikeIdUserInput}"/>
<Button
Text="{x:Static resources:AppResources.MarkingFindBike}"
IsEnabled="{Binding IsSelectBikeEnabled}"
IsVisible="{Binding IsSelectBikeVisible}"
Command="{Binding OnSelectBikeRequest}"/>
Text="{x:Static resources:AppResources.MarkingFindBike}"
IsEnabled="{Binding IsSelectBikeEnabled}"
IsVisible="{Binding IsSelectBikeVisible}"
Command="{Binding OnSelectBikeRequest}"/>
<ListView
x:Name="FindBikeListView"
SelectionMode="None"
SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
x:Name="FindBikeListView"
SelectionMode="None"
SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
</StackLayout>
@ -61,7 +64,7 @@
<Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
@ -73,7 +76,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
Grid.Row="0"
IsVisible="{Binding IsRunning}"/>
IsVisible="{Binding IsProcessWithRunningProcessView}"/>
</Grid>

View file

@ -99,7 +99,7 @@
Grid.Row="3"
Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
@ -107,7 +107,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.RowSpan="4"
Grid.ColumnSpan="3"/>

View file

@ -42,7 +42,10 @@
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
<!--No Bikes-->
<Label
@ -54,7 +57,7 @@
<Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
@ -66,7 +69,7 @@
<!--While process is running-->
<sharedGui:RunningProcessView
Grid.Row="0"
IsVisible="{Binding IsRunning}"/>
IsVisible="{Binding IsProcessWithRunningProcessView}"/>
</Grid>

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@ -26,7 +26,8 @@ namespace TINK.Model.Bikes
/// <param name="bikesAll"> Object holding bikes info from copri to update from. Holds station id but not station name.</param>
/// <param name="stations"> All stations to get station names from.</param>
/// <param name="p_oDateTimeProvider">Provices date time information.</param>
public void Update(IEnumerable<BikeInfo> bikesAll,
public void Update(
IEnumerable<BikeInfo> bikesAll,
IEnumerable<IStation> stations)
{
// Get list of current bikes by state(s) to update.
@ -54,7 +55,9 @@ namespace TINK.Model.Bikes
}
// Update bike.
GetById(bikeInfo.Id).State.Load(bikeInfo.State);
var updateTarget = GetById(bikeInfo.Id);
updateTarget.State.Load(bikeInfo.State);
updateTarget.DataSource = bikeInfo.DataSource;
if (bikesToBeRemoved.Contains<string>(bikeInfo.Id))
{
@ -109,11 +112,7 @@ namespace TINK.Model.Bikes
/// <param name="id"></param>
/// <returns></returns>
public BikeInfoMutable GetById(string id)
{
{
return this.FirstOrDefault(bike => bike.Id == id);
}
}
=> this.FirstOrDefault(bike => bike.Id == id);
/// <summary>
/// Deteermines whether a bike by given key exists.
@ -121,9 +120,7 @@ namespace TINK.Model.Bikes
/// <param name="p_strKey">Key to check.</param>
/// <returns>True if bike exists.</returns>
public bool ContainsKey(string id)
{
return GetById(id) != null;
}
=> GetById(id) != null;
/// <summary>
/// Removes a bike by its id.
@ -150,9 +147,9 @@ namespace TINK.Model.Bikes
BikeInfo bikeInfo,
string stationName)
{
if (bikeInfo is Bikes.BikeInfoNS.BluetoothLock.BikeInfo btBikeInfo)
if (bikeInfo is BikeInfoNS.BluetoothLock.BikeInfo btBikeInfo)
{
return new Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(btBikeInfo, stationName);
return new BikeInfoNS.BluetoothLock.BikeInfoMutable(btBikeInfo, stationName);
}
else if (bikeInfo is BikeInfoNS.CopriLock.BikeInfo copriBikeInfo)
{

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
@ -17,18 +17,23 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// <summary>
/// Holds the bike object.
/// </summary>
public BikeNS.Bike Bike { get; }
public Bike Bike { get; }
/// <summary>
/// Holds the drive object.
/// </summary>
public Drive Drive { get; }
/// <summary> Gets the information where the data origins from. </summary>
public DataSource DataSource { get; }
/// <summary> Constructs a bike object.</summary>
/// <param name="dataSource">Specified the source of the data.</param>
protected BikeInfo(
IStateInfo stateInfo,
BikeNS.Bike bike,
Bike bike,
Drive drive,
DataSource dataSource,
bool? isDemo = DEFAULTVALUEISDEMO,
IEnumerable<string> group = null,
string stationId = null,
@ -37,6 +42,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
{
Bike = bike ?? throw new ArgumentNullException(nameof(bike));
Drive = drive ?? throw new ArgumentNullException(nameof(drive));
DataSource = dataSource;
_StateInfo = stateInfo;
IsDemo = isDemo ?? DEFAULTVALUEISDEMO;
@ -50,6 +56,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
bikeInfo != null ? bikeInfo?.State : throw new ArgumentNullException(nameof(bikeInfo)),
bikeInfo.Bike,
bikeInfo.Drive,
bikeInfo.DataSource,
bikeInfo.IsDemo,
bikeInfo.Group,
bikeInfo.StationId,
@ -60,12 +67,14 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// <summary>
/// Constructs a bike info object for a available bike.
/// </summary>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="stationId">Id of station where bike is located.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <param name="tariffDescription">Hold tariff description of bike.</param>
public BikeInfo(
BikeNS.Bike bike,
Bike bike,
Drive drive,
DataSource dataSource,
string stationId,
Uri operatorUri = null,
RentalDescription tariffDescription = null,
@ -74,6 +83,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
new StateInfo(),
bike,
drive,
dataSource,
isDemo,
group,
stationId,
@ -85,6 +95,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// <summary>
/// Constructs a bike info object for a booked bike.
/// </summary>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="dateTimeProvider">Provider for current date time to calculate remainig time on demand for state of type reserved.</param>
/// <param name="currentStationId">Name of station where bike is located, null if bike is on the road.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
@ -93,8 +104,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// <param name="mailAddress">Mail address of user which booked bike.</param>
/// <param name="code">Booking code.</param>
public BikeInfo(
BikeNS.Bike bike,
Bike bike,
Drive drive,
DataSource dataSource,
bool? isDemo,
IEnumerable<string> group,
string currentStationId,
@ -109,6 +121,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
code),
bike,
drive,
dataSource,
isDemo,
group,
currentStationId,
@ -131,7 +144,6 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// <summary> Holds description about the tarif. </summary>
public RentalDescription TariffDescription { get; }
/// Holds the rent state of the bike.
/// </summary>
public IStateInfo State

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
@ -12,7 +12,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
public class BikeInfoMutable : IBikeInfoMutable, INotifyPropertyChanged
{
/// <summary> Holds the bike. </summary>
private readonly BikeNS.Bike _Bike;
private readonly Bike _Bike;
/// <summary> Holds the drive of the bike. </summary>
private readonly Drive _Drive;
@ -30,8 +30,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// <param name="tariffDescription">Hold tariff description of bike.</param>
/// <param name="stateInfo">Bike state info.</param>
protected BikeInfoMutable(
BikeNS.Bike bike,
Bike bike,
Drive drive,
DataSource dataSource,
bool isDemo = BikeInfo.DEFAULTVALUEISDEMO,
IEnumerable<string> group = null,
string stationId = null,
@ -45,6 +46,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
Group = group;
_Bike = bike;
_Drive = drive;
DataSource = dataSource;
_StateInfo = new StateInfoMutable(dateTimeProvider, stateInfo);
_StateInfo.PropertyChanged += (sender, eventargs) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(eventargs.PropertyName));
StationId = stationId;
@ -59,6 +61,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
? bike.Bike
: throw new ArgumentNullException(nameof(bike)),
bike.Drive,
bike.DataSource,
bike.IsDemo,
bike.Group,
bike.StationId,
@ -121,6 +124,22 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
private DataSource _DataSource = DataSource.Copri;
/// <summary> Gets or sets the information where the data origins from. </summary>
public DataSource DataSource
{
get => _DataSource;
set
{
if (_DataSource == value)
return;
_DataSource = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DataSource)));
}
}
/// <summary>
/// Converts the instance to text.
/// </summary>

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.State;
@ -20,6 +20,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// </summary>
Drive Drive { get; }
/// <summary> Gets or sets the information where the data origins from. </summary>
DataSource DataSource { get; }
/// <summary> True if bike is a demo bike. </summary>
bool IsDemo { get; }
@ -44,4 +47,19 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// </summary>
IStateInfo State { get; }
}
/// <summary>
/// Origin of the data.
/// </summary>
public enum DataSource
{
/// <summary>
/// Data source corpi.
/// </summary>
Copri,
/// <summary>
/// Data source cache.
/// </summary>
Cache
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
@ -56,6 +56,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.BC
/// </summary>
Drive Drive { get; }
/// <summary> Gets or sets the information where the data origins from. </summary>
DataSource DataSource { get; set; }
event PropertyChangedEventHandler PropertyChanged;
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.State;
@ -11,6 +12,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
/// <summary>
/// Constructs a bike info object for a available bike.
/// </summary>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="lockId">Id of the lock.</param>
/// <param name="lockGuid">GUID specifying the lock.</param>
/// <param name="currentStationId">Id of station where bike is located.</param>
@ -19,6 +21,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
public BikeInfo(
Bike bike,
Drive drive,
DataSource dataSource,
int lockId,
Guid lockGuid,
string currentStationId,
@ -36,6 +39,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
bike.Description)
: throw new ArgumentNullException(nameof(bike)),
drive,
dataSource,
isDemo,
group,
currentStationId,
@ -48,6 +52,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
/// <summary>
/// Constructs a bike info object for a requested bike.
/// </summary>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="dateTimeProvider">Provider for current date time to calculate remainig time on demand for state of type reserved.</param>
/// <param name="lockId">Id of the lock.</param>
/// <param name="lockGuid">GUID specifying the lock.</param>
@ -60,6 +65,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
public BikeInfo(
Bike bike,
Drive drive,
DataSource dataSource,
int lockId,
Guid lockGuid,
byte[] userKey,
@ -87,6 +93,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
bike.Description)
: throw new ArgumentNullException(nameof(bike)),
drive,
dataSource,
isDemo,
group,
currentStationId,
@ -99,7 +106,8 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
/// <summary>
/// Constructs a bike info object for a booked bike.
/// </summary>
/// <param name="id">Unique id of bike.</param>
/// <param name="bike">Unique id of bike.</param>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="lockId">Id of the lock.</param>
/// <param name="lockGuid">GUID specifying the lock.</param>
/// <param name="bookedAt">Date time when bike was booked</param>
@ -111,6 +119,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
public BikeInfo(
Bike bike,
Drive drive,
DataSource dataSource,
int lockId,
Guid lockGuid,
byte[] userKey,
@ -136,6 +145,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
bike.Description)
: throw new ArgumentNullException(),
drive,
dataSource,
isDemo,
group,
currentStationId,

View file

@ -1,8 +1,8 @@
using System;
using System;
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{
public class BikeInfoMutable : Model.Bikes.BikeInfoNS.BC.BikeInfoMutable, IBikeInfoMutable
public class BikeInfoMutable : BC.BikeInfoMutable, IBikeInfoMutable
{
/// <summary> Constructs a bike object from source. </summary>
public BikeInfoMutable(BikeInfo bike, string stationName) : base(
@ -10,6 +10,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
? bike.Bike
: throw new ArgumentNullException(nameof(bike)),
bike.Drive,
bike.DataSource,
bike.IsDemo,
bike.Group,
bike.StationId,

View file

@ -1,5 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.MiniSurvey;
@ -13,14 +14,16 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
/// Constructs a bike info object for a available bike or bike for which feed back is pending.
/// </summary>
/// <param name="bike">Bike object.</param>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="currentStationId">Id of station where bike is located.</param>
/// <param name="lockInfo">Lock info.</param>
/// <param name="isFeedbackPending">If true user has not yet given feedback after returning bike.</param>
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <param name="tariffDescription">Hold tariff description of bike.</param>
public BikeInfo(
BikeNS.Bike bike,
Bike bike,
Drive drive,
DataSource dataSource,
string currentStationId,
LockInfo lockInfo,
bool isFeedbackPending = false,
@ -40,6 +43,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
bike.Description)
: throw new ArgumentNullException(nameof(bike)),
drive,
dataSource,
isDemo,
group,
currentStationId,
@ -55,6 +59,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
/// Constructs a bike info object for a requested bike.
/// </summary>
/// <param name="bike">Bike object.</param>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="requestedAt">Date time when bike was requested</param>
/// <param name="mailAddress">Mail address of user which requested bike.</param>
/// <param name="currentStationId">Name of station where bike is located, null if bike is on the road.</param>
@ -63,8 +68,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
/// <param name="tariffDescription">Hold tariff description of bike.</param>
/// <param name="dateTimeProvider">Provider for current date time to calculate remainig time on demand for state of type reserved.</param>
public BikeInfo(
BikeNS.Bike bike,
Bike bike,
Drive drive,
DataSource dataSource,
DateTime requestedAt,
string mailAddress,
string currentStationId,
@ -80,7 +86,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
mailAddress,
""),
bike != null
? new BikeNS.Bike(
? new Bike(
bike.Id,
LockModel.Sigo /* Ensure consistend lock model value */,
bike.WheelType,
@ -88,6 +94,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
bike.Description)
: throw new ArgumentNullException(nameof(bike)),
drive,
dataSource,
isDemo,
group,
currentStationId,
@ -103,6 +110,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
/// Constructs a bike info object for a booked bike.
/// </summary>
/// <param name="bike">Bike object.</param>
/// <param name="dataSource">Specified the source of the data.</param>
/// <param name="bookedAt">Date time when bike was booked</param>
/// <param name="mailAddress">Mail address of user which booked bike.</param>
/// <param name="currentStationId">Name of station where bike is located, null if bike is on the road.</param>
@ -110,8 +118,9 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
/// <param name="operatorUri">Holds the uri of the operator or null, in case of single operator setup.</param>
/// <param name="tariffDescription">Hold tariff description of bike.</param>
public BikeInfo(
BikeNS.Bike bike,
Bike bike,
Drive drive,
DataSource dataSource,
DateTime bookedAt,
string mailAddress,
string currentStationId,
@ -125,7 +134,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
mailAddress,
""),
bike != null
? new BikeNS.Bike(
? new Bike(
bike.Id,
LockModel.Sigo /* Ensure consistend lock model value */,
bike.WheelType,
@ -133,6 +142,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
bike.Description)
: throw new ArgumentNullException(nameof(bike)),
drive,
dataSource,
isDemo,
group,
currentStationId,
@ -143,7 +153,6 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
MiniSurvey = new MiniSurveyModel();
Co2Saving = string.Empty;
}
public BikeInfo(BC.BikeInfo bikeInfo, LockInfo lockInfo) : base(
bikeInfo ?? throw new ArgumentException($"Can not copy-construct {typeof(BikeInfo).Name}-object. Source bike info must not be null."))
{

View file

@ -1,4 +1,4 @@
using System;
using System;
namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
{
@ -10,6 +10,7 @@ namespace TINK.Model.Bikes.BikeInfoNS.CopriLock
? bike.Bike
: throw new ArgumentNullException(nameof(bike)),
bike.Drive,
bike.DataSource,
bike.IsDemo,
bike.Group,
bike.StationId,

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Serilog;
@ -11,9 +11,10 @@ using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
namespace TINK.Model.Connector
{
/// <summary> Provides query functionality for use without log in. </summary>
public class CachedQuery : Base, IQuery
{
/// <summary> Cached copri server. </summary>
/// <summary> Cached copri server (connection to copri backed up by cache). </summary>
private readonly ICachedCopriServer server;
/// <summary>Constructs a copri query object.</summary>
@ -40,7 +41,7 @@ namespace TINK.Model.Connector
resultStations.Source,
new StationsAndBikesContainer(
resultStations.Response.GetStationsAllMutable(),
(await server.GetBikesAvailable(true)).Response.GetBikesAvailable()),
(await server.GetBikesAvailable(true)).Response.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Cache)),
resultStations.GeneralData,
resultStations.Exception);
}
@ -53,7 +54,7 @@ namespace TINK.Model.Connector
resultBikes.Source,
new StationsAndBikesContainer(
(await server.GetStations(true)).Response.GetStationsAllMutable(),
resultBikes.Response.GetBikesAvailable()),
resultBikes.Response.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Cache)),
resultBikes.GeneralData,
resultBikes.Exception);
}
@ -64,7 +65,7 @@ namespace TINK.Model.Connector
return new Result<StationsAndBikesContainer>(
resultStations.Source,
new StationsAndBikesContainer(resultStations.Response.GetStationsAllMutable(), resultBikes.Response.GetBikesAvailable()),
new StationsAndBikesContainer(resultStations.Response.GetStationsAllMutable(), resultBikes.Response.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Copri)),
resultStations.GeneralData);
}
@ -73,6 +74,7 @@ namespace TINK.Model.Connector
public async Task<Result<BikeCollection>> GetBikesOccupiedAsync()
{
Log.ForContext<CachedQuery>().Error("Unexpected call to get be bikes occpied detected. No user is logged in.");
return new Result<BikeCollection>(
typeof(CopriCallsMonkeyStore),
await Task.FromResult(new BikeCollection(new Dictionary<string, BikeInfo>())),
@ -85,8 +87,20 @@ namespace TINK.Model.Connector
public async Task<Result<BikeCollection>> GetBikesAsync()
{
var result = await server.GetBikesAvailable();
server.AddToCache(result);
return new Result<BikeCollection>(result.Source, result.Response.GetBikesAvailable(), result.GeneralData, result.Exception);
if (result.Source != typeof(CopriCallsMonkeyStore))
{
server.AddToCache(result);
}
return new Result<BikeCollection>(
result.Source,
result.Response.GetBikesAvailable(result.Source == typeof(CopriCallsMonkeyStore)
? Bikes.BikeInfoNS.BC.DataSource.Cache
: Bikes.BikeInfoNS.BC.DataSource.Copri),
result.GeneralData,
result.Exception);
}
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Threading.Tasks;
using Serilog;
@ -12,7 +12,7 @@ namespace TINK.Model.Connector
/// <summary> Provides query functionality for a logged in user. </summary>
public class CachedQueryLoggedIn : BaseLoggedIn, IQuery
{
/// <summary> Cached copri server. </summary>
/// <summary> Cached copri server (connection to copri backed up by cache). </summary>
private ICachedCopriServer Server { get; }
/// <summary>Constructs a copri query object.</summary>
@ -42,11 +42,12 @@ namespace TINK.Model.Connector
stationsResponse.Source,
new StationsAndBikesContainer(
stationsResponse.Response.GetStationsAllMutable(),
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
(await Server.GetBikesAvailable(true)).Response?.bikes?.Values,
(await Server.GetBikesOccupied(true)).Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider)),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache)),
stationsResponse.GeneralData,
stationsResponse.Exception);
}
@ -60,10 +61,11 @@ namespace TINK.Model.Connector
bikesAvailableResponse.Source,
new StationsAndBikesContainer(
(await Server.GetStations(true)).Response.GetStationsAllMutable(),
UpdaterJSON.GetBikesAll(bikesAvailableResponse.Response?.bikes?.Values,
BikeCollectionFactory.GetBikesAll(bikesAvailableResponse.Response?.bikes?.Values,
(await Server.GetBikesOccupied(true)).Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider)),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache)),
bikesAvailableResponse.GeneralData,
bikesAvailableResponse.Exception);
}
@ -77,11 +79,12 @@ namespace TINK.Model.Connector
bikesOccupiedResponse.Source,
new StationsAndBikesContainer(
(await Server.GetStations(true)).Response.GetStationsAllMutable(),
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
(await Server.GetBikesAvailable(true)).Response?.bikes?.Values,
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider)),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache)),
bikesOccupiedResponse.GeneralData,
bikesOccupiedResponse.Exception);
}
@ -94,11 +97,12 @@ namespace TINK.Model.Connector
var exceptions = new[] { stationsResponse?.Exception, bikesAvailableResponse?.Exception, bikesOccupiedResponse?.Exception }.Where(x => x != null).ToArray();
var stationsMutable = stationsResponse.Response.GetStationsAllMutable();
var bikesMutable = UpdaterJSON.GetBikesAll(
var bikesMutable = BikeCollectionFactory.GetBikesAll(
bikesAvailableResponse.Response?.bikes?.Values,
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider);
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Copri);
return new Result<StationsAndBikesContainer>(
stationsResponse.Source,
@ -119,11 +123,12 @@ namespace TINK.Model.Connector
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes available read from cache. Reading bikes occupied from cache as well.");
return new Result<BikeCollection>(
bikesAvailableResponse.Source,
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
bikesAvailableResponse.Response?.bikes?.Values?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
(await Server.GetBikesOccupied(true))?.Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache),
bikesAvailableResponse.GeneralData,
bikesAvailableResponse.Exception);
}
@ -136,11 +141,12 @@ namespace TINK.Model.Connector
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes occupied read from cache. Reread bikes available from cache as well.");
return new Result<BikeCollection>(
bikesOccupiedResponse.Source,
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
(await Server.GetBikesAvailable(true)).Response?.bikes?.Values?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache),
bikesOccupiedResponse.GeneralData,
bikesOccupiedResponse.Exception);
}
@ -151,11 +157,12 @@ namespace TINK.Model.Connector
return new Result<BikeCollection>(
bikesOccupiedResponse.Source,
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
bikesAvailableResponse?.Response.bikes?.Values?.Select(bike => bike)?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
bikesOccupiedResponse?.Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Copri),
bikesOccupiedResponse.GeneralData,
bikesOccupiedResponse.Exception);
}
@ -173,11 +180,12 @@ namespace TINK.Model.Connector
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes available read from cache. Reading bikes occupied from cache as well.");
return new Result<BikeCollection>(
bikesAvailableResponse.Source,
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
bikesAvailableResponse.Response?.bikes?.Values,
(await Server.GetBikesOccupied(true)).Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache),
bikesAvailableResponse.GeneralData,
bikesAvailableResponse.Exception);
}
@ -190,11 +198,12 @@ namespace TINK.Model.Connector
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes occupied read from cache. Reread bikes available from cache as well.");
return new Result<BikeCollection>(
bikesOccupiedResponse.Source,
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
(await Server.GetBikesAvailable(true)).Response?.bikes?.Values,
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache),
bikesOccupiedResponse.GeneralData,
bikesOccupiedResponse.Exception);
}
@ -206,11 +215,12 @@ namespace TINK.Model.Connector
Log.ForContext<CachedQueryLoggedIn>().Debug("Bikes available and occupied read successfully from server.");
return new Result<BikeCollection>(
bikesAvailableResponse.Source,
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
bikesAvailableResponse.Response?.bikes?.Values,
bikesOccupiedResponse.Response?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Copri),
bikesAvailableResponse.GeneralData,
bikesAvailableResponse.Exception != null || bikesOccupiedResponse.Exception != null ? new AggregateException(new[] { bikesAvailableResponse.Exception, bikesOccupiedResponse.Exception }) : null);
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Serilog;
@ -11,20 +11,20 @@ using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
namespace TINK.Model.Connector
{
/// <summary> Provides query functionality without login. </summary>
/// <summary> Provides query functionality from cache without login. </summary>
public class Query : Base, IQuery
{
/// <summary> Cached copri server. </summary>
private readonly ICopriServer server;
/// <summary>Constructs a copri query object.</summary>
/// <param name="p_oCopriServer">Server which implements communication.</param>
public Query(ICopriServerBase p_oCopriServer) : base(p_oCopriServer)
/// <param name="copriServer">Server which implements communication.</param>
public Query(ICopriServerBase copriServer) : base(copriServer)
{
server = p_oCopriServer as ICopriServer;
server = copriServer as ICopriServer;
if (server == null)
{
throw new ArgumentException($"Copri server is not of expected typ. Type detected is {p_oCopriServer.GetType()}.");
throw new ArgumentException($"Copri server is not of expected typ. Type detected is {copriServer.GetType()}.");
}
}
@ -36,7 +36,7 @@ namespace TINK.Model.Connector
return new Result<StationsAndBikesContainer>(
typeof(CopriCallsMonkeyStore),
new StationsAndBikesContainer(stationsAllResponse.GetStationsAllMutable(), bikesAvailableResponse.GetBikesAvailable()),
new StationsAndBikesContainer(stationsAllResponse.GetStationsAllMutable(), bikesAvailableResponse.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Cache)),
stationsAllResponse.GetGeneralData());
}
@ -59,7 +59,7 @@ namespace TINK.Model.Connector
var bikesAvailableResponse = await server.GetBikesAvailableAsync();
return new Result<BikeCollection>(
typeof(CopriCallsMonkeyStore),
bikesAvailableResponse.GetBikesAvailable(),
bikesAvailableResponse.GetBikesAvailable(Bikes.BikeInfoNS.BC.DataSource.Cache),
bikesAvailableResponse.GetGeneralData());
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Threading.Tasks;
using TINK.Model.Bikes;
@ -8,7 +8,7 @@ using TINK.Repository;
namespace TINK.Model.Connector
{
/// <summary> Provides query functionality for a logged in user. </summary>
/// <summary> Provides query functionality from cache for a logged in user. </summary>
public class QueryLoggedIn : BaseLoggedIn, IQuery
{
/// <summary> Copri server. </summary>
@ -41,11 +41,12 @@ namespace TINK.Model.Connector
typeof(CopriCallsMonkeyStore),
new StationsAndBikesContainer(
stationResponse.GetStationsAllMutable(),
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
bikesAvailableResponse?.bikes?.Values,
bikesOccupiedResponse?.bikes_occupied?.Values,
Mail,
DateTimeProvider)),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache)),
stationResponse.GetGeneralData());
}
@ -58,11 +59,12 @@ namespace TINK.Model.Connector
return new Result<BikeCollection>(
typeof(CopriCallsMonkeyStore),
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
bikesFeedbackRequired.bikes?.Values?.Select(bike => bike)?.Where(bike => bike.GetState() == State.InUseStateEnum.FeedbackPending),
bikesOccupiedResponse?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache),
bikesOccupiedResponse.GetGeneralData());
}
@ -75,11 +77,12 @@ namespace TINK.Model.Connector
return new Result<BikeCollection>(
typeof(CopriCallsMonkeyStore),
UpdaterJSON.GetBikesAll(
BikeCollectionFactory.GetBikesAll(
bikesAvailableResponse?.bikes?.Values,
bikesOccupiedResponse?.bikes_occupied?.Values,
Mail,
DateTimeProvider),
DateTimeProvider,
Bikes.BikeInfoNS.BC.DataSource.Cache),
bikesAvailableResponse.GetGeneralData());
}
}

View file

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Text;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes;
using TINK.Repository.Response;
using Serilog;
namespace TINK.Model.Connector.Updater
{
public static class BikeCollectionFactory
{
/// <summary> Gets bikes available from copri server response.</summary>
/// <param name="bikesAvailableResponse">Response to create collection from.</param>
/// <param name="dataSource">Specified the data source</param>
/// <returns>New collection of available bikes.</returns>
public static BikeCollection GetBikesAvailable(
this BikesAvailableResponse bikesAvailableResponse,
DataSource dataSource)
=> GetBikesAll(
bikesAvailableResponse?.bikes?.Values,
new BikesReservedOccupiedResponse()?.bikes_occupied?.Values, // There are no occupied bikes.
string.Empty,
() => DateTime.Now,
dataSource);
/// <summary> Gets bikes occupied from copri server response. </summary>
/// <param name="bikesOccupiedResponse">Response to create bikes from.</param>
/// <param name="dataSource">Specified the data source</param>
/// <returns>New collection of occupied bikes.</returns>
public static BikeCollection GetBikesOccupied(
this BikesReservedOccupiedResponse bikesOccupiedResponse,
string mail,
Func<DateTime> dateTimeProvider,
DataSource dataSource)
=> GetBikesAll(
new BikesAvailableResponse()?.bikes?.Values,
bikesOccupiedResponse?.bikes_occupied?.Values,
mail,
dateTimeProvider,
dataSource);
/// <summary> Gets bikes occupied from copri server response. </summary>
/// <param name="bikesAvailable">Response to create bikes available from.</param>
/// <param name="bikesOccupied">Response to create bikes occupied from.</param>
/// <returns>New collection of occupied bikes.</returns>
public static BikeCollection GetBikesAll(
IEnumerable<BikeInfoAvailable> bikesAvailable,
IEnumerable<BikeInfoReservedOrBooked> bikesOccupied,
string mail,
Func<DateTime> dateTimeProvider,
DataSource dataSource)
{
var bikesDictionary = new Dictionary<string, BikeInfo>();
var duplicates = new Dictionary<string, BikeInfo>();
// Get bikes from Copri/ file/ memory, ....
if (bikesAvailable != null)
{
foreach (var bikeInfoResponse in bikesAvailable)
{
var bikeInfo = BikeInfoFactory.Create(bikeInfoResponse, dataSource);
if (bikeInfo == null)
{
// Response is not valid.
continue;
}
if (bikesDictionary.ContainsKey(bikeInfo.Id))
{
// Duplicates are not allowed.
Log.Error($"Duplicate bike with id {bikeInfo.Id} detected evaluating bikes available. Bike status is {bikeInfo.State.Value}.");
if (!duplicates.ContainsKey(bikeInfo.Id))
{
duplicates.Add(bikeInfo.Id, bikeInfo);
}
continue;
}
bikesDictionary.Add(bikeInfo.Id, bikeInfo);
}
}
// Get bikes from Copri/ file/ memory, ....
if (bikesOccupied != null)
{
foreach (var bikeInfoResponse in bikesOccupied)
{
BikeInfo bikeInfo = BikeInfoFactory.Create(
bikeInfoResponse,
mail,
dateTimeProvider,
dataSource);
if (bikeInfo == null)
{
continue;
}
if (bikesDictionary.ContainsKey(bikeInfo.Id))
{
// Duplicates are not allowed.
Log.Error($"Duplicate bike with id {bikeInfo.Id} detected evaluating bikes occupied. Bike status is {bikeInfo.State.Value}.");
if (!duplicates.ContainsKey(bikeInfo.Id))
{
duplicates.Add(bikeInfo.Id, bikeInfo);
}
continue;
}
bikesDictionary.Add(bikeInfo.Id, bikeInfo);
}
}
// Remove entries which are not unique.
foreach (var l_oDuplicate in duplicates)
{
bikesDictionary.Remove(l_oDuplicate.Key);
}
return new BikeCollection(bikesDictionary);
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using System;
using System.Collections.Generic;
using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.MiniSurvey;
using TINK.Model.State;
@ -20,7 +21,10 @@ namespace TINK.Model.Connector.Updater
/// <summary> Creates a bike info object from copri response. </summary>
/// <param name="bikeInfo">Copri response for a disposable bike. </param>
public static BikeInfo Create(BikeInfoAvailable bikeInfo)
/// <param name="dataSource">Specifies the data source.</param>
public static BikeInfo Create(
BikeInfoAvailable bikeInfo,
DataSource dataSource)
{
if (bikeInfo == null) throw new ArgumentNullException(nameof(bikeInfo));
@ -74,6 +78,7 @@ namespace TINK.Model.Connector.Updater
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
bikeInfo.station,
new Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = bikeInfo.GetCopriLockingState() }.Build(),
bikeInfo.GetState() == InUseStateEnum.FeedbackPending,
@ -103,6 +108,7 @@ namespace TINK.Model.Connector.Updater
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
bikeInfo.GetBluetoothLockId(),
bikeInfo.GetBluetoothLockGuid(),
bikeInfo.station,
@ -133,10 +139,12 @@ namespace TINK.Model.Connector.Updater
/// <param name="bikeInfo">Copri response. </param>
/// <param name="mailAddress">Mail address of user.</param>
/// <param name="dateTimeProvider">Date and time provider function.</param>
/// <param name="dataSource">Specified the source of the data.</param>
public static BikeInfo Create(
BikeInfoReservedOrBooked bikeInfo,
string mailAddress,
Func<DateTime> dateTimeProvider)
Func<DateTime> dateTimeProvider,
DataSource dataSource)
{
if (bikeInfo == null) throw new ArgumentNullException(nameof(bikeInfo));
@ -178,6 +186,7 @@ namespace TINK.Model.Connector.Updater
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
lockSerial,
lockGuid,
bikeInfo.GetUserKey(),
@ -207,6 +216,7 @@ namespace TINK.Model.Connector.Updater
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
@ -247,6 +257,7 @@ namespace TINK.Model.Connector.Updater
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
lockSerial,
bikeInfo.GetBluetoothLockGuid(),
bikeInfo.GetUserKey(),
@ -275,6 +286,7 @@ namespace TINK.Model.Connector.Updater
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup(),
bikeInfo.station,
@ -298,6 +310,7 @@ namespace TINK.Model.Connector.Updater
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
DataSource.Copri,
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,

View file

@ -1,7 +1,8 @@
using System;
using System;
using System.Collections.Generic;
using Serilog;
using TINK.Model.Bikes;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.State;
using TINK.Model.Station;
using TINK.Model.Station.Operator;
@ -26,11 +27,8 @@ namespace TINK.Model.Connector.Updater
/// <param name="notifyLevel">Controls whether notify property changed events are fired or not.</param>
public static void Load(
this IBikeInfoMutable bike,
Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel notifyLevel)
{
bike.State.Load(InUseStateEnum.Disposable, notifyLevel: notifyLevel);
}
NotifyPropertyChangedLevel notifyLevel)
=> bike.State.Load(InUseStateEnum.Disposable, notifyLevel: notifyLevel);
/// <summary>
/// Gets all statsion for station provider and add them into station list.
@ -126,7 +124,7 @@ namespace TINK.Model.Connector.Updater
this IBikeInfoMutable bike,
BikeInfoReservedOrBooked bikeInfo,
string mailAddress,
Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel notifyLevel = Bikes.BikeInfoNS.BC.NotifyPropertyChangedLevel.All)
NotifyPropertyChangedLevel notifyLevel = NotifyPropertyChangedLevel.All)
{
if (bike is Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable btBikeInfo)
{
@ -170,113 +168,5 @@ namespace TINK.Model.Connector.Updater
}
}
/// <summary> Gets bikes available from copri server response.</summary>
/// <param name="bikesAvailableResponse">Response to create collection from.</param>
/// <returns>New collection of available bikes.</returns>
public static BikeCollection GetBikesAvailable(
this BikesAvailableResponse bikesAvailableResponse)
=> GetBikesAll(
bikesAvailableResponse?.bikes?.Values,
new BikesReservedOccupiedResponse()?.bikes_occupied?.Values, // There are no occupied bikes.
string.Empty,
() => DateTime.Now);
/// <summary> Gets bikes occupied from copri server response. </summary>
/// <param name="p_oBikesAvailable">Response to create bikes from.</param>
/// <returns>New collection of occupied bikes.</returns>
public static BikeCollection GetBikesOccupied(
this BikesReservedOccupiedResponse bikesOccupiedResponse,
string mail,
Func<DateTime> dateTimeProvider)
{
return GetBikesAll(
new BikesAvailableResponse()?.bikes?.Values,
bikesOccupiedResponse?.bikes_occupied?.Values,
mail,
dateTimeProvider);
}
/// <summary> Gets bikes occupied from copri server response. </summary>
/// <param name="bikesAvailable">Response to create bikes available from.</param>
/// <param name="bikesOccupied">Response to create bikes occupied from.</param>
/// <returns>New collection of occupied bikes.</returns>
public static BikeCollection GetBikesAll(
IEnumerable<BikeInfoAvailable> bikesAvailable,
IEnumerable<BikeInfoReservedOrBooked> bikesOccupied,
string mail,
Func<DateTime> dateTimeProvider)
{
var bikesDictionary = new Dictionary<string, BikeInfo>();
var duplicates = new Dictionary<string, BikeInfo>();
// Get bikes from Copri/ file/ memory, ....
if (bikesAvailable != null)
{
foreach (var bikeInfoResponse in bikesAvailable)
{
var bikeInfo = BikeInfoFactory.Create(bikeInfoResponse);
if (bikeInfo == null)
{
// Response is not valid.
continue;
}
if (bikesDictionary.ContainsKey(bikeInfo.Id))
{
// Duplicates are not allowed.
Log.Error($"Duplicate bike with id {bikeInfo.Id} detected evaluating bikes available. Bike status is {bikeInfo.State.Value}.");
if (!duplicates.ContainsKey(bikeInfo.Id))
{
duplicates.Add(bikeInfo.Id, bikeInfo);
}
continue;
}
bikesDictionary.Add(bikeInfo.Id, bikeInfo);
}
}
// Get bikes from Copri/ file/ memory, ....
if (bikesOccupied != null)
{
foreach (var bikeInfoResponse in bikesOccupied)
{
BikeInfo bikeInfo = BikeInfoFactory.Create(
bikeInfoResponse,
mail,
dateTimeProvider);
if (bikeInfo == null)
{
continue;
}
if (bikesDictionary.ContainsKey(bikeInfo.Id))
{
// Duplicates are not allowed.
Log.Error($"Duplicate bike with id {bikeInfo.Id} detected evaluating bikes occupied. Bike status is {bikeInfo.State.Value}.");
if (!duplicates.ContainsKey(bikeInfo.Id))
{
duplicates.Add(bikeInfo.Id, bikeInfo);
}
continue;
}
bikesDictionary.Add(bikeInfo.Id, bikeInfo);
}
}
// Remove entries which are not unique.
foreach (var l_oDuplicate in duplicates)
{
bikesDictionary.Remove(l_oDuplicate.Key);
}
return new BikeCollection(bikesDictionary);
}
}
}

View file

@ -671,6 +671,11 @@ namespace TINK.Model
{
new Version(3, 0, 356),
AppResources.ChangeLog3_0_231
},
{
new Version(3, 0, 357),
AppResources.ChangeLog_3_0_357_MK_SB,
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
},
};

View file

@ -747,6 +747,15 @@ namespace TINK.MultilingualResources {
}
}
/// <summary>
/// Looks up a localized string similar to You can only start or end a rent with network reception. Turn on mobile data or wifi and drag the page downward with the finger to refresh the page..
/// </summary>
public static string ChangeLog_3_0_357_MK_SB {
get {
return ResourceManager.GetString("ChangeLog_3_0_357_MK_SB", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to We have fixed some bugs. Enjoy the ride!.
/// </summary>
@ -765,6 +774,15 @@ namespace TINK.MultilingualResources {
}
}
/// <summary>
/// Looks up a localized string similar to Minor improvements..
/// </summary>
public static string ChangeLog_MinorImprovements {
get {
return ResourceManager.GetString("ChangeLog_MinorImprovements", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Software packages were updated..
/// </summary>
@ -1840,6 +1858,15 @@ namespace TINK.MultilingualResources {
}
}
/// <summary>
/// Looks up a localized string similar to There are currently no bicycles available at this station..
/// </summary>
public static string MarkingBikesAtStationNoBikesAvailable {
get {
return ResourceManager.GetString("MarkingBikesAtStationNoBikesAvailable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Station id: {0}.
/// </summary>
@ -1930,6 +1957,15 @@ namespace TINK.MultilingualResources {
}
}
/// <summary>
/// Looks up a localized string similar to No network, data is outdated..
/// </summary>
public static string MarkingDataIsFromCache {
get {
return ResourceManager.GetString("MarkingDataIsFromCache", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Charging level: {0}/{1} bars.
/// </summary>
@ -2147,6 +2183,15 @@ namespace TINK.MultilingualResources {
}
}
/// <summary>
/// Looks up a localized string similar to There are currently no bicycles reserved/booked on user {0}..
/// </summary>
public static string MarkingMyBikesNoBikesReservedRented {
get {
return ResourceManager.GetString("MarkingMyBikesNoBikesReservedRented", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Bike is ok.
/// </summary>
@ -2821,6 +2866,15 @@ namespace TINK.MultilingualResources {
}
}
/// <summary>
/// Looks up a localized string similar to Information.
/// </summary>
public static string MessageTitleInformation {
get {
return ResourceManager.GetString("MessageTitleInformation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warning.
/// </summary>

View file

@ -1114,4 +1114,22 @@ Probieren Sie es aus!</value>
<data name="ChangeLog_3_0_355_MK_SB_iOS" xml:space="preserve">
<value>Bluetooth-Kommunikation verbessert.</value>
</data>
<data name="MarkingDataIsFromCache" xml:space="preserve">
<value>Kein Netz, Daten sind veraltet.</value>
</data>
<data name="MarkingBikesAtStationNoBikesAvailable" xml:space="preserve">
<value>Momentan sind keine Fahrräder an dieser Station verfügbar.</value>
</data>
<data name="MarkingMyBikesNoBikesReservedRented" xml:space="preserve">
<value>Momentan sind keine Fahrräder auf Benutzer {0} reserviert/ gebucht.</value>
</data>
<data name="MessageTitleInformation" xml:space="preserve">
<value>Information</value>
</data>
<data name="ChangeLog_3_0_357_MK_SB" xml:space="preserve">
<value>Sie können eine Miete nur bei Netzempfang beginnen oder beenden. Schalten Sie mobile Daten oder WLAN ein und ziehen Sie die Seite mit dem Finger nach unten, um Ihre Ansicht zu aktualisieren.</value>
</data>
<data name="ChangeLog_MinorImprovements" xml:space="preserve">
<value>Kleine Verbesserungen.</value>
</data>
</root>

View file

@ -1204,4 +1204,22 @@ Try it out!</value>
<data name="ChangeLog_3_0_355_MK_SB_iOS" xml:space="preserve">
<value>Bluetooth communication improved.</value>
</data>
<data name="MarkingDataIsFromCache" xml:space="preserve">
<value>No network, data is outdated.</value>
</data>
<data name="MarkingBikesAtStationNoBikesAvailable" xml:space="preserve">
<value>There are currently no bicycles available at this station.</value>
</data>
<data name="MarkingMyBikesNoBikesReservedRented" xml:space="preserve">
<value>There are currently no bicycles reserved/booked on user {0}.</value>
</data>
<data name="MessageTitleInformation" xml:space="preserve">
<value>Information</value>
</data>
<data name="ChangeLog_3_0_357_MK_SB" xml:space="preserve">
<value>You can only start or end a rent with network reception. Turn on mobile data or wifi and drag the page downward with the finger to refresh the page.</value>
</data>
<data name="ChangeLog_MinorImprovements" xml:space="preserve">
<value>Minor improvements.</value>
</data>
</root>

View file

@ -1524,6 +1524,30 @@ Probieren Sie es aus!</target>
<source>Bluetooth communication improved.</source>
<target state="translated">Bluetooth-Kommunikation verbessert.</target>
</trans-unit>
<trans-unit id="MarkingDataIsFromCache" translate="yes" xml:space="preserve">
<source>No network, data is outdated.</source>
<target state="translated">Kein Netz, Daten sind veraltet.</target>
</trans-unit>
<trans-unit id="MarkingBikesAtStationNoBikesAvailable" translate="yes" xml:space="preserve">
<source>There are currently no bicycles available at this station.</source>
<target state="translated">Momentan sind keine Fahrräder an dieser Station verfügbar.</target>
</trans-unit>
<trans-unit id="MarkingMyBikesNoBikesReservedRented" translate="yes" xml:space="preserve">
<source>There are currently no bicycles reserved/booked on user {0}.</source>
<target state="translated">Momentan sind keine Fahrräder auf Benutzer {0} reserviert/ gebucht.</target>
</trans-unit>
<trans-unit id="MessageTitleInformation" translate="yes" xml:space="preserve">
<source>Information</source>
<target state="translated">Information</target>
</trans-unit>
<trans-unit id="ChangeLog_3_0_357_MK_SB" translate="yes" xml:space="preserve">
<source>You can only start or end a rent with network reception. Turn on mobile data or wifi and drag the page downward with the finger to refresh the page.</source>
<target state="translated">Sie können eine Miete nur bei Netzempfang beginnen oder beenden. Schalten Sie mobile Daten oder WLAN ein und ziehen Sie die Seite mit dem Finger nach unten, um Ihre Ansicht zu aktualisieren.</target>
</trans-unit>
<trans-unit id="ChangeLog_MinorImprovements" translate="yes" xml:space="preserve">
<source>Minor improvements.</source>
<target state="translated">Kleine Verbesserungen.</target>
</trans-unit>
</group>
</body>
</file>

View file

@ -12,7 +12,7 @@ namespace TINK.Repository.Request
public class RequestBuilder : IRequestBuilder
{
/// <summary> Constructs a object for building requests. </summary>
/// <param name="merchantId"></param>
/// <param name="merchantId">Holds the id denoting the merchant.</param>
/// <param name="uiIsoLangugageName">Two letter ISO language name.</param>
public RequestBuilder(
string merchantId,
@ -22,12 +22,12 @@ namespace TINK.Repository.Request
? merchantId
: throw new ArgumentException("Merchant id must not be null.", nameof(merchantId));
UiIsoLanguageNameParameter = RequestBuilderHelper.GetLanguageParameter(uiIsoLangugageName);
UiIsoLanguageNameParameter = RequestBuilderHelper.GetLanguageParameter(WebUtility.UrlEncode(uiIsoLangugageName));
AuthCookieParameter = $"&authcookie={MerchantId}";
AuthCookieParameter = $"&authcookie={WebUtility.UrlEncode(MerchantId)}";
}
/// <summary> Parameter specifying current ui language. </summary>
/// <summary>Holds the id denoting the merchant.</summary>
public string MerchantId { get; }
/// <summary> Holds the session cookie if a user is logged in. </summary>
@ -52,7 +52,7 @@ namespace TINK.Repository.Request
$"&merchant_id={MerchantId}" +
$"&user_id={WebUtility.UrlEncode(mailAddress)}" +
$"&user_pw={WebUtility.UrlEncode(password)}" +
$"&hw_id={deviceId}" +
$"&hw_id={WebUtility.UrlEncode(deviceId)}" +
UiIsoLanguageNameParameter;
/// <summary> Logs user out. </summary>

View file

@ -15,7 +15,7 @@ namespace TINK.Repository.Request
public class RequestBuilderLoggedIn : IRequestBuilder
{
/// <summary> Constructs a object for building requests. </summary>
/// <param name="merchantId"></param>
/// <param name="merchantId">Holds the id denoting the merchant.</param>
/// <param name="uiIsoLangugageName">Two letter ISO language name.</param>
public RequestBuilderLoggedIn(
string merchantId,
@ -30,12 +30,12 @@ namespace TINK.Repository.Request
? sessionCookie
: throw new ArgumentException("Session cookie must not be null.", nameof(sessionCookie));
UiIsoLanguageNameParameter = RequestBuilderHelper.GetLanguageParameter(uiIsoLangugageName);
UiIsoLanguageNameParameter = RequestBuilderHelper.GetLanguageParameter(WebUtility.UrlEncode(uiIsoLangugageName));
AuthCookieParameter = $"&authcookie={SessionCookie}{MerchantId}";
AuthCookieParameter = $"&authcookie={WebUtility.UrlEncode(SessionCookie)}{WebUtility.UrlEncode(MerchantId)}";
}
/// <summary> Holds the id denoting the merchant (TINK app). </summary>
/// <summary> Holds the id denoting the merchant. </summary>
public string MerchantId { get; }
/// <summary> Holds the session cookie if a user is logged in. </summary>
@ -268,25 +268,42 @@ namespace TINK.Repository.Request
UiIsoLanguageNameParameter;
}
/// <summary>
/// Gets bike id parameter.
/// </summary>
/// <param name="bikeId">Id of bike.</param>
/// <returns>bike id parameter in a format which is urlencode invariant.</returns>
private static string GetBikeIdParameter(string bikeId)
=> $"&bike={bikeId}";
=> $"&bike={WebUtility.UrlEncode(bikeId)}";
/// <summary>
/// Gets parameter holding lock state or null if state is unknown.
/// </summary>
/// <param name="lockState">Null or state of lock.</param>
/// <returns>Lock state in a format which is urlencode invariant.</returns>
private static string GetLockStateParameter(lock_state? lockState)
=> lockState.HasValue ? $"&lock_state={lockState}" : string.Empty;
/// <summary>
/// Gets the battery level percentage parameter if percentage is not NaN an empty string otherwise.
/// </summary>
/// <returns>Gets battery percentage parameters in a format which is urlencode invariant or an empty string if percentage percentge is NaN.</returns>
private static string GetBatteryPercentageParameters(double batteryPercentage) => !double.IsNaN(batteryPercentage)
? $"&voltage={batteryPercentage.ToString(CultureInfo.InvariantCulture)}"
: string.Empty;
/// <summary>
/// Gets the version info parameter or an empty string if version info is not available.
/// </summary>
/// <param name="versionInfo">Lock version info.</param>
/// <returns>Version info in a format which is urlencode invariant or empty. </returns>
private static string GetVersionInfoParameter(IVersionInfo versionInfo) => versionInfo?.FirmwareVersion > 0 || versionInfo?.HardwareVersion > 0 || versionInfo?.LockVersion > 0
? $"&firmware=HW%20{versionInfo.HardwareVersion}%3BFW%20{versionInfo.FirmwareVersion}%3BLock%20{versionInfo.LockVersion}"
: string.Empty;
/// <summary> Gets the geolocation parameter. </summary>
/// <param name="geolocation">Geolocation or null.</param>
/// <returns>Empty string if geoloction is null otherwise parmeter including latitude, longitude and age in a format which is urlencode invariant.</returns>
private static string GetLocationParameters(LocationDto geolocation)
{
if (geolocation == null)
@ -299,14 +316,14 @@ namespace TINK.Repository.Request
}
/// <summary> Gets the geolocation parameter. </summary>
/// <param name="geolocation">Geolocation or null.</param>
/// <returns>in a format which is urlencode invariant.</returns>
private static string GetSmartDeviceParameters(ISmartDevice smartDevice)
=> smartDevice != null
? $"{(!string.IsNullOrEmpty(smartDevice.Manufacturer) ? $"&user_device_manufaturer={smartDevice.Manufacturer})" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.Model) ? $"&user_device_model={smartDevice.Model}" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.Platform.ToString()) ? $"&user_device_platform={smartDevice.Platform.ToString()}" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.VersionText) ? $"&user_device_version={smartDevice.VersionText}" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.Identifier) ? $"&user_device_id={smartDevice.Identifier}" : string.Empty)}"
? $"{(!string.IsNullOrEmpty(smartDevice.Manufacturer) ? $"&user_device_manufaturer={WebUtility.UrlEncode(smartDevice.Manufacturer)})" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.Model) ? $"&user_device_model={WebUtility.UrlEncode(smartDevice.Model)}" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.Platform.ToString()) ? $"&user_device_platform={WebUtility.UrlEncode(smartDevice.Platform.ToString())}" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.VersionText) ? $"&user_device_version={WebUtility.UrlEncode(smartDevice.VersionText)}" : string.Empty)}" +
$"{(!string.IsNullOrEmpty(smartDevice.Identifier) ? $"&user_device_id={WebUtility.UrlEncode(smartDevice.Identifier)}" : string.Empty)}"
: string.Empty;
/// <summary>

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel;
using TINK.Model.Connector;
using TINK.Model.Device;
@ -65,6 +65,8 @@ namespace TINK.ViewModel.Bikes.Bike.BC
viewService,
bikesViewModel,
ActiveUser);
selectedBike.PropertyChanged += (sender, ev) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsButtonVisible)));
}
/// <summary>
@ -94,7 +96,9 @@ namespace TINK.ViewModel.Bikes.Bike.BC
}
/// <summary> Gets visiblity of the copri command button. </summary>
public bool IsButtonVisible => RequestHandler.IsButtonVisible;
public bool IsButtonVisible
=> RequestHandler.IsButtonVisible
&& Bike.DataSource == Model.Bikes.BikeInfoNS.BC.DataSource.Copri /* do not show button if data is from cache */ ;
/// <summary> Gets the text of the copri command button. </summary>
public string ButtonText => RequestHandler.ButtonText;

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@ -39,6 +39,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
string lastStateText = null,
Xamarin.Forms.Color? lastStateColor = null)
{
if (IsDataFromCache != IsDataFromCache)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsDataFromCache)));
}
if (lastHandler.ButtonText != ButtonText)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonText)));
@ -121,6 +127,15 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
LockService = lockService
?? throw new ArgumentException($"Can not instantiate {this.GetType().Name}-object. Parameter {nameof(lockService)} can not be null.");
selectedBike.PropertyChanged += (sender, ev) =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsButtonVisible)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLockitButtonVisible)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsDataFromCache)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OnButtonClicked)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OnLockitButtonClicked)));
};
}
/// <summary>
@ -147,22 +162,28 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
}
/// <summary> Gets visiblity of the copri command button. </summary>
public bool IsButtonVisible => RequestHandler.IsButtonVisible;
public bool IsButtonVisible
=> RequestHandler.IsButtonVisible;
/// <summary> Gets the text of the copri command button. </summary>
public string ButtonText => RequestHandler.ButtonText;
/// <summary> Gets visiblity of the ILockIt command button. </summary>
public bool IsLockitButtonVisible => RequestHandler.IsLockitButtonVisible;
public bool IsLockitButtonVisible
=> RequestHandler.IsLockitButtonVisible;
/// <summary> Gets the text of the ILockIt command button. </summary>
public string LockitButtonText => RequestHandler.LockitButtonText;
/// <summary> True if Data is from Cache. </summary>
public bool IsDataFromCache
=> Bike.DataSource == Model.Bikes.BikeInfoNS.BC.DataSource.Cache;
/// <summary> Processes request to perform a copri action (reserve bike and cancel reservation). </summary>
public System.Windows.Input.ICommand OnButtonClicked => new Xamarin.Forms.Command(async () => await ClickButton(RequestHandler.HandleRequestOption1()));
public System.Windows.Input.ICommand OnButtonClicked => new Xamarin.Forms.Command(async () => await ClickButton(RequestHandler.HandleRequestOption1()), () => !IsDataFromCache);
/// <summary> Processes request to perform a ILockIt action (unlock bike and lock bike). </summary>
public System.Windows.Input.ICommand OnLockitButtonClicked => new Xamarin.Forms.Command(async () => await ClickButton(RequestHandler.HandleRequestOption2()));
public System.Windows.Input.ICommand OnLockitButtonClicked => new Xamarin.Forms.Command(async () => await ClickButton(RequestHandler.HandleRequestOption2()), () => !IsDataFromCache);
/// <summary> Processes request to perform a copri action (reserve bike and cancel reservation). </summary>
private async Task ClickButton(Task<IRequestHandler> handleRequest)

View file

@ -584,6 +584,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
AppResources.MessageAnswerOk);
}
// Update current state from exception
SelectedBike.LockInfo.State = exception is StateAwareException stateAwareException
? stateAwareException.State
: LockingState.UnknownDisconnected;

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@ -107,6 +107,12 @@ namespace TINK.ViewModel.Bikes.Bike.CopriLock
selectedBike.State.Value,
viewService,
bikesViewModel);
selectedBike.PropertyChanged += (sender, ev) =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsButtonVisible)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLockitButtonVisible)));
};
}
/// <summary>
@ -131,13 +137,17 @@ namespace TINK.ViewModel.Bikes.Bike.CopriLock
}
/// <summary> Gets visiblity of the copri command button. </summary>
public bool IsButtonVisible => RequestHandler.IsButtonVisible;
public bool IsButtonVisible
=> RequestHandler.IsButtonVisible
&& Bike.DataSource == Model.Bikes.BikeInfoNS.BC.DataSource.Copri /* do not show button if data is from cache */ ;
/// <summary> Gets the text of the copri command button. </summary>
public string ButtonText => RequestHandler.ButtonText;
/// <summary> Gets visiblity of the ILockIt command button. </summary>
public bool IsLockitButtonVisible => RequestHandler.IsLockitButtonVisible;
public bool IsLockitButtonVisible
=> RequestHandler.IsLockitButtonVisible
&& Bike.DataSource == Model.Bikes.BikeInfoNS.BC.DataSource.Copri /* do not show button if data is from cache */ ;
/// <summary> Gets the text of the ILockIt command button. </summary>
public string LockitButtonText => RequestHandler.LockitButtonText;

View file

@ -327,11 +327,11 @@ namespace TINK.ViewModel.Bikes
Log.ForContext<BikesViewModel>().Debug($"Switch value of {nameof(IsIdle)} to {value}.");
isIdle = value;
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsIdle)));
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsRunning)));
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsProcessWithRunningProcessView)));
}
}
public bool IsRunning => !isIdle;
public bool IsProcessWithRunningProcessView => !isIdle;
/// <summary> Holds info about current action. </summary>
private string actionText;
@ -479,5 +479,6 @@ namespace TINK.ViewModel.Bikes
/// </summary>
public virtual async Task OnDisappearing()
=> await m_oViewUpdateManager.StopUpdatePeridically();
}
}

View file

@ -23,6 +23,7 @@ using TINK.Settings;
using TINK.View;
using TINK.ViewModel.Bikes;
using Xamarin.Forms;
using Command = Xamarin.Forms.Command;
namespace TINK.ViewModel.BikesAtStation
{
@ -36,6 +37,22 @@ namespace TINK.ViewModel.BikesAtStation
/// </summary>
private IStation Station { get; }
/// <summary>
/// True if ListView of Bikes is refreshing after user pulled;
/// </summary>
private bool _isRefreshing = false;
public bool IsRefreshing
{
get { return _isRefreshing; }
set
{
_isRefreshing = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsRefreshing)));
}
}
public Command RefreshCommand { get; }
/// <summary>
/// Constructs bike collection view model.
/// </summary>
@ -75,11 +92,23 @@ namespace TINK.ViewModel.BikesAtStation
? string.Format(AppResources.MarkingBikesAtStationStationId, Station.Id)
: string.Empty;
/// <summary>
/// Holds what should be executed on pull to refresh
/// </summary>
RefreshCommand = new Command(async () => {
IsRefreshing = true;
await OnAppearing();
IsRefreshing = false;
});
CollectionChanged += (sender, eventargs) =>
{
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsNoBikesAtStationVisible)));
OnPropertyChanged(new PropertyChangedEventArgs(nameof(NoBikesAtStationText)));
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsLoginRequiredHintVisible)));
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsRefreshing)));
};
}
@ -131,7 +160,7 @@ namespace TINK.ViewModel.BikesAtStation
get
{
return IsNoBikesAtStationVisible
? $"Momentan sind keine Fahrräder an dieser Station verfügbar."
? AppResources.MarkingBikesAtStationNoBikesAvailable
: string.Empty;
}
}
@ -215,6 +244,8 @@ namespace TINK.ViewModel.BikesAtStation
/// </summary>
public async Task OnAppearing()
{
IsIdle = false;
Log.ForContext<BikesAtStationPageViewModel>().Information($"Bikes at station {Station.StationName} is appearing, either due to tap on a station or to app being shown again.");
ActionText = AppResources.ActivityTextOneMomentPlease;
@ -334,7 +365,7 @@ namespace TINK.ViewModel.BikesAtStation
}
/// <summary> Create task which updates my bike view model.</summary>
private void UpdateTask()
public void UpdateTask()
{
PostAction(
unused =>

View file

@ -271,7 +271,7 @@ namespace TINK.ViewModel.Contact
{
try
{
IsRunning = true;
IsProcessWithRunningProcessView = true;
// Process map page.
Log.ForContext<SelectStationPageViewModel>().Information(
@ -300,7 +300,7 @@ namespace TINK.ViewModel.Contact
// User decided to give access to locations permissions.
PermissionsService.OpenAppSettings();
ActionText = "";
IsRunning = false;
IsProcessWithRunningProcessView = false;
IsMapPageEnabled = true;
return;
}
@ -406,14 +406,14 @@ namespace TINK.ViewModel.Contact
Exception = resultStationsAndBikes.Exception;
ActionText = "";
IsRunning = false;
IsProcessWithRunningProcessView = false;
IsMapPageEnabled = true;
}
catch (Exception l_oException)
{
Log.ForContext<SelectStationPageViewModel>().Error($"An error occurred opening select station page.\r\n{l_oException.Message}");
IsRunning = false;
IsProcessWithRunningProcessView = false;
await ViewService.DisplayAlert(
"Fehler",
@ -582,22 +582,22 @@ namespace TINK.ViewModel.Contact
}
/// <summary> Used to block more than on copri requests at a given time.</summary>
private bool isRunning = false;
private bool isProcessWithRunningProcessView = false;
/// <summary>
/// True if any action can be performed (request and cancel request)
/// </summary>
public bool IsRunning
public bool IsProcessWithRunningProcessView
{
get => isRunning;
get => isProcessWithRunningProcessView;
set
{
if (value == isRunning)
if (value == isProcessWithRunningProcessView)
return;
Log.ForContext<SelectStationPageViewModel>().Debug($"Switch value of {nameof(isRunning)} to {value}.");
isRunning = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRunning)));
Log.ForContext<SelectStationPageViewModel>().Debug($"Switch value of {nameof(isProcessWithRunningProcessView)} to {value}.");
isProcessWithRunningProcessView = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsProcessWithRunningProcessView)));
}
}

View file

@ -26,6 +26,7 @@ using TINK.Settings;
using TINK.View;
using TINK.ViewModel.Bikes;
using Xamarin.Forms;
using Command = Xamarin.Forms.Command;
namespace TINK.ViewModel.FindBike
{
@ -79,6 +80,22 @@ namespace TINK.ViewModel.FindBike
/// <summary> Holds the stations to get station names form station ids. </summary>
private IEnumerable<IStation> Stations { get; }
/// <summary>
/// True if ListView of Bikes is refreshing after user pulled;
/// </summary>
private bool _isRefreshing = false;
public bool IsRefreshing
{
get { return _isRefreshing; }
set
{
_isRefreshing = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsRefreshing)));
}
}
public Command RefreshCommand { get; }
/// <summary>
/// Constructs bike collection view model in case information about occupied bikes is available.
/// </summary>
@ -118,6 +135,17 @@ namespace TINK.ViewModel.FindBike
};
Stations = stations ?? throw new ArgumentException(nameof(stations));
/// <summary>
/// Holds what should be executed on pull to refresh
/// </summary>
RefreshCommand = new Command(async () => {
IsRefreshing = true;
await OnAppearing();
IsRefreshing = false;
});
}
/// <summary>

View file

@ -313,7 +313,7 @@ namespace TINK.ViewModel.Map
var status = await PermissionsService.RequestAsync();
}
IsRunning = true;
IsProcessWithRunningProcessView = true;
IsNavBarVisible = false;
// Process map page.
Polling = TinkApp.Polling;
@ -332,11 +332,13 @@ namespace TINK.ViewModel.Map
TinkApp.Stations = resultStationsAndBikes.Response.StationsAll;
TinkApp.ResourceUrls = resultStationsAndBikes.GeneralData.ResourceUrls;
// Check if there is a message from COPRI ("merchant_message") to be shown to user.
if (!string.IsNullOrEmpty(resultStationsAndBikes?.GeneralData?.MerchantMessage)
&& !WasMerchantMessageAlreadyShown)
{
// Show COPRI message once.
await ViewService.DisplayAlert(
"Information",
AppResources.MessageTitleInformation,
resultStationsAndBikes.GeneralData.MerchantMessage,
AppResources.MessageAnswerOk);
WasMerchantMessageAlreadyShown = true;
@ -404,7 +406,7 @@ namespace TINK.ViewModel.Map
Exception = resultStationsAndBikes.Exception;
ActionText = "";
IsRunning = false;
IsProcessWithRunningProcessView = false;
IsNavBarVisible = true;
IsMapPageEnabled = true;
}
@ -412,7 +414,7 @@ namespace TINK.ViewModel.Map
{
Log.ForContext<MapPageViewModel>().Error($"An error occurred showing bike stations page.\r\n{l_oException.Message}");
IsRunning = false;
IsProcessWithRunningProcessView = false;
IsNavBarVisible = true;
await ViewService.DisplayAlert(
@ -541,7 +543,7 @@ namespace TINK.ViewModel.Map
// User decided to give access to locations permissions.
PermissionsService.OpenAppSettings();
ActionText = "";
IsRunning = false;
IsProcessWithRunningProcessView = false;
IsNavBarVisible = true;
IsMapPageEnabled = true;
}
@ -782,22 +784,22 @@ namespace TINK.ViewModel.Map
}
/// <summary> Used to block more than on copri requests at a given time.</summary>
private bool isRunning = false;
private bool isProcessWithRunningProcessView = false;
/// <summary>
/// True if any action can be performed (request and cancel request)
/// </summary>
public bool IsRunning
public bool IsProcessWithRunningProcessView
{
get => isRunning;
get => isProcessWithRunningProcessView;
set
{
if (value == isRunning)
if (value == isProcessWithRunningProcessView)
return;
Log.ForContext<MapPageViewModel>().Debug($"Switch value of {nameof(isRunning)} to {value}.");
isRunning = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRunning)));
Log.ForContext<MapPageViewModel>().Debug($"Switch value of {nameof(isProcessWithRunningProcessView)} to {value}.");
isProcessWithRunningProcessView = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsProcessWithRunningProcessView)));
}
}
@ -900,7 +902,7 @@ namespace TINK.ViewModel.Map
try
{
IsMapPageEnabled = false;
IsRunning = true;
IsProcessWithRunningProcessView = true;
IsNavBarVisible = false;
Log.ForContext<MapPageViewModel>().Information($"Request to toggle to \"{selectedFilter}\".");
@ -954,7 +956,7 @@ namespace TINK.ViewModel.Map
}
ActionText = "";
IsRunning = false;
IsProcessWithRunningProcessView = false;
IsNavBarVisible = true;
IsMapPageEnabled = true;
Log.ForContext<MapPageViewModel>().Information($"Toggle to \"{selectedFilter}\" done.");
@ -963,7 +965,7 @@ namespace TINK.ViewModel.Map
{
Log.ForContext<MapPageViewModel>().Error("An error occurred switching view Cargobike/ Citybike.{}");
ActionText = "";
IsRunning = false;
IsProcessWithRunningProcessView = false;
IsNavBarVisible = true;
await ViewService.DisplayAlert(

View file

@ -23,6 +23,7 @@ using TINK.Settings;
using TINK.View;
using TINK.ViewModel.Bikes;
using Xamarin.Forms;
using Command = Xamarin.Forms.Command;
namespace TINK.ViewModel.MyBikes
{
@ -31,6 +32,20 @@ namespace TINK.ViewModel.MyBikes
/// <summary> Holds the stations to get station names form station ids. </summary>
private IEnumerable<IStation> Stations { get; }
/// <summary>
/// True if ListView of Bikes is refreshing after user pulled;
/// </summary>
private bool _isRefreshing = false;
public bool IsRefreshing
{
get { return _isRefreshing; }
set
{
_isRefreshing = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsRefreshing)));
}
}
/// <summary>
/// Constructs bike collection view model in case information about occupied bikes is available.
/// </summary>
@ -71,8 +86,21 @@ namespace TINK.ViewModel.MyBikes
};
Stations = stations ?? throw new ArgumentException(nameof(stations));
/// <summary>
/// Holds what should be executed on pull to refresh
/// </summary>
RefreshCommand = new Command(async () => {
IsRefreshing = true;
await OnAppearing();
IsRefreshing = false;
});
}
public Command RefreshCommand { get; }
/// <summary> Returns if info about the fact that user did not request or book any bikes is visible or not.<summary>
/// Gets message that logged in user has not booked any bikes.
/// </summary>
@ -90,7 +118,7 @@ namespace TINK.ViewModel.MyBikes
get
{
return IsNoBikesOccupiedVisible
? $"Momentan sind keine Fahrräder auf Benutzer {ActiveUser?.Mail} reserviert/ gebucht."
? string.Format(AppResources.MarkingMyBikesNoBikesReservedRented, ActiveUser?.Mail)
: string.Empty;
}
}
@ -101,6 +129,8 @@ namespace TINK.ViewModel.MyBikes
/// </summary>
public async Task OnAppearing()
{
IsIdle = false;
// Get my bikes from COPRI
Log.ForContext<MyBikesPageViewModel>().Information("User request to show page MyBikes/ page re-appearing");

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS;
@ -29,6 +29,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BC
stateInfo,
bike,
drive,
DataSource.Copri,
isDemo,
group,
stationId,

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS;
@ -28,6 +28,7 @@ namespace TestTINKLib
IStateInfo stateInfo = null) : base(
new Bike(id, lockType, wheelType, typeOfBike, description),
new TINK.Model.Bikes.BikeInfoNS.DriveNS.Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
isDemo,
group,
stationId,

View file

@ -1,4 +1,5 @@
using System;
using System;
using NSubstitute.ExceptionExtensions;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
@ -18,16 +19,16 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
"Verify that no unspecific reference not set to... exception is thrown");
Assert.Throws<ArgumentException>(
() => new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), "1"), null),
() => new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, "1"), null),
"Verify that no unspecific reference not set to... exception is thrown");
}
[Test]
public void TestCtorAvailable()
{
Assert.AreEqual("12", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "13").Id);
Assert.AreEqual("13", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "13").StationId);
Assert.AreEqual(InUseStateEnum.Disposable, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "13").State.Value);
Assert.AreEqual("12", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "13").Id);
Assert.AreEqual("13", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "13").StationId);
Assert.AreEqual(InUseStateEnum.Disposable, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "13").State.Value);
}
[Test]
@ -37,6 +38,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
() => new BikeInfo(
null,
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
5200544,
new Guid("00000000-0000-0000-0000-000000000001"),
"13"),
@ -46,9 +48,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
[Test]
public void TestCtorRequested()
{
Assert.AreEqual("12", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null, null, dateTimeProvider: () => new DateTime(2019, 1, 1), false /*isDemo*/, null /*group*/).Id);
Assert.AreEqual(112, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null, null, dateTimeProvider: () => new DateTime(2019, 1, 1), false /*isDemo*/, null /*group*/).LockInfo.Id);
Assert.AreEqual(InUseStateEnum.Reserved, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null, null, dateTimeProvider: () => new DateTime(2019, 1, 1), false /*isDemo*/, null /*group*/).State.Value);
Assert.AreEqual("12", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null, null, dateTimeProvider: () => new DateTime(2019, 1, 1), false /*isDemo*/, null /*group*/).Id);
Assert.AreEqual(112, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null, null, dateTimeProvider: () => new DateTime(2019, 1, 1), false /*isDemo*/, null /*group*/).LockInfo.Id);
Assert.AreEqual(InUseStateEnum.Reserved, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null, null, dateTimeProvider: () => new DateTime(2019, 1, 1), false /*isDemo*/, null /*group*/).State.Value);
}
[Test]
@ -57,7 +59,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
Assert.That(
() => new BikeInfo(
null,
new Drive(), 112,
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
112,
new Guid(),
null,
null,
@ -76,9 +80,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
[Test]
public void TestCtorBooked()
{
Assert.AreEqual("12", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null /*operator uri*/).Id);
Assert.AreEqual(112, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null /*operator uri*/).LockInfo.Id);
Assert.AreEqual(InUseStateEnum.Booked, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null /*operator uri*/).State.Value);
Assert.AreEqual("12", new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null /*operator uri*/).Id);
Assert.AreEqual(112, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null /*operator uri*/).LockInfo.Id);
Assert.AreEqual(InUseStateEnum.Booked, new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("12", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", "13", null /*operator uri*/).State.Value);
}
[Test]
@ -88,6 +92,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
() => new BikeInfo(
null,
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
112,
new Guid(),
null,

View file

@ -1,4 +1,4 @@
using System;
using System;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
@ -12,7 +12,7 @@ namespace TestShareeLib.Model.Bike.BluetoothLock
public void TestCtor()
{
Assert.That(
new BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("MyBikeId", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), 42, new Guid(), "17"), "My Station Name").StationName,
new BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("MyBikeId", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 42, new Guid(), "17"), "My Station Name").StationName,
Is.EqualTo("My Station Name"));
}

View file

@ -1,6 +1,7 @@
using System;
using System;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
@ -15,6 +16,7 @@ namespace TestShareeLib.Model.Bike.CopriLock
var bike = new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("bikeId", LockModel.Sigo),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
"stationId",
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo());
@ -31,6 +33,7 @@ namespace TestShareeLib.Model.Bike.CopriLock
() => new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
null,
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
"stationId",
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo()),
Throws.ArgumentNullException);
@ -42,6 +45,7 @@ namespace TestShareeLib.Model.Bike.CopriLock
var bike = new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("bikeId", LockModel.Sigo),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
"stationId",
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo(),
true);
@ -58,6 +62,7 @@ namespace TestShareeLib.Model.Bike.CopriLock
() => new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
null,
new Drive(),
DataSource.Copri,
DateTime.Now,
"a@b",
"stationId",
@ -75,6 +80,7 @@ namespace TestShareeLib.Model.Bike.CopriLock
() => new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
null,
new Drive(),
DataSource.Copri,
DateTime.Now,
"a@b",
"stationId",

View file

@ -1,4 +1,4 @@
using NUnit.Framework;
using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
@ -25,6 +25,7 @@ namespace TestShareeLib.Model.Bike.CopriLock
var bikeInfo = new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
bike,
new Drive(new TINK.Model.Bikes.BikeInfoNS.DriveNS.EngineNS.Engine("BackendLock")),
DataSource.Copri,
"StationId",
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo());

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using NUnit.Framework;
@ -34,7 +34,8 @@ namespace TestTINKLib
Func<DateTime> dateTimeProvider = null,
IStateInfo stateInfo = null) : base(
new Bike(id, lockType, wheelType, typeOfBike, description),
new TINK.Model.Bikes.BikeInfoNS.DriveNS.Drive(),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
isDemo,
group,
stationId,
@ -110,6 +111,7 @@ namespace TestTINKLib
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike("57", LockModel.ILockIt),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
DateTime.Now,
"john@long",
"7" /*station id*/,
@ -118,13 +120,16 @@ namespace TestTINKLib
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike("20", LockModel.ILockIt),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
DateTime.Now,
"john@long",
"7",
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo(),
null),
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike("33", LockModel.Sigo), new Drive(),
new Bike("33", LockModel.Sigo),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
"7",
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo()),
};
@ -153,7 +158,9 @@ namespace TestTINKLib
var l_oBikeResponse = new List<BikeInfo>
{
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike("57", LockModel.Sigo), new Drive(),
new Bike("57", LockModel.Sigo),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
"7" /*station id*/,
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo()),
};
@ -185,7 +192,7 @@ namespace TestTINKLib
var bikeResponse = new List<BikeInfo>
{
new BikeInfo(new Bike("57" /* bike id*/, LockModel.ILockIt, WheelType.Trike, TypeOfBike.Allround, "Test description"), new Drive(), false, new List<string> {"TINK" }, "7" /*station id*/, null /*operator uri*/, null, DateTime.Now, "john@long,", "1234"),
new BikeInfo(new Bike("57" /* bike id*/, LockModel.ILockIt, WheelType.Trike, TypeOfBike.Allround, "Test description"), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, false, new List<string> {"TINK" }, "7" /*station id*/, null /*operator uri*/, null, DateTime.Now, "john@long,", "1234"),
};
var stations = new List<IStation>
@ -210,7 +217,9 @@ namespace TestTINKLib
var bikeResponse = new List<BikeInfo>
{
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike("57", LockModel.Sigo), new Drive(),
new Bike("57", LockModel.Sigo),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
"7" /*station id*/,
new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo(),
operatorUri: null /*operator uri*/),
@ -234,7 +243,8 @@ namespace TestTINKLib
""gps"" : { ""latitude"": ""47.669888"", ""longitude"": ""9.167749"" },
""station"" : ""9"",
""system"" : ""Ilockit""
}"));
}"),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri);
Assert.That(
BikeCollectionMutable.BikeInfoMutableFactory.Create(bikeInfo, "Stat1").GetType(),
@ -252,7 +262,8 @@ namespace TestTINKLib
""gps"" : { ""latitude"": ""47.669888"", ""longitude"": ""9.167749"" },
""station"" : ""9"",
""system"" : ""SIGO""
}"));
}"),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri);
Assert.That(
BikeCollectionMutable.BikeInfoMutableFactory.Create(bikeInfo, "Stat1").GetType(),
@ -271,7 +282,8 @@ namespace TestTINKLib
""gps"" : { ""latitude"": ""47.669888"", ""longitude"": ""9.167749"" },
""station"" : ""9"",
""system"" : ""LOCK""
}"));
}"),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri);
Assert.That(
BikeCollectionMutable.BikeInfoMutableFactory.Create(bikeInfo, "Stat1"),

View file

@ -1,4 +1,4 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
using NUnit.Framework;
using TINK.Model.Connector.Updater;
using TINK.Repository.Response;
@ -22,7 +22,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse),
BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri),
Is.Null,
"BC- bikes (\"system\" : \"LOCK\") are no more supported.");
}
@ -41,7 +41,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse),
BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri),
Is.Null,
"Invalid (\"state\" : \"reserved\") detected.");
}
@ -60,7 +60,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse),
BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri),
Is.Null,
"Station must not be null.");
}
@ -79,7 +79,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse).GetType(),
BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri).GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo)),
"Default lock by is BackendLock.");
}
@ -98,7 +98,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse).GetType(),
BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri).GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo)));
}
@ -116,7 +116,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse).GetType(),
BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri).GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo)));
}
@ -173,7 +173,7 @@ namespace TestShareeLib.Model.Connector
}
}");
var bike = BikeInfoFactory.Create(bikeInfoResponse) as TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo;
var bike = BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri) as TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo;
Assert.That(
bike,
@ -195,7 +195,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime()),
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri),
Is.Null,
"BC- bikes (\"system\" : \"LOCK\") are no more supported.");
}
@ -215,7 +215,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime()).GetType(),
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri).GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo)));
}
@ -234,7 +234,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime()).GetType(),
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri).GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo)));
}
@ -254,7 +254,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime()).GetType(),
BikeInfoFactory.Create(bikeInfoResponse, "a@b", () => new System.DateTime(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri).GetType(),
Is.EqualTo(typeof(TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo)));
}
@ -318,7 +318,7 @@ namespace TestShareeLib.Model.Connector
}");
Assert.That(
BikeInfoFactory.Create(bikeInfoResponse)?.State?.Value,
BikeInfoFactory.Create(bikeInfoResponse, TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri)?.State?.Value,
Is.EqualTo(TINK.Model.State.InUseStateEnum.FeedbackPending),
"Bikes with state booking state available in ");
}

View file

@ -1,8 +1,10 @@
using System;
using System;
using System.Linq;
using Newtonsoft.Json;
using NUnit.Framework;
using TINK.Model;
using TINK.Model.Bikes;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.Connector.Updater;
@ -164,8 +166,7 @@ namespace TestShareeLib.Model.Connector.Updater
public void TestUpdateBikesAvailable_BikeNr5GetBooked()
{
// Bike 5 is availalbe.
var l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 1).GetBikesAvailable(
);
var l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 1).GetBikesAvailable(DataSource.Copri);
Assert.AreEqual(12, l_oBikesTarget.Count, "Bike 5 is available an must be part of available bikes collection");
@ -180,16 +181,14 @@ namespace TestShareeLib.Model.Connector.Updater
// Bike 5 is reserved.
// Count of bikes must decrease and bike #5 no more in list of bikes.
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 2).GetBikesAvailable(
);
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 2).GetBikesAvailable(DataSource.Copri);
Assert.AreEqual(11, l_oBikesTarget.Count, "One bike (nr. 5) got reserved");
Assert.Null(l_oBikesTarget.GetById("5"), "Bike 5 got requested and must not be part of available bikes collection");
// Bike 5 is booked.
// Count of bikes must decrease and bike #5 no more in list of bikes.
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 3).GetBikesAvailable(
);
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 3).GetBikesAvailable(DataSource.Copri);
Assert.Null(l_oBikesTarget.GetById("5"), "Bike 5 got booked and must not be part of available bikes collection");
Assert.IsNull(l_oBikesTarget.GetById("5"));
@ -200,7 +199,8 @@ namespace TestShareeLib.Model.Connector.Updater
{
var l_oBikesTarget = GetBikesOccupied("4da3044c8657a04ba60e2eaa753bc51a", SampleSets.Set2, 1).GetBikesOccupied(
"a@B",
() => new DateTime(2017, 11, 28, 14, 8, 14)); // Date time now for bikes which are reserved
() => new DateTime(2017, 11, 28, 14, 8, 14), // Date time now for bikes which are reserved
DataSource.Copri);
// Check initial count of bikes.
Assert.AreEqual(
@ -210,7 +210,8 @@ namespace TestShareeLib.Model.Connector.Updater
// Bike 5 is reserved
l_oBikesTarget = GetBikesOccupied("4da3044c8657a04ba60e2eaa753bc51a", SampleSets.Set2, 2).GetBikesOccupied(
"a@B",
() => new DateTime(2017, 11, 28, 14, 08, 36).Add(new TimeSpan(0, 2, 0))); // Date time now for bikes which are reserved
() => new DateTime(2017, 11, 28, 14, 08, 36).Add(new TimeSpan(0, 2, 0)), // Date time now for bikes which are reserved
DataSource.Copri);
Assert.AreEqual(3, l_oBikesTarget.Count, "One bike (nr. 5) got reserved");
@ -225,7 +226,8 @@ namespace TestShareeLib.Model.Connector.Updater
// Bike 5 is booked
l_oBikesTarget = GetBikesOccupied("4da3044c8657a04ba60e2eaa753bc51a", SampleSets.Set2, 3).GetBikesOccupied(
"a@B",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(3, l_oBikesTarget.Count, "One bike (nr. 5) got booked");
@ -240,7 +242,7 @@ namespace TestShareeLib.Model.Connector.Updater
public void TestGetBikesAvailable_BikeNr5GetBooked()
{
// Bike 5 is availalbe.
var l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 1).GetBikesAvailable();
var l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 1).GetBikesAvailable(DataSource.Copri);
Assert.AreEqual(11, l_oBikesTarget.Count, "Bike 5 is available an must be part of available bikes collection");
@ -255,14 +257,14 @@ namespace TestShareeLib.Model.Connector.Updater
// Bike 5 is reserved.
// Count of bikes must decrease and bike #5 no more in list of bikes.
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 2).GetBikesAvailable();
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 2).GetBikesAvailable(DataSource.Copri);
Assert.AreEqual(10, l_oBikesTarget.Count, "One bike (nr. 5) got reserved");
Assert.Null(l_oBikesTarget.GetById("5"), "Bike 5 got requested and must not be part of available bikes collection");
// Bike 5 is booked.
// Count of bikes must decrease and bike #5 no more in list of bikes.
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 3).GetBikesAvailable();
l_oBikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 3).GetBikesAvailable(DataSource.Copri);
Assert.Null(l_oBikesTarget.GetById("5"), "Bike 5 got booked and must not be part of available bikes collection");
Assert.IsNull(l_oBikesTarget.GetById("5"));
@ -273,7 +275,8 @@ namespace TestShareeLib.Model.Connector.Updater
{
var bikesTarget = GetBikesOccupied("4da3044c8657a04ba60e2eaa753bc51a", SampleSets.Set2, 1).GetBikesOccupied(
"a@B",
() => new DateTime(2017, 11, 28, 14, 8, 14)); // Date time now for bikes which are reserved
() => new DateTime(2017, 11, 28, 14, 8, 14), // Date time now for bikes which are reserved
DataSource.Copri);
// Check initial count of bikes.
Assert.AreEqual(2, bikesTarget.Count);
@ -281,7 +284,8 @@ namespace TestShareeLib.Model.Connector.Updater
// Bike 5 is reserved
bikesTarget = GetBikesOccupied("4da3044c8657a04ba60e2eaa753bc51a", SampleSets.Set2, 2).GetBikesOccupied(
"a@B",
() => new DateTime(2017, 11, 28, 14, 08, 36).Add(new TimeSpan(0, 2, 0))); // Date time now for bikes which are reserved
() => new DateTime(2017, 11, 28, 14, 08, 36).Add(new TimeSpan(0, 2, 0)), // Date time now for bikes which are reserved
DataSource.Copri);
Assert.AreEqual(3, bikesTarget.Count, "One bike (nr. 5) got reserved");
@ -296,7 +300,8 @@ namespace TestShareeLib.Model.Connector.Updater
// Bike 5 is booked
bikesTarget = GetBikesOccupied("4da3044c8657a04ba60e2eaa753bc51a", SampleSets.Set2, 3).GetBikesOccupied(
"a@B",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(3, bikesTarget.Count, "One bike (nr. 5) got booked");
@ -314,7 +319,8 @@ namespace TestShareeLib.Model.Connector.Updater
{
var bikesTarget = GetBikesOccupied("5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", SampleSets.ShareeFr01_Set1, 1).GetBikesOccupied(
"a@B",
() => new DateTime(2017, 11, 28, 14, 8, 14)); // Date time now for bikes which are reserved
() => new DateTime(2017, 11, 28, 14, 8, 14), // Date time now for bikes which are reserved
DataSource.Copri);
// Check initial count of bikes.
Assert.AreEqual(2, bikesTarget.Count);
@ -322,7 +328,8 @@ namespace TestShareeLib.Model.Connector.Updater
// Bike 5 is reserved
bikesTarget = GetBikesOccupied("5781_d47fc786e740ef77d85a24bcb6f0ff97_oiF2kahH", SampleSets.ShareeFr01_Set1, 2).GetBikesOccupied(
"a@B",
() => new DateTime(2017, 11, 28, 14, 08, 36).Add(new TimeSpan(0, 2, 0))); // Date time now for bikes which are reserved
() => new DateTime(2017, 11, 28, 14, 08, 36).Add(new TimeSpan(0, 2, 0)), // Date time now for bikes which are reserved
DataSource.Copri);
Assert.AreEqual(3, bikesTarget.Count, "One bike (nr. 5) got reserved");
@ -379,8 +386,7 @@ namespace TestShareeLib.Model.Connector.Updater
[Test]
public void TestGetBikesAvailable()
{
var bikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 1).GetBikesAvailable(
);
var bikesTarget = GetBikesAvailable(TinkApp.MerchantId, sampleSet: SampleSets.Set2, stageIndex: 1).GetBikesAvailable(DataSource.Copri);
// Verify count of bikes
Assert.AreEqual(12, bikesTarget.Count);
@ -406,7 +412,8 @@ namespace TestShareeLib.Model.Connector.Updater
{
var l_oBikesTarget = GetBikesOccupied(TinkApp.MerchantId, SampleSets.Set2, 1).GetBikesOccupied(
"a@b",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
// Verify count of bikes
Assert.AreEqual(2, l_oBikesTarget.Count);
@ -436,11 +443,12 @@ namespace TestShareeLib.Model.Connector.Updater
}
}");
var bikes = UpdaterJSON.GetBikesAll(
var bikes = BikeCollectionFactory.GetBikesAll(
availableResponse?.bikes?.Values,
null,
"Heinz.Mustermann@posteo.de",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(
2,
@ -467,11 +475,12 @@ namespace TestShareeLib.Model.Connector.Updater
}
}");
var bikes = UpdaterJSON.GetBikesAll(
var bikes = BikeCollectionFactory.GetBikesAll(
availableResponse?.bikes?.Values,
null,
"Heinz.Mustermann@posteo.de",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(
0,
@ -495,11 +504,12 @@ namespace TestShareeLib.Model.Connector.Updater
}
}");
var bikes = UpdaterJSON.GetBikesAll(
var bikes = BikeCollectionFactory.GetBikesAll(
availableResponse?.bikes?.Values,
null,
"Heinz.Mustermann@posteo.de",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(
0,
@ -530,11 +540,12 @@ namespace TestShareeLib.Model.Connector.Updater
}
}");
var bikes = UpdaterJSON.GetBikesAll(
var bikes = BikeCollectionFactory.GetBikesAll(
availableResponse?.bikes?.Values,
null,
"Heinz.Mustermann@posteo.de",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(
0,
@ -567,11 +578,12 @@ namespace TestShareeLib.Model.Connector.Updater
}
}");
var bikes = UpdaterJSON.GetBikesAll(
var bikes = BikeCollectionFactory.GetBikesAll(
null,
reservedOccupiedResponse?.bikes_occupied?.Values,
"Heinz.Mustermann@posteo.de",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(
0,
@ -605,11 +617,12 @@ namespace TestShareeLib.Model.Connector.Updater
}
}");
var bikes = UpdaterJSON.GetBikesAll(
var bikes = BikeCollectionFactory.GetBikesAll(
null,
reservedOccupiedResponse?.bikes_occupied?.Values,
"Heinz.Mustermann@posteo.de",
() => DateTime.Now);
() => DateTime.Now,
DataSource.Copri);
Assert.AreEqual(
2,
@ -629,6 +642,7 @@ namespace TestShareeLib.Model.Connector.Updater
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("17", LockModel.ILockIt),
new Drive(),
DataSource.Copri,
22,
new Guid("0000f00d-1212-efde-1523-785fef13d123"),
new[] { (byte)1, (byte)3, (byte)4 },
@ -666,7 +680,9 @@ namespace TestShareeLib.Model.Connector.Updater
{
// Construct occupied bike.
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("17", LockModel.ILockIt), new Drive(),
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("17", LockModel.ILockIt),
new Drive(),
DataSource.Copri,
22,
new Guid("0000f00d-1212-efde-1523-785fef13d123"),
new[] { (byte)1, (byte)3, (byte)4 },
@ -702,6 +718,7 @@ namespace TestShareeLib.Model.Connector.Updater
var bike = new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("17", LockModel.ILockIt),
new Drive(),
DataSource.Copri,
22,
new Guid("0000f00d-1212-efde-1523-785fef13d123"),
new[] { (byte)1, (byte)3, (byte)4 },

View file

@ -1,8 +1,9 @@
using System;
using System;
using System.Collections.Generic;
using NUnit.Framework;
using TINK.Model;
using TINK.Model.Bikes;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
@ -17,9 +18,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike
var coll = new BikeCollection(
new Dictionary<string, TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo>
{
{"3", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("7", LockModel.ILockIt), new Drive(), "3" /* Stadion id */) },
{"7", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("8", LockModel.ILockIt), new Drive(), "12" /* Stadion id */) },
{"12", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), "12" /* Stadion id */) }
{"3", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("7", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,"3" /* Stadion id */) },
{"7", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("8", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,"12" /* Stadion id */) },
{"12", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,"12" /* Stadion id */) }
});
Assert.AreEqual(
@ -58,8 +59,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike
var coll = new BikeCollection(
new Dictionary<string, TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo>
{
{"7", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("8", LockModel.ILockIt), new Drive(), "12" /* Stadion id */) },
{"12", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), "12" /* Stadion id */) }
{"7", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("8", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,"12" /* Stadion id */) },
{"12", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,"12" /* Stadion id */) }
});
Assert.AreEqual(
@ -75,9 +76,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike
var coll = new BikeCollection(
new Dictionary<string, TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo>
{
{"7", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("8", LockModel.ILockIt), new Drive(), "12" /* Stadion id */) },
{"11", new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "12" /* Stadion id */) },
{"12", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), "12" /* Stadion id */) }
{"7", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("8", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,"12" /* Stadion id */) },
{"11", new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "12" /* Stadion id */) },
{"12", new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("33", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,"12" /* Stadion id */) }
});
Assert.AreEqual(

View file

@ -1,4 +1,4 @@
using System;
using System;
using NUnit.Framework;
using TINK.Repository.Exception;
using TINK.Repository.Request;
@ -62,11 +62,13 @@ namespace TestShareeLib.Repository.Request
}
[Test]
public void TestGetStationsLangDe()
public void TestGetStationsLangOes()
{
Assert.That(
new RequestBuilder("123", "de").GetStations(),
Is.EqualTo("request=stations_available&authcookie=123&lang=de"));
new RequestBuilder(
"MärchantId",
"öe" /* this non exisiting language id verifies urlencoding */).GetStations(),
Is.EqualTo("request=stations_available&authcookie=M%C3%A4rchantId&lang=%C3%B6e"));
}
[Test]

View file

@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Net;
using NSubstitute;
using NUnit.Framework;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Repository.Exception;
using TINK.Repository.Request;
@ -22,8 +24,8 @@ namespace TestShareeLib.Repository.Request
public void TestDoAuthout()
{
Assert.AreEqual(
"request=authout&authcookie=456123",
new RequestBuilderLoggedIn("123", null /*UI language */, "456").DoAuthout());
"request=authout&authcookie=K%C3%A4ksM%C3%B6rchantId&lang=%C3%B6e",
new RequestBuilderLoggedIn("MörchantId", "öe" /* fictive UI language */, "Käks").DoAuthout());
}
[Test]
@ -90,8 +92,8 @@ namespace TestShareeLib.Repository.Request
public void TestDoReserve()
{
Assert.AreEqual(
"request=booking_request&bike=42&authcookie=456123",
new RequestBuilderLoggedIn("123", null /*UI language */, "456").DoReserve("42"));
"request=booking_request&bike=M%C3%BChleNr42&authcookie=456123",
new RequestBuilderLoggedIn("123", null /*UI language */, "456").DoReserve("MühleNr42"));
}
[Test]
@ -255,11 +257,11 @@ namespace TestShareeLib.Repository.Request
[Test]
public void TestDoReturnGeolocationIsNull()
public void TestDoReturn()
{
var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That(
builder.DoReturn("12", null, null),
builder.DoReturn("12", null /* Geolocation */, null /* Smart device */),
Is.EqualTo("request=booking_update&bike=12&authcookie=MySessionCookieMyMeranctIt&state=available&lock_state=locked"));
}
@ -271,7 +273,7 @@ namespace TestShareeLib.Repository.Request
builder.DoReturn(
"12",
new LocationDto.Builder { Latitude = 21, Longitude = 17, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(),
null),
null /* Smart device */),
Is.EqualTo("request=booking_update&bike=12&authcookie=MySessionCookieMyMeranctIt&state=available&gps=21,17&gps_age=0.07&lock_state=locked"));
}
@ -283,10 +285,66 @@ namespace TestShareeLib.Repository.Request
builder.DoReturn(
"12",
new LocationDto.Builder { Latitude = 21, Longitude = 17, Accuracy = 5.7, Age = new TimeSpan(0, 0, 0, 0, 70) }.Build(),
null),
null /* Smart device */),
Is.EqualTo("request=booking_update&bike=12&authcookie=MySessionCookieMyMeranctIt&state=available&gps=21,17&gps_accuracy=5.7&gps_age=0.07&lock_state=locked"));
}
[Test]
public void TestDoReturnSmartDeviceManufacturer()
{
var sd = Substitute.For<ISmartDevice>();
sd.Manufacturer.Returns("Färphone");
var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That(
builder.DoReturn(
"12",
null, // Geolocation
sd),
Is.EqualTo("request=booking_update&bike=12&authcookie=MySessionCookieMyMeranctIt&state=available&lock_state=locked&user_device_manufaturer=F%C3%A4rphone)"));
}
[Test]
public void TestDoReturnSmartDeviceModel()
{
var sd = Substitute.For<ISmartDevice>();
sd.Model.Returns("Fön");
var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That(
builder.DoReturn(
"12",
null, // Geolocation
sd),
Is.EqualTo("request=booking_update&bike=12&authcookie=MySessionCookieMyMeranctIt&state=available&lock_state=locked&user_device_model=F%C3%B6n"));
}
[Test]
public void TestDoReturnSmartDeviceVersion()
{
var sd = Substitute.For<ISmartDevice>();
sd.VersionText.Returns("ß1");
var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That(
builder.DoReturn(
"12",
null, // Geolocation
sd),
Is.EqualTo("request=booking_update&bike=12&authcookie=MySessionCookieMyMeranctIt&state=available&lock_state=locked&user_device_version=%C3%9F1"));
}
[Test]
public void TestDoReturnSmartDeviceIdentifier()
{
var sd = Substitute.For<ISmartDevice>();
sd.Identifier.Returns("ß9");
var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That(
builder.DoReturn(
"12",
null, // Geolocation
sd),
Is.EqualTo("request=booking_update&bike=12&authcookie=MySessionCookieMyMeranctIt&state=available&lock_state=locked&user_device_id=%C3%9F9"));
}
[Test]
public void TestDoSubmitFeedback_Ok()
{
@ -311,7 +369,7 @@ namespace TestShareeLib.Repository.Request
var builder = new RequestBuilderLoggedIn("MyMeranctIt", null /*UI language */, "MySessionCookie");
Assert.That(
builder.DoSubmitFeedback("Mühle", null, "Uno due tre"),
Is.EqualTo("request=user_feedback&bike=Mühle&message=Uno+due+tre&authcookie=MySessionCookieMyMeranctIt"));
Is.EqualTo("request=user_feedback&bike=M%C3%BChle&message=Uno+due+tre&authcookie=MySessionCookieMyMeranctIt"));
}
[Test]

View file

@ -186,7 +186,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
// Login hint/ no bikes frame
Assert.IsFalse(bikesAtStation.IsLoginRequiredHintVisible);
Assert.IsTrue(bikesAtStation.IsNoBikesAtStationVisible);
Assert.AreEqual("Momentan sind keine Fahrräder an dieser Station verfügbar.", bikesAtStation.NoBikesAtStationText);
Assert.AreEqual("There are currently no bicycles available at this station.", bikesAtStation.NoBikesAtStationText);
}
[Test]
@ -965,7 +965,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
// Login hint/ no bikes frame
Assert.IsFalse(bikesAtStation.IsLoginRequiredHintVisible);
Assert.IsTrue(bikesAtStation.IsNoBikesAtStationVisible);
Assert.AreEqual("Momentan sind keine Fahrräder an dieser Station verfügbar.", bikesAtStation.NoBikesAtStationText);
Assert.AreEqual("There are currently no bicycles available at this station.", bikesAtStation.NoBikesAtStationText);
}
[Test]

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NSubstitute;
using NUnit.Framework;
@ -30,6 +30,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike
IStateInfo stateInfo = null) : base(
new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike(id, lockModel, wheelType, typeOfBike, description),
new TINK.Model.Bikes.BikeInfoNS.DriveNS.Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
isDemo,
group,
stationId,

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
@ -20,8 +20,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Service.LockService
var bikes = new BikeCollection(new Dictionary<string, TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo>()
{
{ "42", new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), 1, new Guid(),new byte[] { 1, 4 }, new byte[] { 3, 4 }, new byte[] { 3, 4 }, DateTime.Now, "a@b", "1" , null /*operator uri*/) },
{ "43", new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("43", LockModel.ILockIt), new Drive(), 3, new Guid(),new byte[] { 4, 4 }, new byte[] { 4, 7 }, new byte[] { 5, 4 }, DateTime.Now, "c@b", "1" , null /*operator uri*/) }
{ "42", new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 1, new Guid(),new byte[] { 1, 4 }, new byte[] { 3, 4 }, new byte[] { 3, 4 }, DateTime.Now, "a@b", "1" , null /*operator uri*/) },
{ "43", new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("43", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 3, new Guid(),new byte[] { 4, 4 }, new byte[] { 4, 7 }, new byte[] { 5, 4 }, DateTime.Now, "c@b", "1" , null /*operator uri*/) }
}
);

View file

@ -1,4 +1,4 @@
using System;
using System;
using Newtonsoft.Json;
using NUnit.Framework;
using TINK.Model.State;
@ -17,14 +17,14 @@ namespace TestTINKLib.Fixtures.State
var l_oReservedInfo = new StateRequestedInfo(
() => new DateTime(2017, 09, 20),
new DateTime(2017, 09, 19),
"a@b",
"ä@b",
"372");
// Serialize object
// Serialize object and verify.
var l_oDetected = JsonConvert.SerializeObject(l_oReservedInfo);
// Verify xml
const string EXPECTED = @"{""From"":""2017 - 09 - 19T00: 00:00"",""MailAddress"":""a @b"",""Code"":""372""}";
const string EXPECTED = @"{""From"":""2017 - 09 - 19T00: 00:00"",""MailAddress"":""ä @b"",""Code"":""372""}";
Assert.AreEqual(
TestHelper.PrepareXmlForStringCompare(EXPECTED),
TestHelper.PrepareXmlForStringCompare(l_oDetected));
@ -34,7 +34,7 @@ namespace TestTINKLib.Fixtures.State
// Verify state.
Assert.AreEqual(InUseStateEnum.Reserved, l_oInfoTarge.Value);
Assert.AreEqual("a@b", l_oInfoTarge.MailAddress);
Assert.AreEqual("ä@b", l_oInfoTarge.MailAddress);
Assert.AreEqual("372", l_oInfoTarge.Code);
Assert.AreEqual(new DateTime(2017, 9, 19, 0, 0, 0), l_oInfoTarge.From);
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Rhino.Mocks;
@ -27,7 +27,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{
// Verify handler for disposable bike.
var bike = new BikeInfoMutable(
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "12"),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "12"),
"My Station Name");
Assert.AreEqual(InUseStateEnum.Disposable, bike.State.Value);
Assert.AreEqual(LockingState.UnknownDisconnected, bike.LockInfo.State);
@ -47,7 +47,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
// Verify handler for requested bike with state unknown.
bike = new BikeInfoMutable(
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), 0 /* lock Id */, new Guid(), /*K User*/ null, /*K Admin*/ null, /*K Seed*/ null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id */, new Guid(), /*K User*/ null, /*K Admin*/ null, /*K Seed*/ null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
"My Station Name");
Assert.AreEqual(
typeof(ReservedDisconnected),
@ -65,7 +65,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
// Verify handler for requested bike with state closed.
bike = new BikeInfoMutable(
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), 0 /* lock Id*/, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Closed;
Assert.AreEqual(
@ -84,7 +84,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
// Verify handler for requested bike with state open.
bike = new BikeInfoMutable(
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), 0 /* lock Id*/, new Guid(), null /* user key */, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null /* user key */, null, null, new DateTime(2020, 1, 1), "a@b.com", "12", null, null, () => new DateTime(2020, 1, 1), false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Open;
Assert.AreEqual(
@ -103,7 +103,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
// Verify handler for booked bike with state closed.
bike = new BikeInfoMutable(
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Closed;
Assert.AreEqual(
@ -122,7 +122,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
// Verify handler for booked bike with state open.
bike = new BikeInfoMutable(
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
"My Station Name");
bike.LockInfo.State = LockingState.Open;
Assert.AreEqual(
@ -141,7 +141,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
// Verify handler for booked bike with state unknown.
bike = new BikeInfoMutable(
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
new BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("22", LockModel.ILockIt, WheelType.Mono, TypeOfBike.Allround), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, 0 /* lock Id*/, new Guid(), null, null, null, new System.DateTime(2020, 1, 1), "a@b.com", "12", null /*operator uri*/, null, false, new List<string>()),
"My Station Name");
Assert.AreEqual(

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Rhino.Mocks;
@ -36,6 +36,7 @@ namespace UITest.Fixtures.ViewModel
IStateInfo stateInfo = null) : base(
new Bike(id, lockModel, wheelType, typeOfBike, description),
new Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
isDemo,
group,
stationId,

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NUnit.Framework;
using TestFramework.Model.User.Account;
@ -31,6 +31,7 @@ namespace UITest.Fixtures.ViewModel
IStateInfo stateInfo = null) : base(
new Bike(id, lockModel, wheelType, typeOfBike, description),
new TINK.Model.Bikes.BikeInfoNS.DriveNS.Drive(),
TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri,
pisDemo,
group,
stationId,

View file

@ -1,8 +1,9 @@
using System;
using System;
using NUnit.Framework;
using Rhino.Mocks;
using TestFramework.Model.Services.Geolocation;
using TestFramework.Services.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS;
using TINK.Model.Device;
@ -30,7 +31,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
null, // viewService
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
MockRepository.GenerateStub<IUser>(), // user
MockRepository.GenerateStub<IInUseStateInfoProvider>(),
MockRepository.GenerateStub<IBikesViewModel>(),
@ -51,7 +52,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
null, // viewService
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), "17", new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = TINK.Model.Bikes.BikeInfoNS.CopriLock.LockingState.Closed }.Build()), "My Station Name"),
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, "17", new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = TINK.Model.Bikes.BikeInfoNS.CopriLock.LockingState.Closed }.Build()), "My Station Name"),
MockRepository.GenerateStub<IUser>(), // user
MockRepository.GenerateStub<IInUseStateInfoProvider>(),
MockRepository.GenerateStub<IBikesViewModel>(),
@ -71,7 +72,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(),
null, // viewService
new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
MockRepository.GenerateStub<IUser>(), // user
MockRepository.GenerateStub<IInUseStateInfoProvider>(),
MockRepository.GenerateStub<IBikesViewModel>(),

View file

@ -605,7 +605,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
Assert.IsFalse(myBikes.IsBikesListVisible, "If there are any bikes, list must be visible.");
Assert.IsTrue(myBikes.IsNoBikesOccupiedVisible);
Assert.AreEqual("Momentan sind keine Fahrräder auf Benutzer a@b reserviert/ gebucht.", myBikes.NoBikesOccupiedText);
Assert.AreEqual("There are currently no bicycles reserved/booked on user a@b.", myBikes.NoBikesOccupiedText);
}
[Test]