using Serilog; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using TINK.Model.Bike; using TINK.Repository.Exception; using TINK.Repository.Response; using TINK.Model.Services.CopriApi.ServerUris; using TINK.Model.State; namespace TINK.Model.Connector { /// /// Conversion helper functionality. /// public static class TextToTypeHelper { /// Holds the text for demo bikes. private const string DEMOBIKEMARKER = "DEMO"; /// Part text denoting two wheel cargo bike.. private const string TWOWHEELCARGOMARKERFRAGMENT = "LONG"; /// /// Gets the position from StationInfo object. /// /// Object to get information from. /// Position information. public static Station.Position GetPosition(this StationsAllResponse.StationInfo p_oStationInfo) { return GetPosition(p_oStationInfo.gps); } /// Gets the position from StationInfo object. /// Object to get information from. /// Position information. public static IEnumerable GetGroup(this AuthorizationResponse p_oAuthorizationResponse) { try { return p_oAuthorizationResponse.user_group.GetGroup(); } catch (Exception l_oException) { throw new Exception($"Can not get group of user from text \"{p_oAuthorizationResponse.user_group}\".", l_oException); } } /// Gets the position from StationInfo object. /// Object to get information from. /// Position information. public static IEnumerable GetGroup(this string[] group) { if (group == null || group.Length == 0) { // If not logged in stations groups are empty form COPRI version v4.1. Log.Debug("Can not get goup form string. Group text can not be null."); return new List(); } return new HashSet(group).ToList(); } /// Gets the position from StationInfo object. /// Object to get information from. /// Position information. public static string GetGroup(this IEnumerable p_oGroup) { return string.Join(",", p_oGroup); } /// Gets the position from StationInfo object. /// Object to get information from. /// Position information. public static IEnumerable GetGroup(this StationsAllResponse.StationInfo p_oStationInfo) { try { return p_oStationInfo.station_group.GetGroup(); } catch (Exception l_oException) { throw new Exception($"Can not get group of stations from text \"{p_oStationInfo.station_group}\".", l_oException); } } /// /// Gets the position from StationInfo object. /// /// Object to get information from. /// Position information. public static Station.Position GetPosition(this BikeInfoAvailable p_oBikeInfo) { return GetPosition(p_oBikeInfo.gps); } /// /// Gets the position from StationInfo object. /// /// Object to get information from. /// Position information. public static InUseStateEnum GetState(this BikeInfoBase p_oBikeInfo) { var l_oState = p_oBikeInfo.state; if (string.IsNullOrEmpty(l_oState)) { throw new InvalidResponseException( string.Format("Unknown reservation state detected. Member {0}.{1}.", typeof(BikeInfoBase), nameof(BikeInfoBase.state)), p_oBikeInfo); } if (l_oState == "available") { return InUseStateEnum.Disposable; } else if (l_oState == "reserved" || l_oState == "requested") { return InUseStateEnum.Reserved; } else if (l_oState == "booked" || l_oState == "occupied") { return InUseStateEnum.Booked; } throw new CommunicationException(string.Format("Unknown bike state detected. State is {0}.", l_oState)); } /// /// Gets the from date information from JSON. /// /// JSON to get information from.. /// From information. public static DateTime GetFrom(this BikeInfoReservedOrBooked p_oBikeInfo) { return DateTime.Parse(p_oBikeInfo.start_time); } /// /// Gets whether the bike is a trike or not. /// /// JSON to get information from.. /// From information. public static bool? GetIsDemo(this BikeInfoBase p_oBikeInfo) { return p_oBikeInfo?.description != null ? p_oBikeInfo.description.ToUpper().Contains(DEMOBIKEMARKER) : (bool?) null; } /// /// Gets whether the bike is a trike or not. /// /// JSON to get information from.. /// From information. public static IEnumerable GetGroup(this BikeInfoBase p_oBikeInfo) { try { return p_oBikeInfo?.bike_group?.GetGroup()?.ToList() ?? new List(); } catch (System.Exception l_oException) { throw new System.Exception($"Can not get group of user from text \"{p_oBikeInfo.bike_group}\".", l_oException); } } /// Gets whether the bike has a bord computer or not. /// JSON to get information from. /// From information. public static bool GetIsManualLockBike(this BikeInfoBase p_oBikeInfo) { return !string.IsNullOrEmpty(p_oBikeInfo.system) && p_oBikeInfo.system.ToUpper().StartsWith("LOCK"); } /// Gets whether the bike has a bord computer or not. /// JSON to get information from.. /// From information. public static bool GetIsBluetoothLockBike(this BikeInfoBase p_oBikeInfo) { return !string.IsNullOrEmpty(p_oBikeInfo.system) && p_oBikeInfo.system.ToUpper().StartsWith("ILOCKIT"); } /// Gets whether the bike has a bord computer or not. /// JSON to get information from.. /// From information. public static int GetBluetoothLockId(this BikeInfoAvailable bikeInfo) { return TextToLockItTypeHelper.GetBluetoothLockId(bikeInfo?.Ilockit_ID); } /// Gets whether the bike has a bord computer or not. /// JSON to get information from.. /// From information. public static Guid GetBluetoothLockGuid(this BikeInfoAvailable bikeInfo) { // return new Guid("00000000-0000-0000-0000-e57e6b9aee16"); return Guid.TryParse(bikeInfo?.Ilockit_GUID, out Guid lockGuid) ? lockGuid : TextToLockItTypeHelper.INVALIDLOCKGUID; } public static byte[] GetUserKey(this BikeInfoReservedOrBooked bikeInfo) { return GetKey(bikeInfo.K_u); } public static byte[] GetAdminKey(this BikeInfoReservedOrBooked bikeInfo) { return GetKey(bikeInfo.K_a); } public static byte[] GetSeed(this BikeInfoReservedOrBooked bikeInfo) { return GetKey(bikeInfo.K_seed); } /// /// Get array of keys from string of format "[12, -9, 5]" /// /// /// private static byte[] GetKey(string keyArrayText) { try { if (string.IsNullOrEmpty(keyArrayText)) return new byte[0]; return Regex.Replace(keyArrayText, @"\[(.*)\]", "$1").Split(',').Select(x => (byte)sbyte.Parse(x)).ToArray(); } catch (Exception exception) { Log.Error("Can not extract K_u/ K_a/ or K_seed. Key {ArrayText} does not is not of expected format. {Exception}", keyArrayText, exception); return new byte[0]; } } /// /// Gets whether the bike is a trike or not. /// /// JSON to get information from.. /// From information. public static WheelType? GetWheelType(this BikeInfoBase bikeInfo) { var l_oDescription = bikeInfo.description; if (l_oDescription == null) { // Can not get type of wheel if description text is empty. return null; } foreach (WheelType l_oWheelType in Enum.GetValues(typeof(WheelType))) { if (l_oDescription.ToUpper().Contains(l_oWheelType.ToString().ToUpper())) { return l_oWheelType; } } // Check for custom value "Long". if (l_oDescription.ToUpper().Contains(TWOWHEELCARGOMARKERFRAGMENT)) { return WheelType.Two; } // Check for Stadrad. if (GetTypeOfBike(bikeInfo) == TypeOfBike.Citybike) { return WheelType.Two; } return null; } /// /// Gets the type of bike. /// /// Object to get bike type from. /// Type of bike. public static TypeOfBike? GetTypeOfBike(this BikeInfoBase bikeInfo) { var l_oDescription = bikeInfo?.description; if (l_oDescription == null) { // Can not get type of wheel if description text is empty. return null; } foreach (TypeOfBike l_oTypeOfBike in Enum.GetValues(typeof(TypeOfBike))) { if (l_oDescription.ToUpper().Contains(l_oTypeOfBike.GetCopriText().ToUpper())) { return l_oTypeOfBike; } } return null; } /// /// Get position from a ,- separated string. /// /// Text to extract positon from. /// Position object. public static Station.Position GetPosition(GpsInfo gps) { if (gps == null) { return null; } double l_oLatitude; if (!double.TryParse(gps.latitude, NumberStyles.Float, CultureInfo.InvariantCulture, out l_oLatitude)) return null; double l_oLongitude; if (!double.TryParse(gps.longitude, NumberStyles.Float, CultureInfo.InvariantCulture, out l_oLongitude)) return null; return new Station.Position(l_oLatitude, l_oLongitude); } /// Gets text of bike from. /// Type to get text for. /// public static string GetCopriText(this TypeOfBike p_eType) { switch (p_eType) { case TypeOfBike.Citybike: return "Stadtrad"; default: return p_eType.ToString(); } } public static Uri GetOperatorUri(this BikeInfoBase bikeInfo) { return bikeInfo?.uri_operator != null && !string.IsNullOrEmpty(bikeInfo?.uri_operator) ? new Uri($"{bikeInfo.uri_operator}/{CopriServerUriList.REST_RESOURCE_ROOT}") : null; } /// Gets the copriversion from. /// Response to get version info from. /// COPRI version public static Version GetCopriVersion(this CopriVersion response) => response!= null && !string.IsNullOrEmpty(response.copri_version) && Version.TryParse(response.copri_version, out Version copriVersion) ? copriVersion : throw new InvalidResponseException($"Can not get version info from copri response {response?.copri_version}."); } }