context: using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  
  using Color = System.Drawing.Color;
  
  using LeagueSharp;
  using LeagueSharp.Common;
  using SharpDX;
  
  using EloBuddy; 
   using LeagueSharp.Common; 
   namespace ezEvade
  {
      class EvadeHelper
      {
          private static AIHeroClient myHero { get { return ObjectManager.Player; } }
          public static bool fastEvadeMode;
  
          public static bool PlayerInSkillShot(Spell spell)
          {
              return ObjectCache.myHeroCache.serverPos2D.InSkillShot(spell, ObjectCache.myHeroCache.boundingRadius);
          }
  
          public static PositionInfo InitPositionInfo(Vector2 pos, float extraDelayBuffer, float extraEvadeDistance, Vector2 lastMovePos, Spell lowestEvadeTimeSpell)
          {
              if (!ObjectCache.myHeroCache.isMoving && ObjectCache.myHeroCache.serverPos2D.Distance(pos) <= 75)
                  pos = ObjectCache.myHeroCache.serverPos2D;
  
              var extraDist = ObjectCache.menuCache.cache["ExtraCPADistance"].GetValue<Slider>().Value;
  
              PositionInfo posInfo;
              posInfo = CanHeroWalkToPos(pos, ObjectCache.myHeroCache.moveSpeed,extraDelayBuffer + ObjectCache.gamePing, extraDist);
              posInfo.isDangerousPos = pos.CheckDangerousPos(6);
              posInfo.hasExtraDistance = extraEvadeDistance > 0 && pos.CheckDangerousPos(extraEvadeDistance);
              posInfo.closestDistance = posInfo.distanceToMouse;
              posInfo.distanceToMouse = pos.GetPositionValue();
              posInfo.posDistToChamps = pos.GetDistanceToChampions();
              posInfo.speed = ObjectCache.myHeroCache.moveSpeed;
  
              if (ObjectCache.menuCache.cache["RejectMinDistance"].GetValue<Slider>().Value > 0 && 
                  ObjectCache.menuCache.cache["RejectMinDistance"].GetValue<Slider>().Value > posInfo.closestDistance) //reject closestdistance
                  posInfo.rejectPosition = true;
  
              if (ObjectCache.menuCache.cache["MinComfortZone"].GetValue<Slider>().Value > posInfo.posDistToChamps)
                  posInfo.hasComfortZone = false;
  
              return posInfo;
          }
  
          public static IOrderedEnumerable<PositionInfo> GetBestPositionTest()
          {
              int posChecked = 0;
              int maxPosToCheck = 50;
              int posRadius = 50;
              int radiusIndex = 0;
  
              Vector2 heroPoint = ObjectCache.myHeroCache.serverPos2D;
              Vector2 lastMovePos = Game.CursorPos.To2D();
  
              var extraDelayBuffer = ObjectCache.menuCache.cache["ExtraPingBuffer"].GetValue<Slider>().Value;
              var extraEvadeDistance = ObjectCache.menuCache.cache["ExtraEvadeDistance"].GetValue<Slider>().Value;
  
              if (ObjectCache.menuCache.cache["HigherPrecision"].GetValue<bool>())
              {
                  maxPosToCheck = 150;
                  posRadius = 25;
              }
  
              var posTable = new List<PositionInfo>();
              var fastestPositions = GetFastestPositions();
  
              Spell lowestEvadeTimeSpell;
              var lowestEvadeTime = SpellDetector.GetLowestEvadeTime(out lowestEvadeTimeSpell);
  
              foreach (var pos in fastestPositions) //add the fastest positions into list of candidates
              {
                  posTable.Add(InitPositionInfo(pos, extraDelayBuffer, extraEvadeDistance, lastMovePos, lowestEvadeTimeSpell));
              }
  
              while (posChecked < maxPosToCheck)
              {
                  radiusIndex++;
  
                  int curRadius = radiusIndex * (2 * posRadius);
                  int curCircleChecks = (int)Math.Ceiling((2 * Math.PI * (double)curRadius) / (2 * (double)posRadius));
  
                  for (int i = 1; i < curCircleChecks; i++)
                  {
                      posChecked++;
                      var cRadians = (2 * Math.PI / (curCircleChecks - 1)) * i; //check decimals
                      var pos = new Vector2((float)Math.Floor(heroPoint.X + curRadius * Math.Cos(cRadians)), (float)Math.Floor(heroPoint.Y + curRadius * Math.Sin(cRadians)));
  
  
                      posTable.Add(InitPositionInfo(pos, extraDelayBuffer, extraEvadeDistance, lastMovePos, lowestEvadeTimeSpell));
  
  
                      if (pos.IsWall())
                      {
                          //Render.Circle.DrawCircle(new Vector3(pos.X, pos.Y, myHero.Position.Z), (float)25, Color.White, 3);
                      }
                      /*
                      if (posDangerLevel > 0)
                      {
                          Render.Circle.DrawCircle(new Vector3(pos.X, pos.Y, myHero.Position.Z), (float) posRadius, Color.White, 3);
                      }*/
  
  
                      var path = myHero.GetPath(pos.To3D());
  
                      //Render.Circle.DrawCircle(path[path.Length - 1], (float)posRadius, Color.White, 3);
                      //Render.Circle.DrawCircle(new Vector3(pos.X, pos.Y, myHero.Position.Z), (float)posRadius, Color.White, 3);
  
                      //var posOnScreen = Drawing.WorldToScreen(path[path.Length - 1]);
                      //Drawing.DrawText(posOnScreen.X, posOnScreen.Y, Color.Aqua, "" + path.Length);
                  }
              }
  
              var sortedPosTable =
                  posTable.OrderBy(p => p.isDangerousPos)
                      .ThenBy(p => p.posDangerLevel)
                      .ThenBy(p => p.posDangerCount)
                      .ThenBy(p => p.distanceToMouse);
  
              return sortedPosTable;
          }
  
          public static PositionInfo GetBestPosition()
          {
              int posChecked = 0;
              int maxPosToCheck = 50;
              int posRadius = 50;
              int radiusIndex = 0;
  
              var extraDelayBuffer = ObjectCache.menuCache.cache["ExtraPingBuffer"].GetValue<Slider>().Value;
              var extraEvadeDistance = ObjectCache.menuCache.cache["ExtraEvadeDistance"].GetValue<Slider>().Value;
  
              SpellDetector.UpdateSpells();
              CalculateEvadeTime();
  
              if (ObjectCache.menuCache.cache["CalculateWindupDelay"].GetValue<bool>())
              {
                  var extraWindupDelay = Evade.lastWindupTime - EvadeUtils.TickCount;
                  if (extraWindupDelay > 0)
                  {
                      extraDelayBuffer += (int) extraWindupDelay;
                  }
              }
  
              extraDelayBuffer += (int)(Evade.avgCalculationTime);
  
              if (ObjectCache.menuCache.cache["HigherPrecision"].GetValue<bool>())
              {
                  maxPosToCheck = 150;
                  posRadius = 25;
              }
  
              Vector2 heroPoint = ObjectCache.myHeroCache.serverPos2D;
              Vector2 lastMovePos = Game.CursorPos.To2D();
  
              List<PositionInfo> posTable = new List<PositionInfo>();
  
              Spell lowestEvadeTimeSpell;
              var lowestEvadeTime = SpellDetector.GetLowestEvadeTime(out lowestEvadeTimeSpell);
  
              List<Vector2> fastestPositions = GetFastestPositions();
  
              foreach (var pos in fastestPositions) //add the fastest positions into list of candidates
              {
                  posTable.Add(InitPositionInfo(pos, extraDelayBuffer, extraEvadeDistance, lastMovePos, lowestEvadeTimeSpell));
              }
  
              while (posChecked < maxPosToCheck)
              {
                  radiusIndex++;
  
                  int curRadius = radiusIndex * (2 * posRadius);
                  int curCircleChecks = (int)Math.Ceiling((2 * Math.PI * (double)curRadius) / (2 * (double)posRadius));
  
                  for (int i = 1; i < curCircleChecks; i++)
                  {
                      posChecked++;
                      var cRadians = (2 * Math.PI / (curCircleChecks - 1)) * i; //check decimals
                      var pos = new Vector2((float)Math.Floor(heroPoint.X + curRadius * Math.Cos(cRadians)), (float)Math.Floor(heroPoint.Y + curRadius * Math.Sin(cRadians)));
                      posTable.Add(InitPositionInfo(pos, extraDelayBuffer, extraEvadeDistance, lastMovePos, lowestEvadeTimeSpell));
                  }
              }
  
              IOrderedEnumerable<PositionInfo> sortedPosTable;
  
              if (ObjectCache.menuCache.cache["EvadeMode"].GetValue<StringList>().SelectedValue == "Fastest")
              {
                  sortedPosTable =
                      posTable.OrderBy(p => p.isDangerousPos)
                          .ThenByDescending(p => p.intersectionTime)
                          .ThenBy(p => p.posDangerLevel)
                          .ThenBy(p => p.posDangerCount);
  
                  fastEvadeMode = true;
              }
              else if (fastEvadeMode)
              {
                  sortedPosTable =
                      posTable.OrderBy(p => p.isDangerousPos)
                          .ThenByDescending(p => p.intersectionTime)
                          .ThenBy(p => p.posDangerLevel)
                          .ThenBy(p => p.posDangerCount);
              }
              else if (ObjectCache.menuCache.cache["FastEvadeActivationTime"].GetValue<Slider>().Value > 0
                       && ObjectCache.menuCache.cache["FastEvadeActivationTime"].GetValue<Slider>().Value + ObjectCache.gamePing + extraDelayBuffer > lowestEvadeTime)
              {
                  sortedPosTable =
                      posTable.OrderBy(p => p.isDangerousPos)
                          .ThenByDescending(p => p.intersectionTime)
                          .ThenBy(p => p.posDangerLevel)
                          .ThenBy(p => p.posDangerCount);
  
                  fastEvadeMode = true;
              }
              else
              {
                  sortedPosTable =
                      posTable.OrderBy(p => p.rejectPosition)
                          .ThenBy(p => p.posDangerLevel)
  
gt:                         .ThenBy(p => p.posDangerCount)