Add a lable for speed displacement on map

Brian [2016-08-21 16:15:22]
Add a lable for speed displacement on map
Add 3 options as checkbox on map
Display routes from google in dash form
Filename
PokemonGo.RocketBot.Logic/Event/GetHumanizeRouteEvent.cs
PokemonGo.RocketBot.Logic/Navigation.cs
PokemonGo.RocketBot.Logic/PokemonGo.RocketBot.Logic.csproj
PokemonGo.RocketBot.Logic/app.config
PokemonGo.RocketBot.Logic/packages.config
PokemonGo.RocketBot.Window/ConsoleEventListener.cs
PokemonGo.RocketBot.Window/Forms/MainForm.cs
PokemonGo.RocketBot.Window/Forms/MainForm.designer.cs
PokemonGo.RocketBot.Window/PokemonGo.RocketBot.Window.csproj
PokemonGo.RocketBot.Window/packages.config
diff --git a/PokemonGo.RocketBot.Logic/Event/GetHumanizeRouteEvent.cs b/PokemonGo.RocketBot.Logic/Event/GetHumanizeRouteEvent.cs
new file mode 100644
index 0000000..9fff3e0
--- /dev/null
+++ b/PokemonGo.RocketBot.Logic/Event/GetHumanizeRouteEvent.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using GeoCoordinatePortable;
+
+namespace PokemonGo.RocketBot.Logic.Event
+{
+    public class GetHumanizeRouteEvent : IEvent
+    {
+        public GeoCoordinate Destination;
+        public List<GeoCoordinate> Route;
+    }
+}
\ No newline at end of file
diff --git a/PokemonGo.RocketBot.Logic/Navigation.cs b/PokemonGo.RocketBot.Logic/Navigation.cs
index 7b7b661..a20be61 100644
--- a/PokemonGo.RocketBot.Logic/Navigation.cs
+++ b/PokemonGo.RocketBot.Logic/Navigation.cs
@@ -22,6 +22,8 @@ namespace PokemonGo.RocketBot.Logic
 {
     public delegate void UpdatePositionDelegate(double lat, double lng);

+    public delegate void GetHumanizeRouteDelegate(List<GeoCoordinate> route, GeoCoordinate destination);
+
     public class Navigation
     {
         private const double SpeedDownTo = 10/3.6;
@@ -210,6 +212,8 @@ namespace PokemonGo.RocketBot.Logic
                 foreach (var item in route)
                     points.Add(new GeoCoordinate(item.ToArray()[1], item.ToArray()[0]));

+                OnGetHumanizeRouteEvent(points, targetLocation);
+
                 for (var i = 0; i < points.Count; i++)
                 {
                     var speedInMetersPerSecond = session.LogicSettings.UseWalkingSpeedVariant
@@ -413,5 +417,11 @@ namespace PokemonGo.RocketBot.Logic
         }

         public event UpdatePositionDelegate UpdatePositionEvent;
+        public static event GetHumanizeRouteDelegate GetHumanizeRouteEvent;
+
+        protected virtual void OnGetHumanizeRouteEvent(List<GeoCoordinate> route, GeoCoordinate destination)
+        {
+            GetHumanizeRouteEvent?.Invoke(route, destination);
+        }
     }
 }
\ No newline at end of file
diff --git a/PokemonGo.RocketBot.Logic/PokemonGo.RocketBot.Logic.csproj b/PokemonGo.RocketBot.Logic/PokemonGo.RocketBot.Logic.csproj
index 4e780b9..43977d9 100644
--- a/PokemonGo.RocketBot.Logic/PokemonGo.RocketBot.Logic.csproj
+++ b/PokemonGo.RocketBot.Logic/PokemonGo.RocketBot.Logic.csproj
@@ -49,6 +49,10 @@
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="C5, Version=2.4.5947.17248, Culture=neutral, PublicKeyToken=282361b99ded7e8e, processorArchitecture=MSIL">
+      <HintPath>..\packages\C5.2.4.5947.17249\lib\net45\C5.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
     <Reference Include="CloudFlareUtilities, Version=0.2.1.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\CloudFlareUtilities.0.2.1-alpha\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\CloudFlareUtilities.dll</HintPath>
       <Private>True</Private>
@@ -65,8 +69,12 @@
       <HintPath>..\packages\GMap.NET.WindowsForms.1.7.1\lib\net40\GMap.NET.WindowsForms.dll</HintPath>
       <Private>True</Private>
     </Reference>
+    <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+      <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
     <Reference Include="S2Geometry, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>$(SolutionDir)\packages\S2Geometry.1.0.1\lib\portable-net45+wp8+win8\S2Geometry.dll</HintPath>
+      <HintPath>..\packages\S2Geometry.1.0.3\lib\portable-net45+wp8+win8\S2Geometry.dll</HintPath>
       <Private>True</Private>
     </Reference>
     <Reference Include="SocketIoClientDotNet, Version=0.9.13.0, Culture=neutral, processorArchitecture=MSIL">
@@ -74,7 +82,9 @@
       <Private>True</Private>
     </Reference>
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
+    <Reference Include="System.IO.Compression" />
     <Reference Include="System.IO.Compression.FileSystem" />
     <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
@@ -82,16 +92,19 @@
     </Reference>
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="System.Net.Http" />
-    <Reference Include="System.Xml" />
-    <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604">
-      <HintPath>$(SolutionDir)\packages\Google.Protobuf.3.0.0-beta4\lib\net45\Google.Protobuf.dll</HintPath>
+    <Reference Include="System.Numerics" />
+    <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
+      <Private>True</Private>
     </Reference>
+    <Reference Include="System.Xml" />
     <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
       <HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="GeoCoordinatePortable">
       <HintPath>$(SolutionDir)\packages\GeoCoordinate.1.1.0\lib\portable-net45+wp80+win+wpa81\GeoCoordinatePortable.dll</HintPath>
     </Reference>
+    <Reference Include="System.Xml.Linq" />
     <Reference Include="Telegram.Bot, Version=10.3.1.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\Telegram.Bot.10.3.1\lib\net45\Telegram.Bot.dll</HintPath>
       <Private>True</Private>
@@ -110,6 +123,7 @@
     <Compile Include="Event\FortTargetEvent.cs" />
     <Compile Include="Event\FortFailedEvent.cs" />
     <Compile Include="Event\FortUsedEvent.cs" />
+    <Compile Include="Event\GetHumanizeRouteEvent.cs" />
     <Compile Include="Event\HumanWalkingEvent.cs" />
     <Compile Include="Event\InventoryListEvent.cs" />
     <Compile Include="Event\ItemRecycledEvent.cs" />
diff --git a/PokemonGo.RocketBot.Logic/app.config b/PokemonGo.RocketBot.Logic/app.config
index 588df31..83b016d 100644
--- a/PokemonGo.RocketBot.Logic/app.config
+++ b/PokemonGo.RocketBot.Logic/app.config
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
+
 <configuration>
   <runtime>
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
@@ -12,4 +13,7 @@
       </dependentAssembly>
     </assemblyBinding>
   </runtime>
-<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /></startup></configuration>
+  <startup>
+    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
+  </startup>
+</configuration>
\ No newline at end of file
diff --git a/PokemonGo.RocketBot.Logic/packages.config b/PokemonGo.RocketBot.Logic/packages.config
index c8b80be..d7ed144 100644
--- a/PokemonGo.RocketBot.Logic/packages.config
+++ b/PokemonGo.RocketBot.Logic/packages.config
@@ -1,15 +1,48 @@
 <?xml version="1.0" encoding="utf-8"?>
+
 <packages>
-  <package id="C5" version="2.2.5073.27396" targetFramework="net452" />
+  <package id="C5" version="2.4.5947.17249" targetFramework="net452" />
   <package id="CloudFlareUtilities" version="0.2.1-alpha" targetFramework="net452" />
   <package id="EngineIoClientDotNet" version="0.9.22" targetFramework="net452" />
   <package id="GeoCoordinate" version="1.1.0" targetFramework="net45" />
   <package id="GMap.NET.WindowsForms" version="1.7.1" targetFramework="net452" />
-  <package id="Google.Protobuf" version="3.0.0-beta4" targetFramework="net45" />
+  <package id="Google.Protobuf" version="3.0.0" targetFramework="net452" />
   <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
+  <package id="Microsoft.NETCore.Platforms" version="1.0.1" targetFramework="net452" />
+  <package id="NETStandard.Library" version="1.6.0" targetFramework="net452" />
   <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
-  <package id="S2Geometry" version="1.0.1" targetFramework="net452" />
+  <package id="S2Geometry" version="1.0.3" targetFramework="net452" />
   <package id="SocketIoClientDotNet" version="0.9.13" targetFramework="net452" />
+  <package id="System.Collections" version="4.0.11" targetFramework="net452" />
+  <package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net452" />
+  <package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="net452" />
+  <package id="System.Diagnostics.Tools" version="4.0.1" targetFramework="net452" />
+  <package id="System.Diagnostics.Tracing" version="4.1.0" targetFramework="net452" />
+  <package id="System.Globalization" version="4.0.11" targetFramework="net452" />
+  <package id="System.IO" version="4.1.0" targetFramework="net452" />
+  <package id="System.IO.Compression" version="4.1.0" targetFramework="net452" />
+  <package id="System.Linq" version="4.1.0" targetFramework="net452" />
+  <package id="System.Linq.Expressions" version="4.1.0" targetFramework="net452" />
+  <package id="System.Net.Http" version="4.1.0" targetFramework="net452" />
+  <package id="System.Net.Primitives" version="4.0.11" targetFramework="net452" />
+  <package id="System.ObjectModel" version="4.0.12" targetFramework="net452" />
+  <package id="System.Reflection" version="4.1.0" targetFramework="net452" />
+  <package id="System.Reflection.Extensions" version="4.0.1" targetFramework="net452" />
+  <package id="System.Reflection.Primitives" version="4.0.1" targetFramework="net452" />
+  <package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="net452" />
+  <package id="System.Runtime" version="4.1.0" targetFramework="net452" />
+  <package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net452" />
+  <package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net452" />
+  <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.0.0" targetFramework="net452" />
+  <package id="System.Runtime.Numerics" version="4.0.1" targetFramework="net452" />
+  <package id="System.Text.Encoding" version="4.0.11" targetFramework="net452" />
+  <package id="System.Text.Encoding.Extensions" version="4.0.11" targetFramework="net452" />
+  <package id="System.Text.RegularExpressions" version="4.1.0" targetFramework="net452" />
+  <package id="System.Threading" version="4.0.11" targetFramework="net452" />
+  <package id="System.Threading.Tasks" version="4.0.11" targetFramework="net452" />
+  <package id="System.Threading.Timer" version="4.0.1" targetFramework="net452" />
+  <package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="net452" />
+  <package id="System.Xml.XDocument" version="4.0.11" targetFramework="net452" />
   <package id="Telegram.Bot" version="10.3.1" targetFramework="net452" />
   <package id="WebSocket4Net" version="0.14.1" targetFramework="net452" />
 </packages>
\ No newline at end of file
diff --git a/PokemonGo.RocketBot.Window/ConsoleEventListener.cs b/PokemonGo.RocketBot.Window/ConsoleEventListener.cs
index 8b5eb11..ab27d46 100644
--- a/PokemonGo.RocketBot.Window/ConsoleEventListener.cs
+++ b/PokemonGo.RocketBot.Window/ConsoleEventListener.cs
@@ -7,6 +7,7 @@ using PokemonGo.RocketBot.Logic.Common;
 using PokemonGo.RocketBot.Logic.Event;
 using PokemonGo.RocketBot.Logic.Logging;
 using PokemonGo.RocketBot.Logic.State;
+using PokemonGo.RocketBot.Window.Forms;
 using POGOProtos.Enums;
 using POGOProtos.Inventory.Item;
 using POGOProtos.Networking.Responses;
@@ -21,11 +22,8 @@ namespace PokemonGo.RocketBot.Window
         private static void HandleEvent(HumanWalkingEvent humanWalkingEvent, ISession session)
         {
             if (session.LogicSettings.ShowVariantWalking)
-                Logger.Write(
-                    session.Translation.GetTranslation(TranslationString.HumanWalkingVariant,
-                    humanWalkingEvent.OldWalkingSpeed,
-                    humanWalkingEvent.CurrentWalkingSpeed),
-                    LogLevel.Info, ConsoleColor.DarkCyan);
+                MainForm.SetSpeedLable("Current Speed: " + Math.Round(humanWalkingEvent.CurrentWalkingSpeed, 2) +
+                                       " km/h");
         }

         private static void HandleEvent(ProfileEvent profileEvent, ISession session)
diff --git a/PokemonGo.RocketBot.Window/Forms/MainForm.cs b/PokemonGo.RocketBot.Window/Forms/MainForm.cs
index e90bb4d..465c4b6 100644
--- a/PokemonGo.RocketBot.Window/Forms/MainForm.cs
+++ b/PokemonGo.RocketBot.Window/Forms/MainForm.cs
@@ -14,6 +14,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;
 using BrightIdeasSoftware;
+using GeoCoordinatePortable;
 using GMap.NET;
 using GMap.NET.MapProviders;
 using GMap.NET.WindowsForms;
@@ -54,6 +55,7 @@ namespace PokemonGo.RocketBot.Window.Forms
         private readonly List<PointLatLng> _playerLocations = new List<PointLatLng>();

         private readonly GMapOverlay _playerOverlay = new GMapOverlay("players");
+        private readonly GMapOverlay _playerRouteOverlay = new GMapOverlay("playerroutes");
         private readonly GMapOverlay _pokemonsOverlay = new GMapOverlay("pokemons");
         private readonly GMapOverlay _pokestopsOverlay = new GMapOverlay("pokestops");
         private readonly GMapOverlay _searchAreaOverlay = new GMapOverlay("areas");
@@ -61,6 +63,7 @@ namespace PokemonGo.RocketBot.Window.Forms
         private PointLatLng _currentLatLng;
         private ConsoleLogger _logger;
         private StateMachine _machine;
+        private List<PointLatLng> _routePoints;
         private GlobalSettings _settings;

         public MainForm()
@@ -80,6 +83,11 @@ namespace PokemonGo.RocketBot.Window.Forms
             Analytics.Client.Identify(MachineIdHelper.GetMachineId(), new Traits());
             Analytics.Client.Track(MachineIdHelper.GetMachineId(), "App started");

+            speedLable.Parent = gMapControl1;
+            showMoreCheckBox.Parent = gMapControl1;
+            followTrainerCheckBox.Parent = gMapControl1;
+            togglePrecalRoute.Parent = gMapControl1;
+
             InitializeBot();
             InitializePokemonForm();
             InitializeMap();
@@ -110,6 +118,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             gMapControl1.Overlays.Add(_pokestopsOverlay);
             gMapControl1.Overlays.Add(_pokemonsOverlay);
             gMapControl1.Overlays.Add(_playerOverlay);
+            gMapControl1.Overlays.Add(_playerRouteOverlay);

             _playerMarker = new GMapMarkerTrainer(new PointLatLng(lat, lng),
                 ResourceHelper.GetImage("Trainer_Front"));
@@ -213,6 +222,11 @@ namespace PokemonGo.RocketBot.Window.Forms
                     _session.EventDispatcher.Send(new OptimizeRouteEvent {OptimizedRoute = optimizedroute});
             RouteOptimizeUtil.RouteOptimizeEvent += InitializePokestopsAndRoute;

+            Navigation.GetHumanizeRouteEvent +=
+                (route, destination) =>
+                    _session.EventDispatcher.Send(new GetHumanizeRouteEvent {Route = route, Destination = destination});
+            Navigation.GetHumanizeRouteEvent += UpdateMap;
+
             FarmPokestopsTask.LootPokestopEvent +=
                 pokestop => _session.EventDispatcher.Send(new LootPokestopEvent {Pokestop = pokestop});
             FarmPokestopsTask.LootPokestopEvent += UpdateMap;
@@ -255,10 +269,10 @@ namespace PokemonGo.RocketBot.Window.Forms
                     (from pokeStop in pokeStops
                         where pokeStop != null
                         select new PointLatLng(pokeStop.Latitude, pokeStop.Longitude)).ToList();
-                foreach(var pks in pokeStops)
-                    Logger.Write(pks.Latitude + ", " + pks.Longitude);

-                // Temporary removed it since the route is calculated on the fly with gmap api's
+                _routePoints = routePoint;
+                togglePrecalRoute.Enabled = true;
+
                 var route = new GMapRoute(routePoint, "Walking Path")
                 {
                     Stroke = new Pen(Color.FromArgb(128, 0, 179, 253), 4)
@@ -288,6 +302,54 @@ namespace PokemonGo.RocketBot.Window.Forms
             }, null);
         }

+        private void UpdateMap(List<GeoCoordinate> route, GeoCoordinate destination)
+        {
+            var routePointLatLngs = new List<PointLatLng>();
+            foreach (var item in route)
+            {
+                routePointLatLngs.Add(new PointLatLng(item.Latitude, item.Longitude));
+            }
+            var routes = new GMapRoute(routePointLatLngs, routePointLatLngs.ToString())
+            {
+                Stroke = new Pen(Color.FromArgb(128, 0, 179, 253), 4) {DashStyle = DashStyle.Dash}
+            };
+            _playerRouteOverlay.Routes.Add(routes);
+            /* Logger.Write("new call");
+             List<PointLatLng> routePointLatLngs = new List<PointLatLng>();
+             Logger.Write("new route size: " +route.Count);
+             PointLatLng destinationPointLatLng = new PointLatLng(destination.Latitude, destination.Longitude);
+             foreach (var item in route)
+             {
+                 routePointLatLngs.Add(new PointLatLng(item.Latitude, item.Longitude));
+             }
+
+             List<PointLatLng> routePointsDistinct = new List<PointLatLng>(_routePoints.Distinct());
+
+             int listPosition;
+             for (listPosition = 0; listPosition < routePointsDistinct.Count; listPosition++)
+             {
+                 Logger.Write("listPosition: " + listPosition);
+                 var item = routePointsDistinct[listPosition];
+                 if (item == destinationPointLatLng)
+                     break;
+             }
+
+             if (listPosition == 0)
+                 return;
+
+             //routePointsDistinct.Remove(destinationPointLatLng);
+             routePointsDistinct.InsertRange(listPosition, routePointLatLngs);
+             //routePointsDistinct.Remove(routePointsDistinct[listPosition - 1]);
+
+
+             _pokestopsOverlay.Routes.Clear();
+             var routes = new GMapRoute(routePointsDistinct, "Walking Path")
+             {
+                 Stroke = new Pen(Color.FromArgb(128, 0, 179, 253), 4)
+             };
+             _pokestopsOverlay.Routes.Add(routes);*/
+        }
+
         private void UpdateMap(FortData pokestop)
         {
             SynchronizationContext.Post(o =>
@@ -342,6 +404,8 @@ namespace PokemonGo.RocketBot.Window.Forms
                         ? new GMapMarkerTrainer(latlng, ResourceHelper.GetImage("Trainer_Right"))
                         : new GMapMarkerTrainer(latlng, ResourceHelper.GetImage("Trainer_Left"));
                 _playerOverlay.Markers.Add(_playerMarker);
+                if (followTrainerCheckBox.Checked)
+                    gMapControl1.Position = latlng;
             }, null);

             _currentLatLng = latlng;
@@ -403,6 +467,54 @@ namespace PokemonGo.RocketBot.Window.Forms
         {
         }

+        private void gMapControl1_Load(object sender, EventArgs e)
+        {
+        }
+
+        private void showMoreCheckBox_CheckedChanged(object sender, EventArgs e)
+        {
+            if (showMoreCheckBox.Checked)
+            {
+                followTrainerCheckBox.Visible = true;
+                togglePrecalRoute.Visible = true;
+            }
+            else
+            {
+                followTrainerCheckBox.Visible = false;
+                togglePrecalRoute.Visible = false;
+            }
+        }
+
+        private void followTrainerCheckBox_CheckedChanged(object sender, EventArgs e)
+        {
+            if (followTrainerCheckBox.Checked)
+            {
+                gMapControl1.CanDragMap = false;
+                gMapControl1.Position = _currentLatLng;
+            }
+            else
+            {
+                gMapControl1.CanDragMap = true;
+            }
+        }
+
+        private void togglePrecalRoute_CheckedChanged(object sender, EventArgs e)
+        {
+            if (togglePrecalRoute.Checked)
+            {
+                _pokestopsOverlay.Routes.Clear();
+                var route = new GMapRoute(_routePoints, "Walking Path")
+                {
+                    Stroke = new Pen(Color.FromArgb(128, 0, 179, 253), 4)
+                };
+                _pokestopsOverlay.Routes.Add(route);
+            }
+            else
+            {
+                _pokestopsOverlay.Routes.Clear();
+            }
+        }
+
         #region INTERFACE

         public static void ColoredConsoleWrite(Color color, string text)
@@ -421,6 +533,16 @@ namespace PokemonGo.RocketBot.Window.Forms
             Instance.logTextBox.AppendText(message);
         }

+        public static void SetSpeedLable(string text)
+        {
+            if (Instance.InvokeRequired)
+            {
+                Instance.Invoke(new Action<string>(SetSpeedLable), text);
+                return;
+            }
+            Instance.speedLable.Text = text;
+        }
+
         public static void SetStatusText(string text)
         {
             if (Instance.InvokeRequired)
@@ -791,7 +913,10 @@ namespace PokemonGo.RocketBot.Window.Forms
                 var inventoryAppliedItems =
                     await _session.Inventory.GetAppliedItems();

-                var appliedItems = inventoryAppliedItems.Where(aItems => aItems?.Item != null).SelectMany(aItems => aItems.Item).ToDictionary(item => item.ItemId, item => Utils.FromUnixTimeUtc(item.ExpireMs));
+                var appliedItems =
+                    inventoryAppliedItems.Where(aItems => aItems?.Item != null)
+                        .SelectMany(aItems => aItems.Item)
+                        .ToDictionary(item => item.ItemId, item => Utils.FromUnixTimeUtc(item.ExpireMs));

                 PokemonObject.Initilize(itemTemplates);

@@ -827,7 +952,8 @@ namespace PokemonGo.RocketBot.Window.Forms
                     inventory.InventoryDelta.InventoryItems
                         .Select(i => i.InventoryItemData?.PokemonData)
                         .Count(p => p != null && p.IsEgg);
-                lblPokemonList.Text = $"{pokemoncount + eggcount} / {profile.PlayerData.MaxPokemonStorage} ({pokemoncount} pokemon, {eggcount} eggs)";
+                lblPokemonList.Text =
+                    $"{pokemoncount + eggcount} / {profile.PlayerData.MaxPokemonStorage} ({pokemoncount} pokemon, {eggcount} eggs)";

                 var items =
                     inventory.InventoryDelta.InventoryItems
@@ -1029,10 +1155,5 @@ namespace PokemonGo.RocketBot.Window.Forms
         }

         #endregion POKEMON LIST
-
-        private void gMapControl1_Load(object sender, EventArgs e)
-        {
-
-        }
     }
 }
\ No newline at end of file
diff --git a/PokemonGo.RocketBot.Window/Forms/MainForm.designer.cs b/PokemonGo.RocketBot.Window/Forms/MainForm.designer.cs
index 39ee085..9ec6e51 100644
--- a/PokemonGo.RocketBot.Window/Forms/MainForm.designer.cs
+++ b/PokemonGo.RocketBot.Window/Forms/MainForm.designer.cs
@@ -64,6 +64,10 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.btnRefresh = new System.Windows.Forms.Button();
             this.splitContainer1 = new System.Windows.Forms.SplitContainer();
             this.splitContainer2 = new System.Windows.Forms.SplitContainer();
+            this.togglePrecalRoute = new System.Windows.Forms.CheckBox();
+            this.followTrainerCheckBox = new System.Windows.Forms.CheckBox();
+            this.showMoreCheckBox = new System.Windows.Forms.CheckBox();
+            this.speedLable = new System.Windows.Forms.Label();
             this.lblInventory = new System.Windows.Forms.Label();
             this.flpItems = new System.Windows.Forms.FlowLayoutPanel();
             this.lblPokemonList = new System.Windows.Forms.Label();
@@ -92,7 +96,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.logTextBox.Name = "logTextBox";
             this.logTextBox.ReadOnly = true;
             this.logTextBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.ForcedVertical;
-            this.logTextBox.Size = new System.Drawing.Size(611, 267);
+            this.logTextBox.Size = new System.Drawing.Size(611, 244);
             this.logTextBox.TabIndex = 0;
             this.logTextBox.Text = "";
             //
@@ -101,7 +105,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.statusStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
             this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.statusLabel});
-            this.statusStrip1.Location = new System.Drawing.Point(0, 541);
+            this.statusStrip1.Location = new System.Drawing.Point(0, 498);
             this.statusStrip1.Name = "statusStrip1";
             this.statusStrip1.Size = new System.Drawing.Size(1254, 22);
             this.statusStrip1.TabIndex = 1;
@@ -110,7 +114,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             // statusLabel
             //
             this.statusLabel.Name = "statusLabel";
-            this.statusLabel.Size = new System.Drawing.Size(39, 17);
+            this.statusLabel.Size = new System.Drawing.Size(43, 17);
             this.statusLabel.Text = "Status";
             //
             // menuStrip1
@@ -121,14 +125,14 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.todoToolStripMenuItem});
             this.menuStrip1.Location = new System.Drawing.Point(0, 0);
             this.menuStrip1.Name = "menuStrip1";
-            this.menuStrip1.Size = new System.Drawing.Size(1254, 24);
+            this.menuStrip1.Size = new System.Drawing.Size(1254, 25);
             this.menuStrip1.TabIndex = 2;
             this.menuStrip1.Text = "menuStrip1";
             //
             // startStopBotToolStripMenuItem
             //
             this.startStopBotToolStripMenuItem.Name = "startStopBotToolStripMenuItem";
-            this.startStopBotToolStripMenuItem.Size = new System.Drawing.Size(77, 20);
+            this.startStopBotToolStripMenuItem.Size = new System.Drawing.Size(85, 21);
             this.startStopBotToolStripMenuItem.Text = "▶ Start Bot";
             this.startStopBotToolStripMenuItem.Click += new System.EventHandler(this.startStopBotToolStripMenuItem_Click);
             //
@@ -136,7 +140,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             //
             this.todoToolStripMenuItem.Enabled = false;
             this.todoToolStripMenuItem.Name = "todoToolStripMenuItem";
-            this.todoToolStripMenuItem.Size = new System.Drawing.Size(490, 20);
+            this.todoToolStripMenuItem.Size = new System.Drawing.Size(540, 21);
             this.todoToolStripMenuItem.Text = "Settings (Not finish yet, please go to the config folder and set your information" +
     " manually)";
             this.todoToolStripMenuItem.Click += new System.EventHandler(this.todoToolStripMenuItem_Click);
@@ -175,7 +179,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.gMapControl1.ScaleMode = GMap.NET.WindowsForms.ScaleModes.Integer;
             this.gMapControl1.SelectedAreaFillColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(65)))), ((int)(((byte)(105)))), ((int)(((byte)(225)))));
             this.gMapControl1.ShowTileGridLines = false;
-            this.gMapControl1.Size = new System.Drawing.Size(605, 239);
+            this.gMapControl1.Size = new System.Drawing.Size(605, 219);
             this.gMapControl1.TabIndex = 23;
             this.gMapControl1.Zoom = 0D;
             this.gMapControl1.Load += new System.EventHandler(this.gMapControl1_Load);
@@ -229,7 +233,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.olvPokemonList.Name = "olvPokemonList";
             this.olvPokemonList.RowHeight = 32;
             this.olvPokemonList.ShowGroups = false;
-            this.olvPokemonList.Size = new System.Drawing.Size(633, 328);
+            this.olvPokemonList.Size = new System.Drawing.Size(633, 299);
             this.olvPokemonList.SmallImageList = this.smallPokemonImageList;
             this.olvPokemonList.TabIndex = 25;
             this.olvPokemonList.UseCompatibleStateImageBehavior = false;
@@ -363,9 +367,9 @@ namespace PokemonGo.RocketBot.Window.Forms
             | System.Windows.Forms.AnchorStyles.Right)));
             this.btnRefresh.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
             this.btnRefresh.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.btnRefresh.Location = new System.Drawing.Point(3, 488);
+            this.btnRefresh.Location = new System.Drawing.Point(3, 446);
             this.btnRefresh.Name = "btnRefresh";
-            this.btnRefresh.Size = new System.Drawing.Size(633, 28);
+            this.btnRefresh.Size = new System.Drawing.Size(633, 26);
             this.btnRefresh.TabIndex = 26;
             this.btnRefresh.Text = "Refresh";
             this.btnRefresh.UseVisualStyleBackColor = true;
@@ -374,7 +378,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             // splitContainer1
             //
             this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.splitContainer1.Location = new System.Drawing.Point(0, 24);
+            this.splitContainer1.Location = new System.Drawing.Point(0, 25);
             this.splitContainer1.Name = "splitContainer1";
             //
             // splitContainer1.Panel1
@@ -388,7 +392,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.splitContainer1.Panel2.Controls.Add(this.lblPokemonList);
             this.splitContainer1.Panel2.Controls.Add(this.olvPokemonList);
             this.splitContainer1.Panel2.Controls.Add(this.btnRefresh);
-            this.splitContainer1.Size = new System.Drawing.Size(1254, 517);
+            this.splitContainer1.Size = new System.Drawing.Size(1254, 473);
             this.splitContainer1.SplitterDistance = 611;
             this.splitContainer1.TabIndex = 27;
             //
@@ -405,19 +409,83 @@ namespace PokemonGo.RocketBot.Window.Forms
             //
             // splitContainer2.Panel2
             //
+            this.splitContainer2.Panel2.Controls.Add(this.togglePrecalRoute);
+            this.splitContainer2.Panel2.Controls.Add(this.followTrainerCheckBox);
+            this.splitContainer2.Panel2.Controls.Add(this.showMoreCheckBox);
+            this.splitContainer2.Panel2.Controls.Add(this.speedLable);
             this.splitContainer2.Panel2.Controls.Add(this.gMapControl1);
-            this.splitContainer2.Size = new System.Drawing.Size(611, 517);
-            this.splitContainer2.SplitterDistance = 267;
+            this.splitContainer2.Size = new System.Drawing.Size(611, 473);
+            this.splitContainer2.SplitterDistance = 244;
             this.splitContainer2.TabIndex = 0;
             //
+            // togglePrecalRoute
+            //
+            this.togglePrecalRoute.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.togglePrecalRoute.AutoSize = true;
+            this.togglePrecalRoute.BackColor = System.Drawing.Color.Transparent;
+            this.togglePrecalRoute.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.togglePrecalRoute.Checked = true;
+            this.togglePrecalRoute.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.togglePrecalRoute.Enabled = false;
+            this.togglePrecalRoute.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.togglePrecalRoute.Location = new System.Drawing.Point(420, 53);
+            this.togglePrecalRoute.Name = "togglePrecalRoute";
+            this.togglePrecalRoute.Size = new System.Drawing.Size(184, 19);
+            this.togglePrecalRoute.TabIndex = 27;
+            this.togglePrecalRoute.Text = "Toggle Pre-Calculated Route";
+            this.togglePrecalRoute.UseVisualStyleBackColor = false;
+            this.togglePrecalRoute.Visible = false;
+            this.togglePrecalRoute.CheckedChanged += new System.EventHandler(this.togglePrecalRoute_CheckedChanged);
+            //
+            // followTrainerCheckBox
+            //
+            this.followTrainerCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.followTrainerCheckBox.AutoSize = true;
+            this.followTrainerCheckBox.BackColor = System.Drawing.Color.Transparent;
+            this.followTrainerCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.followTrainerCheckBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.followTrainerCheckBox.Location = new System.Drawing.Point(472, 28);
+            this.followTrainerCheckBox.Name = "followTrainerCheckBox";
+            this.followTrainerCheckBox.Size = new System.Drawing.Size(132, 19);
+            this.followTrainerCheckBox.TabIndex = 26;
+            this.followTrainerCheckBox.Text = "Map Follow Trainer";
+            this.followTrainerCheckBox.UseVisualStyleBackColor = false;
+            this.followTrainerCheckBox.Visible = false;
+            this.followTrainerCheckBox.CheckedChanged += new System.EventHandler(this.followTrainerCheckBox_CheckedChanged);
+            //
+            // showMoreCheckBox
+            //
+            this.showMoreCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.showMoreCheckBox.AutoSize = true;
+            this.showMoreCheckBox.BackColor = System.Drawing.Color.Transparent;
+            this.showMoreCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.showMoreCheckBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.showMoreCheckBox.Location = new System.Drawing.Point(453, 3);
+            this.showMoreCheckBox.Name = "showMoreCheckBox";
+            this.showMoreCheckBox.Size = new System.Drawing.Size(151, 19);
+            this.showMoreCheckBox.TabIndex = 25;
+            this.showMoreCheckBox.Text = "Show Advance Options";
+            this.showMoreCheckBox.UseVisualStyleBackColor = false;
+            this.showMoreCheckBox.CheckedChanged += new System.EventHandler(this.showMoreCheckBox_CheckedChanged);
+            //
+            // speedLable
+            //
+            this.speedLable.AutoSize = true;
+            this.speedLable.BackColor = System.Drawing.Color.Transparent;
+            this.speedLable.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.speedLable.Location = new System.Drawing.Point(1, 3);
+            this.speedLable.Name = "speedLable";
+            this.speedLable.Size = new System.Drawing.Size(0, 15);
+            this.speedLable.TabIndex = 24;
+            //
             // lblInventory
             //
             this.lblInventory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
             this.lblInventory.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.lblInventory.Location = new System.Drawing.Point(3, 472);
+            this.lblInventory.Location = new System.Drawing.Point(3, 432);
             this.lblInventory.Name = "lblInventory";
-            this.lblInventory.Size = new System.Drawing.Size(633, 13);
+            this.lblInventory.Size = new System.Drawing.Size(633, 12);
             this.lblInventory.TabIndex = 33;
             this.lblInventory.Text = "0 / 0 ";
             this.lblInventory.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
@@ -430,9 +498,9 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.flpItems.BackColor = System.Drawing.SystemColors.Window;
             this.flpItems.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
             this.flpItems.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
-            this.flpItems.Location = new System.Drawing.Point(3, 348);
+            this.flpItems.Location = new System.Drawing.Point(3, 317);
             this.flpItems.Name = "flpItems";
-            this.flpItems.Size = new System.Drawing.Size(633, 120);
+            this.flpItems.Size = new System.Drawing.Size(633, 111);
             this.flpItems.TabIndex = 32;
             //
             // lblPokemonList
@@ -440,18 +508,18 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.lblPokemonList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
             this.lblPokemonList.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-            this.lblPokemonList.Location = new System.Drawing.Point(3, 333);
+            this.lblPokemonList.Location = new System.Drawing.Point(3, 303);
             this.lblPokemonList.Name = "lblPokemonList";
-            this.lblPokemonList.Size = new System.Drawing.Size(633, 12);
+            this.lblPokemonList.Size = new System.Drawing.Size(633, 11);
             this.lblPokemonList.TabIndex = 27;
             this.lblPokemonList.Text = "0 / 0";
             this.lblPokemonList.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
             //
             // MainForm
             //
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(1254, 563);
+            this.ClientSize = new System.Drawing.Size(1254, 520);
             this.Controls.Add(this.splitContainer1);
             this.Controls.Add(this.statusStrip1);
             this.Controls.Add(this.menuStrip1);
@@ -474,6 +542,7 @@ namespace PokemonGo.RocketBot.Window.Forms
             this.splitContainer1.ResumeLayout(false);
             this.splitContainer2.Panel1.ResumeLayout(false);
             this.splitContainer2.Panel2.ResumeLayout(false);
+            this.splitContainer2.Panel2.PerformLayout();
             ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
             this.splitContainer2.ResumeLayout(false);
             this.ResumeLayout(false);
@@ -518,5 +587,9 @@ namespace PokemonGo.RocketBot.Window.Forms
         private BrightIdeasSoftware.OLVColumn pkmnLevel;
         private BrightIdeasSoftware.OLVColumn pkmnMove1;
         private BrightIdeasSoftware.OLVColumn pkmnMove2;
+        private Label speedLable;
+        private CheckBox togglePrecalRoute;
+        private CheckBox followTrainerCheckBox;
+        private CheckBox showMoreCheckBox;
     }
 }
diff --git a/PokemonGo.RocketBot.Window/PokemonGo.RocketBot.Window.csproj b/PokemonGo.RocketBot.Window/PokemonGo.RocketBot.Window.csproj
index e91f81c..674d74e 100644
--- a/PokemonGo.RocketBot.Window/PokemonGo.RocketBot.Window.csproj
+++ b/PokemonGo.RocketBot.Window/PokemonGo.RocketBot.Window.csproj
@@ -91,6 +91,10 @@
       <HintPath>..\packages\Analytics.2.0.2\lib\Analytics.NET.dll</HintPath>
       <Private>True</Private>
     </Reference>
+    <Reference Include="GeoCoordinatePortable, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\GeoCoordinate.1.1.0\lib\portable-net45+wp80+win+wpa81\GeoCoordinatePortable.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
     <Reference Include="GMap.NET.Core, Version=1.7.0.0, Culture=neutral, PublicKeyToken=b85b9027b614afef, processorArchitecture=MSIL">
       <HintPath>..\packages\GMap.NET.WindowsForms.1.7.1\lib\net40\GMap.NET.Core.dll</HintPath>
       <Private>True</Private>
diff --git a/PokemonGo.RocketBot.Window/packages.config b/PokemonGo.RocketBot.Window/packages.config
index a4501d6..be2074c 100644
--- a/PokemonGo.RocketBot.Window/packages.config
+++ b/PokemonGo.RocketBot.Window/packages.config
@@ -6,6 +6,7 @@
   <package id="C5" version="2.4.5947.17249" targetFramework="net452" />
   <package id="Costura.Fody" version="1.3.3.0" targetFramework="net45" developmentDependency="true" />
   <package id="Fody" version="1.29.4" targetFramework="net45" developmentDependency="true" />
+  <package id="GeoCoordinate" version="1.1.0" targetFramework="net452" />
   <package id="GMap.NET.WindowsForms" version="1.7.1" targetFramework="net452" />
   <package id="Google.Apis" version="1.15.0" targetFramework="net452" />
   <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net452" />
You may download the files in Public Git.