From 7fa72db0704904ee48c1959ec7c2a23c7cc081da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Thu, 2 Nov 2023 23:59:09 +0900 Subject: [PATCH 01/29] Add TRViS.LocationService project to solution --- TRViS.LocationService/TRViS.LocationService.csproj | 10 ++++++++++ TRViS.sln | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 TRViS.LocationService/TRViS.LocationService.csproj diff --git a/TRViS.LocationService/TRViS.LocationService.csproj b/TRViS.LocationService/TRViS.LocationService.csproj new file mode 100644 index 00000000..5625b3af --- /dev/null +++ b/TRViS.LocationService/TRViS.LocationService.csproj @@ -0,0 +1,10 @@ + + + + netstandard2.1 + 11.0 + enable + enable + + + diff --git a/TRViS.sln b/TRViS.sln index 3928c350..02be5a96 100644 --- a/TRViS.sln +++ b/TRViS.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 17.0.31611.283 @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TRViS.IO", "TRViS.IO\TRViS. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TRViS.IO.Tests", "TRViS.IO.Tests\TRViS.IO.Tests.csproj", "{39F34DB6-F6A8-4830-A2A0-A3F18C81C225}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TRViS.LocationService", "TRViS.LocationService\TRViS.LocationService.csproj", "{7B07663D-D68A-4CFD-823B-EE07644FEA8F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,6 +31,10 @@ Global {39F34DB6-F6A8-4830-A2A0-A3F18C81C225}.Debug|Any CPU.Build.0 = Debug|Any CPU {39F34DB6-F6A8-4830-A2A0-A3F18C81C225}.Release|Any CPU.ActiveCfg = Release|Any CPU {39F34DB6-F6A8-4830-A2A0-A3F18C81C225}.Release|Any CPU.Build.0 = Release|Any CPU + {7B07663D-D68A-4CFD-823B-EE07644FEA8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B07663D-D68A-4CFD-823B-EE07644FEA8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B07663D-D68A-4CFD-823B-EE07644FEA8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B07663D-D68A-4CFD-823B-EE07644FEA8F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From a56cd036e602f93f8ec09e77fe4ce22cad7e10fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Sun, 12 Nov 2023 22:58:27 +0900 Subject: [PATCH 02/29] change line ending from CRLF to LF --- .../TRViS.LocationService.csproj | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/TRViS.LocationService/TRViS.LocationService.csproj b/TRViS.LocationService/TRViS.LocationService.csproj index 5625b3af..559307bf 100644 --- a/TRViS.LocationService/TRViS.LocationService.csproj +++ b/TRViS.LocationService/TRViS.LocationService.csproj @@ -1,10 +1,10 @@ - - - - netstandard2.1 - 11.0 - enable - enable - - - + + + + netstandard2.1 + 11.0 + enable + enable + + + From f993a48fac227aa2d9f366feb23b16e1f9e131d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Sun, 12 Nov 2023 23:03:37 +0900 Subject: [PATCH 03/29] Create CalculateDistance.cs --- .../Utils/CalculateDistance.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 TRViS.LocationService/Utils/CalculateDistance.cs diff --git a/TRViS.LocationService/Utils/CalculateDistance.cs b/TRViS.LocationService/Utils/CalculateDistance.cs new file mode 100644 index 00000000..0d1d2763 --- /dev/null +++ b/TRViS.LocationService/Utils/CalculateDistance.cs @@ -0,0 +1,26 @@ +namespace TRViS.Services.LocationService; + +internal static partial class Utils +{ + const double EARTH_RADIUS_m = 6378137; + + public static double DegToRad(in double deg) + => deg * Math.PI / 180.0; + + // Haversine Formula + public static double CalculateDistance_m(in double lon1_deg, in double lat1_deg, in double lon2_deg, in double lat2_deg) + { + double lon1_rad = DegToRad(lon1_deg); + double lat1_rad = DegToRad(lat1_deg); + double lon2_rad = DegToRad(lon2_deg); + double lat2_rad = DegToRad(lat2_deg); + + return EARTH_RADIUS_m * Math.Acos( + Math.Sin(lat1_rad) * Math.Sin(lat2_rad) + + Math.Cos(lat1_rad) * Math.Cos(lat2_rad) * Math.Cos(lon2_rad - lon1_rad) + ); + } + + public static double CalculateDistance_m(in ILocationLonLat_deg value1, in ILocationLonLat_deg value2) + => CalculateDistance_m(value1.Location_lon_deg, value1.Location_lat_deg, value2.Location_lon_deg, value2.Location_lat_deg); +} From 8fcc6115668daf81ec904634d09090c733db52b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Sun, 12 Nov 2023 23:05:26 +0900 Subject: [PATCH 04/29] Create IsNearBy.cs --- TRViS.LocationService/Utils/IsNearBy.cs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 TRViS.LocationService/Utils/IsNearBy.cs diff --git a/TRViS.LocationService/Utils/IsNearBy.cs b/TRViS.LocationService/Utils/IsNearBy.cs new file mode 100644 index 00000000..72c2f255 --- /dev/null +++ b/TRViS.LocationService/Utils/IsNearBy.cs @@ -0,0 +1,9 @@ +namespace TRViS.Services.LocationService; + +internal static partial class Utils +{ + public static bool IsNearBy(StaLocationInfo target, ILocationLonLat_deg currentLocation) + => IsNearBy(target, CalculateDistance_m(target, currentLocation)); + public static bool IsNearBy(StaLocationInfo target, double currentDistance_m) + => currentDistance_m <= target.NearbyRadius_m; +} From c4fd06b574d52c702395d014652e69e651ddba9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Sun, 12 Nov 2023 23:06:49 +0900 Subject: [PATCH 05/29] add test project for TRViS.LocationService --- TRViS.LocationService.Tests/GlobalUsings.cs | 1 + .../TRViS.LocationService.Tests.csproj | 24 +++++++++++++++++++ TRViS.sln | 6 +++++ 3 files changed, 31 insertions(+) create mode 100644 TRViS.LocationService.Tests/GlobalUsings.cs create mode 100644 TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj diff --git a/TRViS.LocationService.Tests/GlobalUsings.cs b/TRViS.LocationService.Tests/GlobalUsings.cs new file mode 100644 index 00000000..32445676 --- /dev/null +++ b/TRViS.LocationService.Tests/GlobalUsings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; diff --git a/TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj b/TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj new file mode 100644 index 00000000..b9451058 --- /dev/null +++ b/TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + diff --git a/TRViS.sln b/TRViS.sln index 02be5a96..c5944145 100644 --- a/TRViS.sln +++ b/TRViS.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TRViS.IO.Tests", "TRViS.IO. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TRViS.LocationService", "TRViS.LocationService\TRViS.LocationService.csproj", "{7B07663D-D68A-4CFD-823B-EE07644FEA8F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TRViS.LocationService.Tests", "TRViS.LocationService.Tests\TRViS.LocationService.Tests.csproj", "{9E965886-84FE-499E-9C30-D17F707D5EF5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,6 +37,10 @@ Global {7B07663D-D68A-4CFD-823B-EE07644FEA8F}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B07663D-D68A-4CFD-823B-EE07644FEA8F}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B07663D-D68A-4CFD-823B-EE07644FEA8F}.Release|Any CPU.Build.0 = Release|Any CPU + {9E965886-84FE-499E-9C30-D17F707D5EF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E965886-84FE-499E-9C30-D17F707D5EF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E965886-84FE-499E-9C30-D17F707D5EF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E965886-84FE-499E-9C30-D17F707D5EF5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 849edc514735500dff837f79d2e5c36b4b061e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Wed, 15 Nov 2023 21:21:19 +0900 Subject: [PATCH 06/29] =?UTF-8?q?Leave=E5=88=A4=E5=AE=9A=E7=94=A8=E3=81=AE?= =?UTF-8?q?=E9=96=A2=E6=95=B0=E3=82=82=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS.LocationService/Utils/IsNearBy.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/TRViS.LocationService/Utils/IsNearBy.cs b/TRViS.LocationService/Utils/IsNearBy.cs index 72c2f255..8d22555f 100644 --- a/TRViS.LocationService/Utils/IsNearBy.cs +++ b/TRViS.LocationService/Utils/IsNearBy.cs @@ -5,5 +5,15 @@ internal static partial class Utils public static bool IsNearBy(StaLocationInfo target, ILocationLonLat_deg currentLocation) => IsNearBy(target, CalculateDistance_m(target, currentLocation)); public static bool IsNearBy(StaLocationInfo target, double currentDistance_m) - => currentDistance_m <= target.NearbyRadius_m; + => IsNearBy(target.NearbyRadius_m, currentDistance_m); + + public static bool IsNearBy(double NearbyRadius_m, double currentDistance_m) + => currentDistance_m <= NearbyRadius_m; + + public static bool IsLeaved(StaLocationInfo target, ILocationLonLat_deg currentLocation) + => IsLeaved(target, CalculateDistance_m(target, currentLocation)); + public static bool IsLeaved(StaLocationInfo target, double currentDistance_m) + => IsLeaved(target.NearbyRadius_m, currentDistance_m); + public static bool IsLeaved(double NearbyRadius_m, double currentDistance_m) + => !IsNearBy(NearbyRadius_m * 1.1, currentDistance_m); } From 0fa965905b0fb93fd56dbd479ce6784ee9281eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Wed, 15 Nov 2023 22:07:35 +0900 Subject: [PATCH 07/29] Create ILocationService.cs --- TRViS.LocationService/ILocationService.cs | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 TRViS.LocationService/ILocationService.cs diff --git a/TRViS.LocationService/ILocationService.cs b/TRViS.LocationService/ILocationService.cs new file mode 100644 index 00000000..921bfb5f --- /dev/null +++ b/TRViS.LocationService/ILocationService.cs @@ -0,0 +1,52 @@ +namespace TRViS.Services; + +public class LocationStateChangedEventArgs : EventArgs, IEquatable +{ + public int NewStationIndex { get; } + public bool IsRunningToNextStation { get; } + + public LocationStateChangedEventArgs(int newStationIndex, bool isRunningToNextStation) + { + NewStationIndex = newStationIndex; + IsRunningToNextStation = isRunningToNextStation; + } + + public bool Equals(LocationStateChangedEventArgs? other) + { + if (other is null) + return false; + + if (ReferenceEquals(this, other)) + return true; + + return + NewStationIndex == other.NewStationIndex + && + IsRunningToNextStation == other.IsRunningToNextStation + ; + } + + public override bool Equals(object obj) + => Equals(obj as LocationStateChangedEventArgs); + + public override int GetHashCode() + => HashCode.Combine(NewStationIndex, IsRunningToNextStation); + + public override string ToString() + { + return $"{nameof(LocationStateChangedEventArgs)} {{ {nameof(NewStationIndex)}: {NewStationIndex}, {nameof(IsRunningToNextStation)}: {IsRunningToNextStation} }}"; + } +} + +public interface ILocationService +{ + event EventHandler? LocationStateChanged; + + StaLocationInfo[]? StaLocationInfo { get; set; } + + int CurrentStationIndex { get; } + + bool IsRunningToNextStation { get; } + + void ResetLocationInfo(); +} From a81e85fa7079085cc424d3faf7832bf6243faec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Wed, 15 Nov 2023 22:08:27 +0900 Subject: [PATCH 08/29] Create StaLocationInfo.cs --- TRViS.LocationService/StaLocationInfo.cs | 53 ++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 TRViS.LocationService/StaLocationInfo.cs diff --git a/TRViS.LocationService/StaLocationInfo.cs b/TRViS.LocationService/StaLocationInfo.cs new file mode 100644 index 00000000..23a9b164 --- /dev/null +++ b/TRViS.LocationService/StaLocationInfo.cs @@ -0,0 +1,53 @@ +namespace TRViS.Services; + +public interface ILocationLonLat_deg +{ + double Location_lon_deg { get; } + double Location_lat_deg { get; } +} + +public class StaLocationInfo : ILocationLonLat_deg +{ + public double Location_m { get; } + public double Location_lon_deg { get; } + public double Location_lat_deg { get; } + public double NearbyRadius_m { get; } + + public StaLocationInfo(double location_m, double location_lon_deg, double location_lat_deg, double nearbyRadius_m) + { + Location_m = location_m; + Location_lon_deg = location_lon_deg; + Location_lat_deg = location_lat_deg; + NearbyRadius_m = nearbyRadius_m; + } + + public bool Equals(StaLocationInfo? other) + { + if (other is null) + return false; + + if (ReferenceEquals(this, other)) + return true; + + return + Location_m == other.Location_m + && + Location_lon_deg == other.Location_lon_deg + && + Location_lat_deg == other.Location_lat_deg + && + NearbyRadius_m == other.NearbyRadius_m + ; + } + + public override bool Equals(object obj) + => Equals(obj as StaLocationInfo); + + public override int GetHashCode() + => HashCode.Combine(Location_m, Location_lon_deg, Location_lat_deg, NearbyRadius_m); + + public override string ToString() + { + return $"{nameof(StaLocationInfo)} {{ {nameof(Location_m)}: {Location_m}, {nameof(Location_lon_deg)}: {Location_lon_deg}, {nameof(Location_lat_deg)}: {Location_lat_deg}, {nameof(NearbyRadius_m)}: {NearbyRadius_m} }}"; + } +} From 64c11f22297b8673ac57c2f18d9bbf9d83c9dfa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Wed, 15 Nov 2023 22:08:34 +0900 Subject: [PATCH 09/29] Create LonLatLocationService.cs --- .../LonLatLocationService.cs | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 TRViS.LocationService/LonLatLocationService.cs diff --git a/TRViS.LocationService/LonLatLocationService.cs b/TRViS.LocationService/LonLatLocationService.cs new file mode 100644 index 00000000..b8a0f532 --- /dev/null +++ b/TRViS.LocationService/LonLatLocationService.cs @@ -0,0 +1,163 @@ + +using TRViS.Services.LocationService; + +namespace TRViS.Services; + +public class LonLatLocationService : ILocationService +{ + public event EventHandler? LocationStateChanged; + + const int CURRENT_STATION_INDEX_NOT_SET = -1; + const int DISTANCE_HISTORY_QUEUE_SIZE = 3; + readonly Queue DistanceHistoryQueue = new(DISTANCE_HISTORY_QUEUE_SIZE); + + private StaLocationInfo[]? _staLocationInfo; + public StaLocationInfo[]? StaLocationInfo + { + get => _staLocationInfo; + set + { + if (value == _staLocationInfo) + return; + + _staLocationInfo = value; + ResetLocationInfo(); + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + } + } + + public int CurrentStationIndex { get; private set; } = CURRENT_STATION_INDEX_NOT_SET; + + public bool IsRunningToNextStation { get; private set; } + + public void ResetLocationInfo() + => ResetLocationInfo(true); + void ResetLocationInfo(bool invokeEvent) + { + CurrentStationIndex = StaLocationInfo is null ? CURRENT_STATION_INDEX_NOT_SET : 0; + IsRunningToNextStation = false; + DistanceHistoryQueue.Clear(); + + if (invokeEvent) + { + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + } + } + + public void ForceSetLocationInfo(double lon_deg, double lat_deg) + { + ResetLocationInfo(false); + if (StaLocationInfo is null) + return; + + if (StaLocationInfo.Length <= 1) + { + CurrentStationIndex = StaLocationInfo.Length - 1; + IsRunningToNextStation = false; + return; + } + + double[] distanceArray = StaLocationInfo.Select(v => Utils.CalculateDistance_m(lon_deg, lat_deg, v.Location_lon_deg, v.Location_lat_deg)).ToArray(); + + int nearestStationIndex = -1; + double nearestDistance = double.MaxValue; + for (int i = 0; i < distanceArray.Length; i++) + { + if (distanceArray[i] < nearestDistance) + { + nearestStationIndex = i; + nearestDistance = distanceArray[i]; + } + } + + if (nearestStationIndex == 0) + { + // 最初の駅が一番近い場合 + CurrentStationIndex = 0; + IsRunningToNextStation = Utils.IsLeaved(StaLocationInfo[nearestStationIndex], distanceArray[nearestStationIndex]); + } + else if (nearestStationIndex == StaLocationInfo.Length - 1) + { + // 最後の駅が一番近い場合 + if (Utils.IsNearBy(StaLocationInfo[nearestStationIndex], distanceArray[nearestStationIndex])) + { + CurrentStationIndex = nearestStationIndex; + IsRunningToNextStation = false; + } + else + { + CurrentStationIndex = nearestStationIndex - 1; + IsRunningToNextStation = true; + } + } + else + { + // 途中の駅が一番近い場合 + if (Utils.IsNearBy(StaLocationInfo[nearestStationIndex], distanceArray[nearestStationIndex])) + { + CurrentStationIndex = nearestStationIndex; + IsRunningToNextStation = false; + } + else + { + IsRunningToNextStation = true; + CurrentStationIndex = nearestStationIndex; + // 次の駅よりも前の駅の方が近い場合、おそらく前の駅からこの駅に向かっているところである + if (distanceArray[nearestStationIndex - 1] < distanceArray[nearestStationIndex + 1]) + { + CurrentStationIndex = nearestStationIndex - 1; + } + } + } + + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + } + + double GetDistanceToStationAverage(in StaLocationInfo staLocationInfo, double lon_deg, double lat_deg) + { + double distanceToStation = Utils.CalculateDistance_m(lon_deg, lat_deg, staLocationInfo.Location_lon_deg, staLocationInfo.Location_lat_deg); + + if (DistanceHistoryQueue.Count == DISTANCE_HISTORY_QUEUE_SIZE) + DistanceHistoryQueue.Dequeue(); + DistanceHistoryQueue.Enqueue(distanceToStation); + + if (DistanceHistoryQueue.Count < DISTANCE_HISTORY_QUEUE_SIZE) + return double.NaN; + + return DistanceHistoryQueue.Average(); + } + + public void SetCurrentLocation(double lon_deg, double lat_deg) + { + if (StaLocationInfo is null || CurrentStationIndex < 0 || StaLocationInfo.Length <= CurrentStationIndex) + return; + + if (IsRunningToNextStation) + { + StaLocationInfo nextStation = StaLocationInfo[CurrentStationIndex + 1]; + double distanceToNextStationAverage = GetDistanceToStationAverage(nextStation, lon_deg, lat_deg); + + if (!double.IsNaN(distanceToNextStationAverage) + && Utils.IsNearBy(nextStation, distanceToNextStationAverage)) + { + DistanceHistoryQueue.Clear(); + CurrentStationIndex++; + IsRunningToNextStation = false; + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + } + } + else if (CurrentStationIndex < StaLocationInfo.Length - 1) + { + StaLocationInfo currentStation = StaLocationInfo[CurrentStationIndex]; + + double distanceFromCurrentStationAverage = GetDistanceToStationAverage(currentStation, lon_deg, lat_deg); + if (!double.IsNaN(distanceFromCurrentStationAverage) + && Utils.IsLeaved(currentStation, distanceFromCurrentStationAverage)) + { + DistanceHistoryQueue.Clear(); + IsRunningToNextStation = true; + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + } + } + } +} From b7709ecd2ecc0af670e3be4611711d0694818d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Wed, 15 Nov 2023 22:08:58 +0900 Subject: [PATCH 10/29] Create LonLatLocationService.Tests.cs --- .../LonLatLocationService.Tests.cs | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 TRViS.LocationService.Tests/LonLatLocationService.Tests.cs diff --git a/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs b/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs new file mode 100644 index 00000000..5f973d3f --- /dev/null +++ b/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs @@ -0,0 +1,102 @@ +using TRViS.Services; + +namespace TRViS.LocationService.Tests; + +public class Tests +{ + [Test] + public void InitializeTest() + { + LonLatLocationService service = new(); + Assert.Multiple(() => + { + Assert.That(service.StaLocationInfo, Is.Null); + Assert.That(service.CurrentStationIndex, Is.EqualTo(-1)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + } + + [Test] + public void MoveTest() + { + LonLatLocationService service = new() + { + StaLocationInfo = + [ + new(0, 0, 0, 200), + new(1, 1, 1, 200), + new(2, 2, 2, 200), + ] + }; + + // 初期状態は、駅0にいる + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + + service.SetCurrentLocation(0.1, 0.1); + + // (平均値を取るために、3回以上の移動が必要) + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + + service.SetCurrentLocation(0.1, 0.1); + service.SetCurrentLocation(0.1, 0.1); + + // 駅0を離れ、駅1に向かっている + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.True); + }); + + service.SetCurrentLocation(1, 1); + service.SetCurrentLocation(1, 1); + service.SetCurrentLocation(1, 1); + + // ちょうど駅1にいる + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(1)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + + service.SetCurrentLocation(2, 2); + service.SetCurrentLocation(2, 2); + service.SetCurrentLocation(2, 2); + + // 駅1を離れ、駅2に向かっている + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(1)); + Assert.That(service.IsRunningToNextStation, Is.True); + }); + + service.SetCurrentLocation(2, 2); + service.SetCurrentLocation(2, 2); + service.SetCurrentLocation(2, 2); + + // ちょうど駅2にいる + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(2)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + + service.SetCurrentLocation(3, 3); + service.SetCurrentLocation(3, 3); + service.SetCurrentLocation(3, 3); + + // 駅2から先には進まない + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(2)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + } +} From 011ee09760a3d283315a72a0d97760005da61bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Wed, 15 Nov 2023 22:09:58 +0900 Subject: [PATCH 11/29] =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=83=87=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj b/TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj index b9451058..db4ce0f5 100644 --- a/TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj +++ b/TRViS.LocationService.Tests/TRViS.LocationService.Tests.csproj @@ -18,7 +18,7 @@ - + From e0a7f0280c14e14c366d7ee10a3f705a653877d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Thu, 16 Nov 2023 00:09:46 +0900 Subject: [PATCH 12/29] =?UTF-8?q?InfoRow=E7=AD=89=E3=81=AE=E3=80=8C?= =?UTF-8?q?=E7=B7=AF=E5=BA=A6=E7=B5=8C=E5=BA=A6=E3=81=8C=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E9=A7=85?= =?UTF-8?q?=E3=80=8D=E3=81=AF=E7=84=A1=E8=A6=96=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LonLatLocationService.cs | 91 ++++++++++++++++--- TRViS.LocationService/StaLocationInfo.cs | 39 +++++++- 2 files changed, 112 insertions(+), 18 deletions(-) diff --git a/TRViS.LocationService/LonLatLocationService.cs b/TRViS.LocationService/LonLatLocationService.cs index b8a0f532..899d72de 100644 --- a/TRViS.LocationService/LonLatLocationService.cs +++ b/TRViS.LocationService/LonLatLocationService.cs @@ -34,7 +34,7 @@ public void ResetLocationInfo() => ResetLocationInfo(true); void ResetLocationInfo(bool invokeEvent) { - CurrentStationIndex = StaLocationInfo is null ? CURRENT_STATION_INDEX_NOT_SET : 0; + CurrentStationIndex = GetNextStationIndex(StaLocationInfo ?? Array.Empty(), CURRENT_STATION_INDEX_NOT_SET); IsRunningToNextStation = false; DistanceHistoryQueue.Clear(); @@ -44,25 +44,67 @@ void ResetLocationInfo(bool invokeEvent) } } + static int GetPastStationIndex(in StaLocationInfo[] staLocationInfo, int currentStationIndex) + { + for (int i = currentStationIndex - 1; i >= 0; i--) + { + if (staLocationInfo[i].HasLonLatLocation) + return i; + } + + return CURRENT_STATION_INDEX_NOT_SET; + } + static int GetNextStationIndex(in StaLocationInfo[] staLocationInfo, int currentStationIndex) + { + for (int i = currentStationIndex + 1; i < staLocationInfo.Length; i++) + { + if (staLocationInfo[i].HasLonLatLocation) + return i; + } + + return CURRENT_STATION_INDEX_NOT_SET; + } public void ForceSetLocationInfo(double lon_deg, double lat_deg) { ResetLocationInfo(false); if (StaLocationInfo is null) + { + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); return; + } + CurrentStationIndex = CURRENT_STATION_INDEX_NOT_SET; if (StaLocationInfo.Length <= 1) { - CurrentStationIndex = StaLocationInfo.Length - 1; - IsRunningToNextStation = false; + if (StaLocationInfo.Length == 1 && StaLocationInfo[0].HasLonLatLocation) + { + CurrentStationIndex = 0; + } + + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); return; } - double[] distanceArray = StaLocationInfo.Select(v => Utils.CalculateDistance_m(lon_deg, lat_deg, v.Location_lon_deg, v.Location_lat_deg)).ToArray(); + double[] distanceArray = StaLocationInfo.Select( + v => + v.HasLonLatLocation + ? Utils.CalculateDistance_m(lon_deg, lat_deg, v.Location_lon_deg, v.Location_lat_deg) + : double.NaN + ).ToArray(); - int nearestStationIndex = -1; + int nearestStationIndex = CURRENT_STATION_INDEX_NOT_SET; + int firstStationIndex = CURRENT_STATION_INDEX_NOT_SET; + int lastStationIndex = CURRENT_STATION_INDEX_NOT_SET; double nearestDistance = double.MaxValue; for (int i = 0; i < distanceArray.Length; i++) { + if (double.IsNaN(distanceArray[i])) + continue; + + if (firstStationIndex < 0) + firstStationIndex = i; + lastStationIndex = i; + if (distanceArray[i] < nearestDistance) { nearestStationIndex = i; @@ -70,13 +112,29 @@ public void ForceSetLocationInfo(double lon_deg, double lat_deg) } } - if (nearestStationIndex == 0) + // 全ての駅で位置情報が設定されていない場合 + if (nearestStationIndex < 0) + { + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + return; + } + + // 有効な駅が1つしかない場合 + if (firstStationIndex == lastStationIndex) + { + CurrentStationIndex = firstStationIndex; + IsRunningToNextStation = false; + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + return; + } + + if (nearestStationIndex == firstStationIndex) { // 最初の駅が一番近い場合 - CurrentStationIndex = 0; + CurrentStationIndex = firstStationIndex; IsRunningToNextStation = Utils.IsLeaved(StaLocationInfo[nearestStationIndex], distanceArray[nearestStationIndex]); } - else if (nearestStationIndex == StaLocationInfo.Length - 1) + else if (nearestStationIndex == lastStationIndex) { // 最後の駅が一番近い場合 if (Utils.IsNearBy(StaLocationInfo[nearestStationIndex], distanceArray[nearestStationIndex])) @@ -86,7 +144,7 @@ public void ForceSetLocationInfo(double lon_deg, double lat_deg) } else { - CurrentStationIndex = nearestStationIndex - 1; + CurrentStationIndex = GetPastStationIndex(StaLocationInfo, nearestStationIndex); IsRunningToNextStation = true; } } @@ -102,10 +160,12 @@ public void ForceSetLocationInfo(double lon_deg, double lat_deg) { IsRunningToNextStation = true; CurrentStationIndex = nearestStationIndex; + int pastStationIndex = GetPastStationIndex(StaLocationInfo, nearestStationIndex); + int nextStationIndex = GetNextStationIndex(StaLocationInfo, nearestStationIndex); // 次の駅よりも前の駅の方が近い場合、おそらく前の駅からこの駅に向かっているところである - if (distanceArray[nearestStationIndex - 1] < distanceArray[nearestStationIndex + 1]) + if (distanceArray[pastStationIndex] < distanceArray[nextStationIndex]) { - CurrentStationIndex = nearestStationIndex - 1; + CurrentStationIndex = pastStationIndex; } } } @@ -134,19 +194,22 @@ public void SetCurrentLocation(double lon_deg, double lat_deg) if (IsRunningToNextStation) { - StaLocationInfo nextStation = StaLocationInfo[CurrentStationIndex + 1]; + // LastStationであれば、RunningToNextStationはfalseであるはずである。 + // -> 次の駅は必ず存在する + int nextStationIndex = GetNextStationIndex(StaLocationInfo, CurrentStationIndex); + StaLocationInfo nextStation = StaLocationInfo[nextStationIndex]; double distanceToNextStationAverage = GetDistanceToStationAverage(nextStation, lon_deg, lat_deg); if (!double.IsNaN(distanceToNextStationAverage) && Utils.IsNearBy(nextStation, distanceToNextStationAverage)) { DistanceHistoryQueue.Clear(); - CurrentStationIndex++; + CurrentStationIndex = nextStationIndex; IsRunningToNextStation = false; LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); } } - else if (CurrentStationIndex < StaLocationInfo.Length - 1) + else if (0 <= GetNextStationIndex(StaLocationInfo, CurrentStationIndex)) { StaLocationInfo currentStation = StaLocationInfo[CurrentStationIndex]; diff --git a/TRViS.LocationService/StaLocationInfo.cs b/TRViS.LocationService/StaLocationInfo.cs index 23a9b164..4ffe2305 100644 --- a/TRViS.LocationService/StaLocationInfo.cs +++ b/TRViS.LocationService/StaLocationInfo.cs @@ -2,23 +2,54 @@ namespace TRViS.Services; public interface ILocationLonLat_deg { + bool HasLonLatLocation { get; } double Location_lon_deg { get; } double Location_lat_deg { get; } } public class StaLocationInfo : ILocationLonLat_deg { + public const double DefaultNearbyRadius_m = 200; + + public bool HasLonLatLocation { get; } public double Location_m { get; } public double Location_lon_deg { get; } public double Location_lat_deg { get; } public double NearbyRadius_m { get; } - public StaLocationInfo(double location_m, double location_lon_deg, double location_lat_deg, double nearbyRadius_m) + public StaLocationInfo( + double location_m, + double? location_lon_deg, + double? location_lat_deg, + double? nearbyRadius_m + ) { Location_m = location_m; - Location_lon_deg = location_lon_deg; - Location_lat_deg = location_lat_deg; - NearbyRadius_m = nearbyRadius_m; + NearbyRadius_m = nearbyRadius_m ?? DefaultNearbyRadius_m; + if (location_lon_deg is double lon && location_lat_deg is double lat) + { + Location_lon_deg = lon; + Location_lat_deg = lat; + HasLonLatLocation = true; + } + else + { + Location_lon_deg = 0; + Location_lat_deg = 0; + HasLonLatLocation = false; + } + } + + public StaLocationInfo( + double location_m, + double? nearbyRadius_m + ) : this( + location_m, + null, + null, + nearbyRadius_m + ) + { } public bool Equals(StaLocationInfo? other) From f9c06f0bbd58615e5fe5239f1c115b12f94a55db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Thu, 16 Nov 2023 02:02:08 +0900 Subject: [PATCH 13/29] add ref to LocationService project --- TRViS/TRViS.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/TRViS/TRViS.csproj b/TRViS/TRViS.csproj index ce007f04..5782321f 100644 --- a/TRViS/TRViS.csproj +++ b/TRViS/TRViS.csproj @@ -79,6 +79,7 @@ + From bdff465b7867f3de18aff1427f48b714f7e2a425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Thu, 16 Nov 2023 02:03:04 +0900 Subject: [PATCH 14/29] =?UTF-8?q?LocationService=E3=81=AE=E5=88=A4?= =?UTF-8?q?=E5=AE=9A=E3=83=AD=E3=82=B8=E3=83=83=E3=82=AF=E3=82=92=E3=83=96?= =?UTF-8?q?=E3=83=AD=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88=E5=88=86=E9=9B=A2?= =?UTF-8?q?=E3=81=97=E3=81=9F=E3=81=9F=E3=82=81=E3=80=81=E6=9C=AC=E4=BD=93?= =?UTF-8?q?=E5=81=B4=E3=81=AB=E3=81=9D=E3=82=8C=E3=82=92=E5=8F=8D=E6=98=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/DTAC/PageHeader.cs | 6 + TRViS/DTAC/VerticalStylePage.xaml.cs | 9 +- TRViS/DTAC/VerticalTimetableView.Init.cs | 3 +- .../VerticalTimetableView.LocationService.cs | 87 +++---- TRViS/DTAC/VerticalTimetableView.cs | 4 +- TRViS/Services/LocationService.cs | 219 +++++++----------- 6 files changed, 128 insertions(+), 200 deletions(-) diff --git a/TRViS/DTAC/PageHeader.cs b/TRViS/DTAC/PageHeader.cs index 42339c0b..be1278cd 100644 --- a/TRViS/DTAC/PageHeader.cs +++ b/TRViS/DTAC/PageHeader.cs @@ -45,6 +45,12 @@ public string AffectDateLabelText #region Start / End Run Button readonly StartEndRunButton StartEndRunButton = new(); + public event EventHandler>? IsRunningChanged + { + add => StartEndRunButton.IsCheckedChanged += value; + remove => StartEndRunButton.IsCheckedChanged -= value; + } + partial void OnIsRunningChanged(bool newValue) { logger.Info("IsRunning: {0}", newValue); diff --git a/TRViS/DTAC/VerticalStylePage.xaml.cs b/TRViS/DTAC/VerticalStylePage.xaml.cs index 5b3e0fec..77c4bf8b 100644 --- a/TRViS/DTAC/VerticalStylePage.xaml.cs +++ b/TRViS/DTAC/VerticalStylePage.xaml.cs @@ -102,11 +102,10 @@ public VerticalStylePage() TimetableView.IgnoreSafeArea = false; TimetableView.VerticalOptions = LayoutOptions.Start; - TimetableView.SetBinding(VerticalTimetableView.IsRunStartedProperty, new Binding() - { - Source = this.PageHeaderArea, - Path = nameof(PageHeader.IsRunning) - }); + PageHeaderArea.IsRunningChanged += (_, e) => { + logger.Info("IsRunningChanged: {0}", e.NewValue); + TimetableView.IsRunStarted = e.NewValue; + }; TimetableView.ScrollRequested += VerticalTimetableView_ScrollRequested; diff --git a/TRViS/DTAC/VerticalTimetableView.Init.cs b/TRViS/DTAC/VerticalTimetableView.Init.cs index c28f4fde..504798ac 100644 --- a/TRViS/DTAC/VerticalTimetableView.Init.cs +++ b/TRViS/DTAC/VerticalTimetableView.Init.cs @@ -2,6 +2,7 @@ using TRViS.Controls; using TRViS.IO.Models; +using TRViS.Services; namespace TRViS.DTAC; @@ -44,7 +45,7 @@ public VerticalTimetableView() ColumnDefinitions = DTACElementStyles.TimetableColumnWidthCollection; Grid.SetColumnSpan(CurrentLocationLine, 8); - LocationService.IsNearbyChanged += LocationService_IsNearbyChanged; + LocationService.LocationStateChanged += LocationService_LocationStateChanged; LocationService.ExceptionThrown += (s, e) => { MainThread.BeginInvokeOnMainThread(() => Shell.Current.DisplayAlert("Location Service Error", e.ToString(), "OK")); diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index 6cc19388..7f4ed3bc 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -14,81 +14,46 @@ public partial class VerticalTimetableView : Grid public event EventHandler>? IsLocationServiceEnabledChanged; partial void OnIsLocationServiceEnabledChanged(bool newValue) { - if (newValue) - { - logger.Info("IsLocationServiceEnabled is changed to true -> set NearbyCheckInfo"); - SetNearbyCheckInfo(CurrentRunningRow); - } - else - { - logger.Info("IsLocationServiceEnabled is changed to false"); - } + logger.Info("IsLocationServiceEnabled is changed to {0}", newValue); LocationService.IsEnabled = newValue; IsLocationServiceEnabledChanged?.Invoke(this, new(!newValue, newValue)); } - private void LocationService_IsNearbyChanged(object? sender, bool oldValue, bool newValue) + private void LocationService_LocationStateChanged(object? sender, LocationStateChangedEventArgs e) { - if (!IsRunStarted || !IsEnabled || CurrentRunningRow is null || !LocationService.IsEnabled) + if (!IsLocationServiceEnabled) { - logger.Info( - "!IsRunStarted: {0} || " - + "!IsEnabled: {1} || " - + "CurrentRunningRow is null: {2} || " - + "!LocationService.IsEnabled: {3}" - + "-> do nothing", - IsRunStarted, - IsEnabled, - CurrentRunningRow is null, - LocationService.IsEnabled - ); - + logger.Debug("IsLocationServiceEnabled is false -> Do nothing"); return; } - - if (newValue) + if (e.NewStationIndex < 0) { - logger.Info("IsNearby is changed to true (= Around Current Station) -> set CurrentRunningRow to NextRunningRow({0})", NextRunningRow?.RowIndex ?? -1); - SetCurrentRunningRow(NextRunningRow); + logger.Warn("e.NewStationIndex is less than 0 -> Disable LocationService"); + IsLocationServiceEnabled = false; + return; } - else if (CurrentRunningRow is not null) + if (RowViewList.Count <= e.NewStationIndex) { - logger.Info("IsNearby is changed to false (= Running to next station)" - + " -> set CurrentRunningRow.LocationState to RunningToNextStation and Update NearbyCheckInfo"); - CurrentRunningRow.LocationState = VerticalTimetableRow.LocationStates.RunningToNextStation; - - SetNearbyCheckInfo(NextRunningRow); + logger.Warn("RowViewList.Count is less than e.NewStationIndex -> Disable LocationService"); + IsLocationServiceEnabled = false; + return; } - } - - private void SetNearbyCheckInfo(VerticalTimetableRow? nextRunningRow) - { - if (nextRunningRow?.RowData is TimetableRow nextRowData) - { - LocationService.NearbyCenter - = nextRowData.Location is LocationInfo - { - Latitude_deg: double lat, - Longitude_deg: double lon - } - ? new Location(lat, lon) - : null; - - logger.Info( - "Set NearbyCenter to {0}, Radius: {1}, (Row[{2}].StationName: {3})", - LocationService.NearbyCenter, - nextRowData.Location.OnStationDetectRadius_m, - nextRunningRow.RowIndex, - nextRowData.StationName - ); - LocationService.NearbyRadius_m = nextRowData.Location.OnStationDetectRadius_m ?? LocationService.DefaultNearbyRadius_m; - } - else - { - logger.Debug("nextRunningRow is null or nextRunningRow.RowData is null -> do nothing"); - } + logger.Info("LocationStateChanged: [{0}](State:{1}) Rows[{2}](IsRunningToNextStation: {3})", + CurrentRunningRowIndex, + CurrentRunningRow?.LocationState, + e.NewStationIndex, + e.IsRunningToNextStation + ); + if (CurrentRunningRow is not null) + CurrentRunningRow.LocationState = VerticalTimetableRow.LocationStates.Undefined; + UpdateCurrentRunningLocationVisualizer(RowViewList[e.NewStationIndex], e.IsRunningToNextStation + ? VerticalTimetableRow.LocationStates.RunningToNextStation + : VerticalTimetableRow.LocationStates.AroundThisStation + ); + CurrentRunningRow = RowViewList[e.NewStationIndex]; + CurrentRunningRowIndex = e.NewStationIndex; } public void SetCurrentRunningRow(int index) diff --git a/TRViS/DTAC/VerticalTimetableView.cs b/TRViS/DTAC/VerticalTimetableView.cs index b0260292..a9711ac9 100644 --- a/TRViS/DTAC/VerticalTimetableView.cs +++ b/TRViS/DTAC/VerticalTimetableView.cs @@ -27,6 +27,8 @@ partial void OnSelectedTrainDataChanged(TrainData? newValue) { logger.Trace("SelectedTrainData is changed to {0}", newValue?.TrainNumber); SetRowViews(newValue, newValue?.Rows); + IsRunStarted = false; + LocationService.SetTimetableRows(newValue?.Rows); } partial void OnIsBusyChanged() @@ -81,7 +83,7 @@ private void RowTapped(object? sender, EventArgs e) if (!IsRunStarted || !IsEnabled) { - logger.Debug("IsRunStarted is false or IsEnabled is false -> do nothing"); + logger.Debug("IsRunStarted({0}) is false or IsEnabled({1}) is false -> do nothing", IsRunStarted, IsEnabled); return; } diff --git a/TRViS/Services/LocationService.cs b/TRViS/Services/LocationService.cs index d8f119a2..80dcee64 100644 --- a/TRViS/Services/LocationService.cs +++ b/TRViS/Services/LocationService.cs @@ -1,6 +1,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using TRViS.Controls; +using TRViS.IO.Models; using TRViS.MyAppCustomizables; using TRViS.ViewModels; @@ -23,95 +24,30 @@ public partial class LocationService : ObservableObject, IDisposable [ObservableProperty] bool _IsEnabled; - [ObservableProperty] - Location? _NearbyCenter; - - [ObservableProperty] - double _NearbyRadius_m = DefaultNearbyRadius_m; - public const double DefaultNearbyRadius_m = 200; + readonly LonLatLocationService LonLatLocationService; - bool _IsNearby; - public bool IsNearby + public event EventHandler LocationStateChanged { - get => _IsNearby; - private set - { - if (_IsNearby == value) - return; - - logger.Debug("IsNearby is changed to {0}", value); - this.OnPropertyChanging(nameof(IsNearby)); - _IsNearby = value; - this.OnPropertyChanged(nameof(IsNearby)); - IsNearbyChanged?.Invoke(this, !value, value); - } + add => LonLatLocationService.LocationStateChanged += value; + remove => LonLatLocationService.LocationStateChanged -= value; } - Location? _LastLocation; - public Location? LastLocation - { - get => _LastLocation; - - private set - { - if ( - value == _LastLocation - || (_LastLocation is not null && value?.Equals(_LastLocation) != false) - ) - { - logger.Trace("LastLocation is already {0}, so skipping...", value); - return; - } - - logger.Info("LastLocation is changing to {0}", value); - this.OnPropertyChanging(nameof(LastLocation)); - - setIsNearby(value); + public const double DefaultNearbyRadius_m = 200; - Location? lastLocation = _LastLocation; - _LastLocation = value; + public event EventHandler? ExceptionThrown; - this.OnPropertyChanged(nameof(LastLocation)); - LastLocationChanged?.Invoke(this, lastLocation, value); - } - } + CancellationTokenSource? gpsCancelation; - void setIsNearby(in Location? location) + public LocationService() { - if (NearbyCenter is null || location is null) - { - logger.Trace("NearbyCenter is null or location is null -> do nothing"); - return; - } - - double distance = location.CalculateDistance(NearbyCenter, DistanceUnits.Kilometers) * 1000; + logger.Trace("Creating..."); - bool isNearby = distance <= NearbyRadius_m; - logger.Info("IsNearby: {0} (= distance: {1} <= NearbyRadius_m: {2})", isNearby, distance, NearbyRadius_m); - logger.Debug("Station Lon:{4:F5}, Lat:{5:F5}\tCurrent Lon:{0:F5}, Lat:{1:F5}", - NearbyCenter.Longitude, - NearbyCenter.Latitude, - location.Longitude, - location.Latitude - ); + IsEnabled = false; + LonLatLocationService = new(); - LogView.Add( - LogView.Priority.Info, - - $"setIsNearby() Lon:{location.Longitude:F5}, Lat:{location.Latitude:F5}" - + $" (Distance:{distance:F2}m/{NearbyRadius_m:F2}m from Lon:{NearbyCenter.Longitude:F5}, Lat:{NearbyCenter.Latitude:F5} -> IsNearBy:{isNearby})" - ); - IsNearby = isNearby; + logger.Debug("LocationService is created"); } - public event EventHandler? ExceptionThrown; - public event ValueChangedEventHandler? IsNearbyChanged; - public event ValueChangedEventHandler? LastLocationChanged; - - CancellationTokenSource? gpsCancelation; - - private bool disposedValue; - partial void OnIsEnabledChanged(bool newValue) { // GPS停止 @@ -127,17 +63,12 @@ partial void OnIsEnabledChanged(bool newValue) } } - partial void OnNearbyCenterChanged(Location? newValue) + public void SetTimetableRows(TimetableRow[]? timetableRows) { - if (LastLocation is null || newValue is null) - { - logger.Trace("LastLocation is null or newValue is null -> do nothing"); - return; - } + logger.Trace("Setting TimetableRows..."); - logger.Info("NearbyCenter is changed to {0}", newValue); - IsNearby = false; - setIsNearby(LastLocation); + IsEnabled = false; + LonLatLocationService.StaLocationInfo = timetableRows?.Select(v => new StaLocationInfo(v.Location.Location_m, v.Location.Longitude_deg, v.Location.Latitude_deg, v.Location.OnStationDetectRadius_m)).ToArray(); } static EasterEggPageViewModel EasterEggPageViewModel { get; } = InstanceManager.EasterEggPageViewModel; @@ -171,69 +102,93 @@ public Task StartGPS() } gpsCancelation = new CancellationTokenSource(); - CancellationToken token = gpsCancelation.Token; - LastLocation = null; - _IsNearby = true; - return Task.Run(async () => - { - // ref: https://docs.microsoft.com/en-us/dotnet/maui/platform-integration/device/geolocation - // accuracy: 30m - 500m - GeolocationRequest req = new(GeolocationAccuracy.Default, Interval); - logger.Info("Starting Location Service... (Interval: {0})", Interval); - - LogView.Add("Location Service Starting..."); - while (!token.IsCancellationRequested) - { - logger.Trace("Location Service Loop"); - TimeSpan timeout = Interval; - req.Timeout = timeout; - - await Task.WhenAll(new Task[] - { - CheckAndNotifyCurrentLocation(req, token), - Task.Delay(timeout, token), - }); - } - - logger.Info("Location Service Ended"); - LogView.Add("Location Service Ended"); - }, token); + return Task.Run(PositioningTask, gpsCancelation.Token); } - async Task CheckAndNotifyCurrentLocation(GeolocationRequest req, CancellationToken token) + async Task PositioningTask() { - logger.Trace("Starting..."); + // ref: https://docs.microsoft.com/en-us/dotnet/maui/platform-integration/device/geolocation + // accuracy: 30m - 500m + GeolocationRequest req = new(GeolocationAccuracy.Default, Interval); + logger.Info("Starting Location Service... (Interval: {0})", Interval); - try + if (gpsCancelation?.Token is not CancellationToken token) { - Location? loc = await Geolocation.Default.GetLocationAsync(req, token); + logger.Warn("gpsCancelation is null -> do nothing"); + return; + } + + LogView.Add("Location Service Starting..."); + bool isFirst = true; + while (!token.IsCancellationRequested) + { + logger.Trace("Location Service Loop"); + DateTime executeStartTime = DateTime.Now; + TimeSpan timeout = Interval; + req.Timeout = timeout; + + Location? loc = null; + + try + { + loc = await Geolocation.Default.GetLocationAsync(req, token); + } + catch (Exception ex) + { + logger.Error(ex, "GetLocationAsync failed"); + IsEnabled = false; + gpsCancelation?.Cancel(); + LogView.Add(LogView.Priority.Error, "GetLocationAsync failed:" + ex.ToString()); + + if (ExceptionThrown is null) + throw; + else + ExceptionThrown.Invoke(this, ex); + } if (loc is not null) { - logger.Debug("CurrentLocation is {0}", loc); - LastLocation = loc; + if (isFirst) + { + logger.Info("Location Service First Positioning"); + LogView.Add("Location Service Started"); + isFirst = false; + LonLatLocationService.ForceSetLocationInfo(loc.Longitude, loc.Latitude); + } + else + { + LonLatLocationService.SetCurrentLocation(loc.Longitude, loc.Latitude); + } + logger.Trace("Location Service Positioning Success (lon: {0}, lat: {1})", loc.Longitude, loc.Latitude); } else { - logger.Warn("CurrentLocation is null"); - LogView.Add("CurrentLocation is UNKNOWN (value was null)"); + logger.Warn("Location Service Positioning Failed"); + LogView.Add("Location Service Positioning Failed"); } - } - catch (Exception ex) - { - logger.Error(ex, "GetLocationAsync failed"); - IsEnabled = false; - gpsCancelation?.Cancel(); - System.Diagnostics.Debug.WriteLine(ex); - LogView.Add(LogView.Priority.Error, "GetLocationAsync failed:" + ex.ToString()); - if (ExceptionThrown is null) - throw; + if (token.IsCancellationRequested) + { + logger.Debug("gpsCancelation is requested -> break"); + break; + } + DateTime executeEndTime = DateTime.Now; + if (executeEndTime < (executeStartTime + timeout)) + { + logger.Trace("Location Service Positioning Took {0}", executeEndTime - executeStartTime); + await Task.Delay(timeout - (executeEndTime - executeStartTime), token); + } else - ExceptionThrown.Invoke(this, ex); + { + logger.Warn("Location Service Positioning Took Too Long (time: {0})", executeEndTime - executeStartTime); + } } + + logger.Info("Location Service Ended"); + LogView.Add("Location Service Ended"); } + private bool disposedValue; protected virtual void Dispose(bool disposing) { From 718461be8bce869bb58b7ce5fe80e66cdeb06df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Thu, 16 Nov 2023 22:34:31 +0900 Subject: [PATCH 15/29] =?UTF-8?q?=E3=83=A1=E3=82=A4=E3=83=B3=E3=82=B9?= =?UTF-8?q?=E3=83=AC=E3=83=83=E3=83=89=E4=BB=A5=E5=A4=96=E3=81=A7UI?= =?UTF-8?q?=E3=82=92=E8=A7=A6=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E3=83=9F?= =?UTF-8?q?=E3=82=B9=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/DTAC/LocationServiceButton.cs | 7 +++++++ TRViS/DTAC/VerticalTimetableView.LocationService.cs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/TRViS/DTAC/LocationServiceButton.cs b/TRViS/DTAC/LocationServiceButton.cs index c99e69e7..f502a001 100644 --- a/TRViS/DTAC/LocationServiceButton.cs +++ b/TRViS/DTAC/LocationServiceButton.cs @@ -131,6 +131,13 @@ void OnIsCheckedChanged(object? sender, ValueChangedEventArgs e) void OnIsCheckedChanged(bool isLocationServiceEnabled) { + if (!MainThread.IsMainThread) + { + logger.Debug("MainThread is not current thread -> invoke OnIsCheckedChanged on MainThread"); + MainThread.BeginInvokeOnMainThread(() => OnIsCheckedChanged(isLocationServiceEnabled)); + return; + } + if (isLocationServiceEnabled) { logger.Info("Location Service is enabled"); diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index 7f4ed3bc..a8cb3f60 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -124,6 +124,13 @@ void SetCurrentRunningRow(int index, VerticalTimetableRow? value) void UpdateCurrentRunningLocationVisualizer(VerticalTimetableRow row, VerticalTimetableRow.LocationStates states) { + if (!MainThread.IsMainThread) + { + logger.Debug("MainThread is not current thread -> invoke UpdateCurrentRunningLocationVisualizer on MainThread"); + MainThread.BeginInvokeOnMainThread(() => UpdateCurrentRunningLocationVisualizer(row, states)); + return; + } + logger.Info("UpdateCurrentRunningLocationVisualizer: {0} ... {1}", row.RowIndex, states); row.LocationState = states; From 4eeba60dc5878d1c647181556013bb8b1308ef5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Thu, 16 Nov 2023 22:34:49 +0900 Subject: [PATCH 16/29] =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E6=83=85=E5=A0=B1?= =?UTF-8?q?=E3=81=AE=E3=83=91=E3=83=BC=E3=83=9F=E3=83=83=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=82=92=E6=AF=8E=E5=BA=A6=E7=A2=BA=E8=AA=8D=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/Services/LocationService.cs | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/TRViS/Services/LocationService.cs b/TRViS/Services/LocationService.cs index 80dcee64..cae45c3d 100644 --- a/TRViS/Services/LocationService.cs +++ b/TRViS/Services/LocationService.cs @@ -106,6 +106,7 @@ public Task StartGPS() return Task.Run(PositioningTask, gpsCancelation.Token); } + static Permissions.LocationWhenInUse LocationWhenInUsePermission { get; } = new(); async Task PositioningTask() { // ref: https://docs.microsoft.com/en-us/dotnet/maui/platform-integration/device/geolocation @@ -128,6 +129,42 @@ async Task PositioningTask() TimeSpan timeout = Interval; req.Timeout = timeout; + PermissionStatus permissionStatus = await LocationWhenInUsePermission.CheckStatusAsync(); + logger.Trace("Location Service Current Permission Status: {0}", permissionStatus); + if (permissionStatus != PermissionStatus.Granted) + { + try + { + + permissionStatus = await MainThread.InvokeOnMainThreadAsync(LocationWhenInUsePermission.RequestAsync); + logger.Trace("Location Service Requested Permission Status: {0}", permissionStatus); + } + catch (Exception ex) + { + logger.Error(ex, "Location Service Request Permission Failed"); + IsEnabled = false; + gpsCancelation?.Cancel(); + LogView.Add(LogView.Priority.Error, "Location Service Request Permission Failed:" + ex.ToString()); + + if (ExceptionThrown is null) + throw; + else + ExceptionThrown.Invoke(this, ex); + return; + } + } + switch (permissionStatus) + { + case PermissionStatus.Disabled: + case PermissionStatus.Denied: + case PermissionStatus.Unknown: + logger.Error("Location Service Permission Disabled, Denied or Unknown state"); + IsEnabled = false; + gpsCancelation?.Cancel(); + ExceptionThrown?.Invoke(this, new Exception("Location Service Permission Disabled, Denied or Unknown state")); + return; + } + logger.Trace("Location Service Permission Granted"); Location? loc = null; try @@ -145,6 +182,7 @@ async Task PositioningTask() throw; else ExceptionThrown.Invoke(this, ex); + return; } if (loc is not null) From 6971347e61cd6aca8722d0d9d36b168e818b37ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Thu, 16 Nov 2023 22:35:29 +0900 Subject: [PATCH 17/29] =?UTF-8?q?=E5=88=97=E8=BB=8A=E3=83=87=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E5=A4=89=E6=9B=B4=E5=BE=8C=E3=81=AB=E3=83=9C=E3=82=BF?= =?UTF-8?q?=E3=83=B3=E3=81=AE=E3=80=8C=E9=81=8B=E8=BB=A2=E9=96=8B=E5=A7=8B?= =?UTF-8?q?=E3=80=8D=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92=E3=81=8D=E3=81=A1?= =?UTF-8?q?=E3=82=93=E3=81=A8=E6=88=BB=E3=81=99=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/DTAC/VerticalStylePage.xaml.cs | 1 + TRViS/DTAC/VerticalTimetableView.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/TRViS/DTAC/VerticalStylePage.xaml.cs b/TRViS/DTAC/VerticalStylePage.xaml.cs index 77c4bf8b..a8f9c950 100644 --- a/TRViS/DTAC/VerticalStylePage.xaml.cs +++ b/TRViS/DTAC/VerticalStylePage.xaml.cs @@ -154,6 +154,7 @@ partial void OnSelectedTrainDataChanged(TrainData? newValue) logger.Info("SelectedTrainDataChanged: {0}", newValue); BindingContext = newValue; TimetableView.SelectedTrainData = newValue; + PageHeaderArea.IsRunning = false; TrainInfo_BeforeDepartureArea.TrainInfoText = newValue?.TrainInfo ?? ""; TrainInfo_BeforeDepartureArea.BeforeDepartureText = newValue?.BeforeDeparture ?? ""; diff --git a/TRViS/DTAC/VerticalTimetableView.cs b/TRViS/DTAC/VerticalTimetableView.cs index a9711ac9..f1e8464a 100644 --- a/TRViS/DTAC/VerticalTimetableView.cs +++ b/TRViS/DTAC/VerticalTimetableView.cs @@ -29,6 +29,7 @@ partial void OnSelectedTrainDataChanged(TrainData? newValue) SetRowViews(newValue, newValue?.Rows); IsRunStarted = false; LocationService.SetTimetableRows(newValue?.Rows); + ScrollRequested?.Invoke(this, new(0)); } partial void OnIsBusyChanged() From 85988c268bdbfe9c0e004e990d17e81d475c567c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 11:01:00 +0900 Subject: [PATCH 18/29] =?UTF-8?q?ForceSetLocationInfo=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LonLatLocationService.Tests.cs | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs b/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs index 5f973d3f..6bcef3d3 100644 --- a/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs +++ b/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs @@ -99,4 +99,100 @@ public void MoveTest() Assert.That(service.IsRunningToNextStation, Is.False); }); } + + [Test] + public void ForceSetPositionTest_NearStation() + { + StaLocationInfo sta1 = new(0, 0, 0, 200); + StaLocationInfo sta2 = new(1, 1, 1, 200); + StaLocationInfo sta3 = new(2, 2, 2, 200); + LonLatLocationService service = new() + { + StaLocationInfo = + [ + sta1, + sta2, + sta3, + ] + }; + + // 初期状態は、駅0にいる + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + + service.ForceSetLocationInfo(1, 1); + + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(1)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + } + + [Test] + public void ForceSetPositionTest_RunningToNextStation1() + { + StaLocationInfo sta1 = new(0, 0, 0, 200); + StaLocationInfo sta2 = new(1, 1, 1, 200); + StaLocationInfo sta3 = new(2, 2, 2, 200); + LonLatLocationService service = new() + { + StaLocationInfo = + [ + sta1, + sta2, + sta3, + ] + }; + + // 初期状態は、駅0にいる + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + + service.ForceSetLocationInfo(0.5, 0.5); + + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.True); + }); + } + + [Test] + public void ForceSetPositionTest_RunningToNextStation2() + { + StaLocationInfo sta1 = new(0, 0, 0, 200); + StaLocationInfo sta2 = new(1, 1, 1, 200); + StaLocationInfo sta3 = new(2, 2, 2, 200); + LonLatLocationService service = new() + { + StaLocationInfo = + [ + sta1, + sta2, + sta3, + ] + }; + + // 初期状態は、駅0にいる + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); + + service.ForceSetLocationInfo(1.5, 1.5); + + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(1)); + Assert.That(service.IsRunningToNextStation, Is.True); + }); + } } From b238ff27158728cb2067977a745b43655a46bd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 11:09:01 +0900 Subject: [PATCH 19/29] =?UTF-8?q?=E3=83=AD=E3=82=B0=E5=87=BA=E5=8A=9B?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/Services/LocationService.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/TRViS/Services/LocationService.cs b/TRViS/Services/LocationService.cs index cae45c3d..7663b1ad 100644 --- a/TRViS/Services/LocationService.cs +++ b/TRViS/Services/LocationService.cs @@ -45,6 +45,11 @@ public LocationService() IsEnabled = false; LonLatLocationService = new(); + LocationStateChanged += (sender, e) => + { + LogView.Add($"LocationStateChanged: Station[{e.NewStationIndex}]@({LonLatLocationService.StaLocationInfo?[e.NewStationIndex].Location_lon_deg}, {LonLatLocationService.StaLocationInfo?[e.NewStationIndex].Location_lat_deg} & Radius:{LonLatLocationService.StaLocationInfo?[e.NewStationIndex].NearbyRadius_m}) IsRunningToNextStation:{e.IsRunningToNextStation}"); + }; + logger.Debug("LocationService is created"); } @@ -190,13 +195,14 @@ async Task PositioningTask() if (isFirst) { logger.Info("Location Service First Positioning"); - LogView.Add("Location Service Started"); + LogView.Add($"Location Service Started with lonlat: ({loc.Longitude}, {loc.Latitude})"); isFirst = false; LonLatLocationService.ForceSetLocationInfo(loc.Longitude, loc.Latitude); } else { LonLatLocationService.SetCurrentLocation(loc.Longitude, loc.Latitude); + LogView.Add($"lonlat: ({loc.Longitude}, {loc.Latitude})"); } logger.Trace("Location Service Positioning Success (lon: {0}, lat: {1})", loc.Longitude, loc.Latitude); } From ede799685b7120e9777e312748eeb4924a626c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 12:56:10 +0900 Subject: [PATCH 20/29] =?UTF-8?q?=E3=83=AD=E3=82=B0=E5=87=BA=E5=8A=9B?= =?UTF-8?q?=E3=81=A7NullRef=E3=81=8C=E8=B5=B7=E3=81=8D=E3=82=8B=E3=83=90?= =?UTF-8?q?=E3=82=B0=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 存在しない駅は-1を指定するという仕様を忘れてた --- TRViS/Services/LocationService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TRViS/Services/LocationService.cs b/TRViS/Services/LocationService.cs index 6fe07b52..32b53979 100644 --- a/TRViS/Services/LocationService.cs +++ b/TRViS/Services/LocationService.cs @@ -47,7 +47,8 @@ public LocationService() LocationStateChanged += (sender, e) => { - LogView.Add($"LocationStateChanged: Station[{e.NewStationIndex}]@({LonLatLocationService.StaLocationInfo?[e.NewStationIndex].Location_lon_deg}, {LonLatLocationService.StaLocationInfo?[e.NewStationIndex].Location_lat_deg} & Radius:{LonLatLocationService.StaLocationInfo?[e.NewStationIndex].NearbyRadius_m}) IsRunningToNextStation:{e.IsRunningToNextStation}"); + StaLocationInfo? newStaLocationInfo = LonLatLocationService.StaLocationInfo?.ElementAtOrDefault(e.NewStationIndex); + LogView.Add($"LocationStateChanged: Station[{e.NewStationIndex}]@({newStaLocationInfo?.Location_lon_deg}, {newStaLocationInfo?.Location_lat_deg} & Radius:{newStaLocationInfo?.NearbyRadius_m}) IsRunningToNextStation:{e.IsRunningToNextStation}"); }; logger.Debug("LocationService is created"); From 06d98ee67a14adf5a28964e17f476f71620dee3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 12:56:27 +0900 Subject: [PATCH 21/29] =?UTF-8?q?=E9=A7=85=E3=81=8C=E9=80=B2=E3=82=80?= =?UTF-8?q?=E3=81=A8=E3=81=8D=E3=81=ABHaptic=20Feedback=E3=82=92=E5=87=BA?= =?UTF-8?q?=E3=81=99=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VerticalTimetableView.LocationService.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index a8cb3f60..87c7100c 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -122,6 +122,7 @@ void SetCurrentRunningRow(int index, VerticalTimetableRow? value) }); } + static bool IsHapticEnabled { get; set; } = true; void UpdateCurrentRunningLocationVisualizer(VerticalTimetableRow row, VerticalTimetableRow.LocationStates states) { if (!MainThread.IsMainThread) @@ -147,5 +148,21 @@ is VerticalTimetableRow.LocationStates.AroundThisStation CurrentLocationBoxView.Margin = row.LocationState is VerticalTimetableRow.LocationStates.RunningToNextStation ? new(0, -(RowHeight.Value / 2)) : new(0); + + try + { + if (IsHapticEnabled) + HapticFeedback.Default.Perform(HapticFeedbackType.Click); + } + catch (FeatureNotSupportedException) + { + logger.Warn("HapticFeedback is not supported"); + IsHapticEnabled = false; + } + catch (Exception ex) + { + logger.Error(ex, "Failed to perform HapticFeedback"); + IsHapticEnabled = false; + } } } From 7b471a8016bf7e3eb9c6b2a8795301cd5cbb80d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 15:13:48 +0900 Subject: [PATCH 22/29] =?UTF-8?q?Row=E3=81=AE=E3=83=80=E3=83=96=E3=83=AB?= =?UTF-8?q?=E3=82=BF=E3=83=83=E3=83=97=E3=81=A7=E5=BC=B7=E5=88=B6=E7=9A=84?= =?UTF-8?q?=E3=81=AB=E7=8F=BE=E5=9C=A8=E9=A7=85=E3=82=92=E3=82=BB=E3=83=83?= =?UTF-8?q?=E3=83=88=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS.LocationService/ILocationService.cs | 2 ++ .../LonLatLocationService.cs | 28 +++++++++++++++++++ TRViS/DTAC/VerticalTimetableView.cs | 9 ++++-- TRViS/Services/LocationService.cs | 13 +++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/TRViS.LocationService/ILocationService.cs b/TRViS.LocationService/ILocationService.cs index 921bfb5f..491e41bc 100644 --- a/TRViS.LocationService/ILocationService.cs +++ b/TRViS.LocationService/ILocationService.cs @@ -49,4 +49,6 @@ public interface ILocationService bool IsRunningToNextStation { get; } void ResetLocationInfo(); + + void ForceSetLocationInfo(int stationIndex, bool isRunningToNextStation); } diff --git a/TRViS.LocationService/LonLatLocationService.cs b/TRViS.LocationService/LonLatLocationService.cs index 899d72de..d17a588f 100644 --- a/TRViS.LocationService/LonLatLocationService.cs +++ b/TRViS.LocationService/LonLatLocationService.cs @@ -173,6 +173,34 @@ public void ForceSetLocationInfo(double lon_deg, double lat_deg) LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); } + public void ForceSetLocationInfo(int stationIndex, bool isRunningToNextStation) + { + ResetLocationInfo(false); + if (StaLocationInfo is null) + { + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + return; + } + + if (stationIndex < 0 || StaLocationInfo.Length <= stationIndex) + { + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + return; + } + + bool isNextStationAvailable = 0 <= GetNextStationIndex(StaLocationInfo, stationIndex); + // 現在駅に位置情報がセットされていない場合、「IsNearby」判定ができないため、次の駅に走行中であると仮定する + // 但し、次の駅が存在しない場合は、次の駅のIsNearby判定ができないため、指定の駅に停車中であると仮定する + IsRunningToNextStation = isNextStationAvailable && isRunningToNextStation; + if (!StaLocationInfo[stationIndex].HasLonLatLocation) + { + IsRunningToNextStation = isNextStationAvailable; + } + + CurrentStationIndex = stationIndex; + LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); + } + double GetDistanceToStationAverage(in StaLocationInfo staLocationInfo, double lon_deg, double lat_deg) { double distanceToStation = Utils.CalculateDistance_m(lon_deg, lat_deg, staLocationInfo.Location_lon_deg, staLocationInfo.Location_lat_deg); diff --git a/TRViS/DTAC/VerticalTimetableView.cs b/TRViS/DTAC/VerticalTimetableView.cs index 7a893c86..b2a66de7 100644 --- a/TRViS/DTAC/VerticalTimetableView.cs +++ b/TRViS/DTAC/VerticalTimetableView.cs @@ -107,10 +107,13 @@ private void RowTapped(object? sender, EventArgs e) logger.Trace("LocationService is not enabled"); } - if (IsLocationServiceEnabled) - logger.Info("Location Service disabled because of double tapping"); _lastTappInfo = null; - IsLocationServiceEnabled = false; + if (IsLocationServiceEnabled) + { + logger.Info("New LocationInfo is set because of double tapping (row:{0})", row.RowIndex); + LocationService.ForceSetLocationInfo(row.RowIndex, false); + return; + } logger.Info("Tapped {0} -> set CurrentRunningRow to {0}", row.RowIndex); switch (row.LocationState) diff --git a/TRViS/Services/LocationService.cs b/TRViS/Services/LocationService.cs index 32b53979..803f5b14 100644 --- a/TRViS/Services/LocationService.cs +++ b/TRViS/Services/LocationService.cs @@ -112,6 +112,19 @@ public Task StartGPS() return Task.Run(PositioningTask, gpsCancelation.Token); } + public void ForceSetLocationInfo(int row, bool isRunningToNextStation) + { + if (!IsEnabled) + { + logger.Debug("IsEnabled is false -> do nothing"); + return; + } + + logger.Debug("ForceSetLocationInfo({0}, {1})", row, isRunningToNextStation); + LonLatLocationService.ForceSetLocationInfo(row, isRunningToNextStation); + logger.Debug("Done"); + } + static Permissions.LocationWhenInUse LocationWhenInUsePermission { get; } = new(); async Task PositioningTask() { From 4c9f153600e60674309c61de38e5ef0b0f6c7bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 15:30:07 +0900 Subject: [PATCH 23/29] =?UTF-8?q?LogView=E3=81=AB=E8=B7=9D=E9=9B=A2?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=82=82=E5=87=BA=E5=8A=9B=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LonLatLocationService.cs | 16 ++++- TRViS.LocationService/StaLocationInfo.cs | 68 ++++++++++++++++++- TRViS/Services/LocationService.cs | 4 +- 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/TRViS.LocationService/LonLatLocationService.cs b/TRViS.LocationService/LonLatLocationService.cs index d17a588f..48ecd100 100644 --- a/TRViS.LocationService/LonLatLocationService.cs +++ b/TRViS.LocationService/LonLatLocationService.cs @@ -215,17 +215,26 @@ double GetDistanceToStationAverage(in StaLocationInfo staLocationInfo, double lo return DistanceHistoryQueue.Average(); } - public void SetCurrentLocation(double lon_deg, double lat_deg) + /// + /// 現在の位置情報を設定し、駅到着・駅出発の判定を行う。 + /// なお、指定回数分の平均距離にて判定を行うため、即時の判定ではない。 + /// + /// 現在の経度 [deg] + /// 現在の経度 [deg] + /// 判定対象の駅までの距離 + public double SetCurrentLocation(double lon_deg, double lat_deg) { if (StaLocationInfo is null || CurrentStationIndex < 0 || StaLocationInfo.Length <= CurrentStationIndex) - return; + return double.NaN; + double distance = double.NaN; if (IsRunningToNextStation) { // LastStationであれば、RunningToNextStationはfalseであるはずである。 // -> 次の駅は必ず存在する int nextStationIndex = GetNextStationIndex(StaLocationInfo, CurrentStationIndex); StaLocationInfo nextStation = StaLocationInfo[nextStationIndex]; + distance = Utils.CalculateDistance_m(nextStation, new LocationLonLat_deg(lon_deg, lat_deg)); double distanceToNextStationAverage = GetDistanceToStationAverage(nextStation, lon_deg, lat_deg); if (!double.IsNaN(distanceToNextStationAverage) @@ -241,6 +250,7 @@ public void SetCurrentLocation(double lon_deg, double lat_deg) { StaLocationInfo currentStation = StaLocationInfo[CurrentStationIndex]; + distance = Utils.CalculateDistance_m(currentStation, new LocationLonLat_deg(lon_deg, lat_deg)); double distanceFromCurrentStationAverage = GetDistanceToStationAverage(currentStation, lon_deg, lat_deg); if (!double.IsNaN(distanceFromCurrentStationAverage) && Utils.IsLeaved(currentStation, distanceFromCurrentStationAverage)) @@ -250,5 +260,7 @@ public void SetCurrentLocation(double lon_deg, double lat_deg) LocationStateChanged?.Invoke(this, new(CurrentStationIndex, IsRunningToNextStation)); } } + + return distance; } } diff --git a/TRViS.LocationService/StaLocationInfo.cs b/TRViS.LocationService/StaLocationInfo.cs index 4ffe2305..7d3cab83 100644 --- a/TRViS.LocationService/StaLocationInfo.cs +++ b/TRViS.LocationService/StaLocationInfo.cs @@ -1,13 +1,75 @@ namespace TRViS.Services; -public interface ILocationLonLat_deg +public interface ILocationLonLat_deg : IEquatable { bool HasLonLatLocation { get; } double Location_lon_deg { get; } double Location_lat_deg { get; } + + bool IEquatable.Equals(ILocationLonLat_deg? other) + { + if (other is null) + return false; + + if (ReferenceEquals(this, other)) + return true; + + return + HasLonLatLocation == other.HasLonLatLocation + && + Location_lon_deg == other.Location_lon_deg + && + Location_lat_deg == other.Location_lat_deg + ; + } } -public class StaLocationInfo : ILocationLonLat_deg +public class LocationLonLat_deg : ILocationLonLat_deg, IEquatable +{ + public bool HasLonLatLocation { get; } + public double Location_lon_deg { get; } + public double Location_lat_deg { get; } + + public LocationLonLat_deg( + double location_lon_deg, + double location_lat_deg + ) + { + Location_lon_deg = location_lon_deg; + Location_lat_deg = location_lat_deg; + HasLonLatLocation = true; + } + + public bool Equals(LocationLonLat_deg? other) + { + if (other is null) + return false; + + if (ReferenceEquals(this, other)) + return true; + + return + ((IEquatable)this).Equals(other) + && + Location_lon_deg == other.Location_lon_deg + && + Location_lat_deg == other.Location_lat_deg + ; + } + + public override bool Equals(object obj) + => Equals(obj as LocationLonLat_deg); + + public override int GetHashCode() + => HashCode.Combine(Location_lon_deg, Location_lat_deg); + + public override string ToString() + { + return $"{nameof(LocationLonLat_deg)} {{ lon:{Location_lon_deg}, lat:{Location_lat_deg} }}"; + } +} + +public class StaLocationInfo : ILocationLonLat_deg, IEquatable { public const double DefaultNearbyRadius_m = 200; @@ -61,6 +123,8 @@ public bool Equals(StaLocationInfo? other) return true; return + ((IEquatable)this).Equals(other) + && Location_m == other.Location_m && Location_lon_deg == other.Location_lon_deg diff --git a/TRViS/Services/LocationService.cs b/TRViS/Services/LocationService.cs index 803f5b14..875cac61 100644 --- a/TRViS/Services/LocationService.cs +++ b/TRViS/Services/LocationService.cs @@ -215,8 +215,8 @@ async Task PositioningTask() } else { - LonLatLocationService.SetCurrentLocation(loc.Longitude, loc.Latitude); - LogView.Add($"lonlat: ({loc.Longitude}, {loc.Latitude})"); + double distance = LonLatLocationService.SetCurrentLocation(loc.Longitude, loc.Latitude); + LogView.Add($"lonlat: ({loc.Longitude}, {loc.Latitude}), distance: {distance}m"); } logger.Trace("Location Service Positioning Success (lon: {0}, lat: {1})", loc.Longitude, loc.Latitude); } From 7e7dba601dc9befa0f435f2ffc210a4898ef7b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:21:50 +0900 Subject: [PATCH 24/29] =?UTF-8?q?ForceLonLat=E3=81=BE=E3=82=8F=E3=82=8A?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 駅をセットしたあと、正常に移動できるか --- .../LonLatLocationService.Tests.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs b/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs index 6bcef3d3..63ace70e 100644 --- a/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs +++ b/TRViS.LocationService.Tests/LonLatLocationService.Tests.cs @@ -162,6 +162,20 @@ public void ForceSetPositionTest_RunningToNextStation1() Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); Assert.That(service.IsRunningToNextStation, Is.True); }); + + service.SetCurrentLocation(1, 1); + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(0)); + Assert.That(service.IsRunningToNextStation, Is.True); + }); + service.SetCurrentLocation(1, 1); + service.SetCurrentLocation(1, 1); + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(1)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); } [Test] @@ -194,5 +208,20 @@ public void ForceSetPositionTest_RunningToNextStation2() Assert.That(service.CurrentStationIndex, Is.EqualTo(1)); Assert.That(service.IsRunningToNextStation, Is.True); }); + + service.SetCurrentLocation(2, 2); + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(1)); + Assert.That(service.IsRunningToNextStation, Is.True); + }); + service.SetCurrentLocation(2, 2); + service.SetCurrentLocation(2, 2); + + Assert.Multiple(() => + { + Assert.That(service.CurrentStationIndex, Is.EqualTo(2)); + Assert.That(service.IsRunningToNextStation, Is.False); + }); } } From 849cb2c431998837620a0e9afb75494e2911e137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:22:09 +0900 Subject: [PATCH 25/29] =?UTF-8?q?=E3=83=AD=E3=82=B0=E5=87=BA=E5=8A=9B?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/DTAC/VerticalTimetableView.LocationService.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index 87c7100c..5ec04936 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -132,8 +132,8 @@ void UpdateCurrentRunningLocationVisualizer(VerticalTimetableRow row, VerticalTi return; } - logger.Info("UpdateCurrentRunningLocationVisualizer: {0} ... {1}", row.RowIndex, states); row.LocationState = states; + logger.Info("UpdateCurrentRunningLocationVisualizer: Row[{0}] ... Requested:{1}, Actual:{2}", row.RowIndex, states, row.LocationState); int rowCount = row.RowIndex; @@ -149,6 +149,8 @@ is VerticalTimetableRow.LocationStates.AroundThisStation is VerticalTimetableRow.LocationStates.RunningToNextStation ? new(0, -(RowHeight.Value / 2)) : new(0); + logger.Debug("CurrentLocationBoxView.IsVisible: {0}, CurrentLocationLine.IsVisible: {1}", CurrentLocationBoxView.IsVisible, CurrentLocationLine.IsVisible); + try { if (IsHapticEnabled) From 8af752f83d7cf6ba060dc9b054b4f160fa6a1475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:22:45 +0900 Subject: [PATCH 26/29] =?UTF-8?q?ForceLonLat=E3=81=A7RunningToNextStation?= =?UTF-8?q?=E3=81=AB=E3=81=AA=E3=82=89=E3=81=AA=E3=81=84=E4=B8=8D=E5=85=B7?= =?UTF-8?q?=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/DTAC/VerticalTimetableView.LocationService.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index 5ec04936..7ac7a0d8 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -48,11 +48,12 @@ private void LocationService_LocationStateChanged(object? sender, LocationStateC ); if (CurrentRunningRow is not null) CurrentRunningRow.LocationState = VerticalTimetableRow.LocationStates.Undefined; - UpdateCurrentRunningLocationVisualizer(RowViewList[e.NewStationIndex], e.IsRunningToNextStation + VerticalTimetableRow rowView = RowViewList[e.NewStationIndex]; + UpdateCurrentRunningLocationVisualizer(rowView, e.IsRunningToNextStation ? VerticalTimetableRow.LocationStates.RunningToNextStation : VerticalTimetableRow.LocationStates.AroundThisStation ); - CurrentRunningRow = RowViewList[e.NewStationIndex]; + _CurrentRunningRow = rowView; CurrentRunningRowIndex = e.NewStationIndex; } From d4f70a2a2d3c28526c362ea0df117ed2d403d0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:29:19 +0900 Subject: [PATCH 27/29] =?UTF-8?q?=E7=8F=BE=E5=9C=A8=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=99=82=E3=81=AB=E3=82=B9=E3=82=AF=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=81=97=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/DTAC/VerticalTimetableView.LocationService.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index 7ac7a0d8..6ff7ff1a 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -55,6 +55,11 @@ private void LocationService_LocationStateChanged(object? sender, LocationStateC ); _CurrentRunningRow = rowView; CurrentRunningRowIndex = e.NewStationIndex; + + if (rowView.LocationState != VerticalTimetableRow.LocationStates.Undefined) + { + ScrollRequested?.Invoke(this, new(Math.Max(rowView.RowIndex - 1, 0) * RowHeight.Value)); + } } public void SetCurrentRunningRow(int index) From 9908288c7fcbd1f4e0b69add82ef004390ccf82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:29:28 +0900 Subject: [PATCH 28/29] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E3=83=97?= =?UTF-8?q?=E3=83=AD=E3=83=91=E3=83=86=E3=82=A3=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TRViS/DTAC/VerticalTimetableView.LocationService.cs | 6 ------ TRViS/DTAC/VerticalTimetableView.cs | 2 -- 2 files changed, 8 deletions(-) diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index 6ff7ff1a..0289eafc 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -119,12 +119,6 @@ void SetCurrentRunningRow(int index, VerticalTimetableRow? value) logger.Debug("value is null -> set CurrentRunningRowIndex to -1"); CurrentRunningRowIndex = -1; } - - NextRunningRow = RowViewList.ElementAtOrDefault(index + 1); - logger.Debug("NextRunningRow is set to {0}: `{1}`", - NextRunningRow?.RowIndex, - NextRunningRow?.RowData.StationName - ); }); } diff --git a/TRViS/DTAC/VerticalTimetableView.cs b/TRViS/DTAC/VerticalTimetableView.cs index b2a66de7..14139ec3 100644 --- a/TRViS/DTAC/VerticalTimetableView.cs +++ b/TRViS/DTAC/VerticalTimetableView.cs @@ -41,8 +41,6 @@ partial void OnIsBusyChanged() int CurrentRunningRowIndex = -1; - VerticalTimetableRow? NextRunningRow = null; - VerticalTimetableRow? _CurrentRunningRow = null; VerticalTimetableRow? CurrentRunningRow { From f7962aaf138126b2607abe1dca1aacf8f17d1509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EF=BC=B4=EF=BC=B2?= <31824852+TetsuOtter@users.noreply.github.com> Date: Fri, 24 Nov 2023 16:43:42 +0900 Subject: [PATCH 29/29] =?UTF-8?q?=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E5=AE=9F=E8=A1=8C=E3=82=92UpdateCurrentRunningLocatio?= =?UTF-8?q?nVisualizer=E5=81=B4=E3=81=AB=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit わざわざ呼び出し元で実行する意味はないため --- .../VerticalTimetableView.LocationService.cs | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/TRViS/DTAC/VerticalTimetableView.LocationService.cs b/TRViS/DTAC/VerticalTimetableView.LocationService.cs index 0289eafc..4229e707 100644 --- a/TRViS/DTAC/VerticalTimetableView.LocationService.cs +++ b/TRViS/DTAC/VerticalTimetableView.LocationService.cs @@ -56,10 +56,7 @@ private void LocationService_LocationStateChanged(object? sender, LocationStateC _CurrentRunningRow = rowView; CurrentRunningRowIndex = e.NewStationIndex; - if (rowView.LocationState != VerticalTimetableRow.LocationStates.Undefined) - { - ScrollRequested?.Invoke(this, new(Math.Max(rowView.RowIndex - 1, 0) * RowHeight.Value)); - } + logger.Debug("process finished"); } public void SetCurrentRunningRow(int index) @@ -103,16 +100,6 @@ void SetCurrentRunningRow(int index, VerticalTimetableRow? value) { CurrentRunningRowIndex = index; UpdateCurrentRunningLocationVisualizer(value, VerticalTimetableRow.LocationStates.AroundThisStation); - - if (value.LocationState != VerticalTimetableRow.LocationStates.Undefined) - { - logger.Debug("value.LocationState is not Undefined -> invoke ScrollRequested"); - ScrollRequested?.Invoke(this, new(Math.Max(value.RowIndex - 1, 0) * RowHeight.Value)); - } - else - { - logger.Debug("value.LocationState is Undefined -> do nothing"); - } } else { @@ -166,5 +153,15 @@ is VerticalTimetableRow.LocationStates.RunningToNextStation logger.Error(ex, "Failed to perform HapticFeedback"); IsHapticEnabled = false; } + + if (row.LocationState != VerticalTimetableRow.LocationStates.Undefined) + { + logger.Debug("value.LocationState is not Undefined -> invoke ScrollRequested"); + ScrollRequested?.Invoke(this, new(Math.Max(row.RowIndex - 1, 0) * RowHeight.Value)); + } + else + { + logger.Debug("value.LocationState is Undefined -> do nothing"); + } } }