using CzokoŚmieciarka.DataModels.Enums; using CzokoŚmieciarka.DataModels.Interfaces; using CzokoŚmieciarka.DataModels.Interfaces.RoutePlanningEngine; using CzokoŚmieciarka.DataModels.Interfaces.TrashCans; using CzokoŚmieciarka.DataModels.Models; using CzokoŚmieciarka.DataModels.Models.Steps; using System; using System.Collections.Generic; using System.Linq; namespace Czoko_Smieciarka.AI_Naive { public class RoutePlanningEngine : IRoutePlanningEngine { public IGarbageCollector Collector { get; } public IEnumerable Cans { get; } public IEnumerable Dumps { get; } enum State { TravelToDump, TravelToCan, Wait, Finish } public Coords Destination { get; set; } public object DestinationObject { get; set; } private State CurrentState { get; set; } public IEnumerable CalculateStep() { return PerformMove(); } public RoutePlanningEngine(IGarbageCollector collector, IEnumerable cans, IEnumerable dumps) { this.Collector = collector.Clone() as IGarbageCollector; this.Cans = cans; this.Dumps = dumps; this.CurrentState = State.Wait; } private IEnumerable PerformMove() { switch (CurrentState) { case State.TravelToDump: if (Destination == Collector.Position) { var dump = (DestinationObject as ADump); var step = new SpillStep(Collector, dump, dump.TypeOfGarbage); step.Invoke(); yield return step; this.CurrentState = State.Wait; } else { var dif = Destination - Collector.Position; Direction nextDirection = (dif.X == 0) ? ((dif.Y > 0) ? Direction.Up : Direction.Down) : ((dif.X > 0) ? Direction.Right : Direction.Left); var step = new MoveStep(nextDirection, Collector); step.Invoke(); yield return step; } break; case State.TravelToCan: if (Destination == Collector.Position) { var garbage = (DestinationObject as IGarbageLocalization); foreach (var item in garbage.TrashCans) { var step = new CollectStep(Collector, garbage, item.TypeOfGarbage); step.Invoke(); yield return step; } this.CurrentState = State.Wait; } else { var dif = Destination - Collector.Position; Direction nextDirection = (dif.X == 0) ? ((dif.Y > 0) ? Direction.Up : Direction.Down) : ((dif.X > 0) ? Direction.Right : Direction.Left); var step = new MoveStep(nextDirection, Collector); step.Invoke(); yield return step; } break; case State.Wait: var notEmpty = Collector.TrashContainers.Where(i => i.FillPercent > 0); if (notEmpty.Any()) { var destDump = Dumps.First(i => i.TypeOfGarbage == notEmpty.First().TypeOfGarbage); this.Destination = destDump.Localization; this.CurrentState = State.TravelToDump; } else { var notEmptyCans = Cans.Where(i => i.TrashCans.Any(j => j.FillPercent > 0)); if (notEmptyCans.Any()) { this.Destination = notEmptyCans.First().Coords; this.CurrentState = State.TravelToCan; } else { this.CurrentState = State.Finish; } } break; case State.Finish: yield break; break; } foreach (var item in PerformMove()) { yield return item; } } } }