sharee.bike-App/TINKLib/Model/Connector/Updater/BikeInfoFactory.cs
2023-06-06 12:05:48 +02:00

328 lines
12 KiB
C#

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;
using TINK.Repository.Response;
using BikeExtension = TINK.Model.Bikes.BikeInfoNS.BikeNS.BikeExtension;
namespace TINK.Model.Connector.Updater
{
/// <summary>
/// Constructs bike info instances/ bike info derived instances.
/// </summary>
public static class BikeInfoFactory
{
/// <summary> Set default lock type to . </summary>
public static LockModel DEFAULTLOCKMODEL = LockModel.Sigo;
/// <summary> Creates a bike info object from copri response. </summary>
/// <param name="bikeInfo">Copri response for a disposable bike. </param>
/// <param name="dataSource">Specifies the data source.</param>
public static BikeInfo Create(
BikeInfoAvailable bikeInfo,
DataSource dataSource)
{
if (bikeInfo == null) throw new ArgumentNullException(nameof(bikeInfo));
var lockModel = bikeInfo.GetLockModel();
if (lockModel.HasValue
&& lockModel.Value == LockModel.BordComputer)
{
// Manual lock bikes are no more supported.
Log.Error(
$"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. " +
"Manual lock bikes are no more supported." +
$"Bike number: {bikeInfo.bike}{(bikeInfo.station != null ? $"station number {bikeInfo.station}" : string.Empty)}."
);
return null;
}
switch (bikeInfo.GetState())
{
case InUseStateEnum.Disposable:
case InUseStateEnum.FeedbackPending:
break;
default:
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. Unexpected state {bikeInfo.GetState()} detected.");
return null;
}
if (string.IsNullOrEmpty(bikeInfo.station))
{
// Bike available must always have a station id because bikes can only be returned at a station.
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. No station info set.");
return null;
}
var lockType = lockModel.HasValue
? BikeExtension.GetLockType(lockModel.Value)
: BikeExtension.GetLockType(DEFAULTLOCKMODEL); // Map bikes without "system"- entry in response to back end- locks.
try
{
switch (lockType)
{
case LockType.Backend:
return new Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.Sigo,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.GetAaRideType(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
bikeInfo.station,
new Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = bikeInfo.GetCopriLockingState() }.Build(),
bikeInfo.GetState() == InUseStateEnum.FeedbackPending,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription) null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup(),
miniSurvey: bikeInfo.user_miniquery != null
? new MiniSurveyModel(new Dictionary<string, IQuestionModel> {
{ "q1", new QuestionModel()} // Add a dummy query. Queries are not yet read from COPRI but compiled into the app.
})
: new MiniSurveyModel(),
co2Saving: bikeInfo.co2saving);
case LockType.Bluethooth:
return new Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.ILockIt,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.GetAaRideType(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
bikeInfo.GetBluetoothLockId(),
bikeInfo.GetBluetoothLockGuid(),
bikeInfo.station,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
default:
throw new ArgumentException($"Unsupported lock type {lockType} detected.");
}
}
catch (ArgumentException ex)
{
// Constructor reported invalid arguments (missing lock id, ....).
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. Invalid response detected. Available bike with id {bikeInfo.bike} skipped. {ex.Message}");
return null;
}
}
/// <summary> Creates a bike info object from copri response. </summary>
/// <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,
DataSource dataSource)
{
if (bikeInfo == null) throw new ArgumentNullException(nameof(bikeInfo));
var lockModel = bikeInfo.GetLockModel();
if (lockModel.HasValue
&& lockModel.Value == LockModel.BordComputer)
{
// Manual lock bikes are no more supported.
Log.Error(
$"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. " +
"Manual lock bikes are no more supported." +
$"Bike number: {bikeInfo.bike}{(bikeInfo.station != null ? $", station number {bikeInfo.station}" : string.Empty)}."
);
return null;
}
var lockType = lockModel.HasValue
? BikeExtension.GetLockType(lockModel.Value)
: BikeExtension.GetLockType(DEFAULTLOCKMODEL); // Map bikes without "system"- entry in response to backend- locks.
// Check if bike is a bluetooth lock bike.
int lockSerial = bikeInfo.GetBluetoothLockId();
Guid lockGuid = bikeInfo.GetBluetoothLockGuid();
switch (bikeInfo.GetState())
{
case InUseStateEnum.Reserved:
try
{
switch (lockType)
{
case LockType.Bluethooth:
return new Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.ILockIt,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.GetAaRideType(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
lockSerial,
lockGuid,
bikeInfo.GetUserKey(),
bikeInfo.GetAdminKey(),
bikeInfo.GetSeed(),
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
dateTimeProvider,
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
case LockType.Backend:
return new Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.Sigo,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.GetAaRideType(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
new Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = bikeInfo.GetCopriLockingState() }.Build(),
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
dateTimeProvider,
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
default:
throw new ArgumentException($"Unsupported lock type {lockType} detected.");
}
}
catch (ArgumentException ex)
{
// Constructor reported invalid arguments (missing lock id, ....).
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoReservedOrBooked)} argument. Invalid response detected. Reserved bike with id {bikeInfo.bike} skipped. {ex.Message}");
return null;
}
case InUseStateEnum.Booked:
try
{
switch (lockModel)
{
case LockModel.ILockIt:
return new Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.ILockIt,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.GetAaRideType(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
dataSource,
lockSerial,
bikeInfo.GetBluetoothLockGuid(),
bikeInfo.GetUserKey(),
bikeInfo.GetAdminKey(),
bikeInfo.GetSeed(),
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
case LockModel.BordComputer:
throw new NotSupportedException($"Bikes with lock model of type {lockModel} are no more supported.");
default:
return new Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.Sigo,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.GetAaRideType(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
DataSource.Copri,
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
new Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = bikeInfo.GetCopriLockingState() }.Build(),
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
}
}
catch (ArgumentException ex)
{
// Constructor reported invalid arguments (missing lock id, ....).
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoReservedOrBooked)} argument. Invalid response detected. Booked bike with id {bikeInfo.bike} skipped. {ex.Message}");
return null;
}
default:
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. Unexpected state {bikeInfo.GetState()} detected.");
return null;
}
}
}
}