You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AgAgent.cs 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using Microsoft.Extensions.DependencyInjection;
  6. using Microsoft.Extensions.Options;
  7. using uqac_ia_aspirobot.Agent.FakeEnv;
  8. using uqac_ia_aspirobot.Agent.FakeEnv.Effectors;
  9. using uqac_ia_aspirobot.Agent.FakeEnv.Sensors;
  10. using uqac_ia_aspirobot.Agent.Interfaces.Effectors;
  11. using uqac_ia_aspirobot.Agent.Interfaces.Sensors;
  12. using uqac_ia_aspirobot.Common;
  13. using uqac_ia_aspirobot.Extensions;
  14. using uqac_ia_aspirobot.Interfaces;
  15. using uqac_ia_aspirobot.UI;
  16. namespace uqac_ia_aspirobot.Agent
  17. {
  18. public class AgAgent
  19. {
  20. private readonly IAgEngineEffector _engineEffector;
  21. private readonly IAgVaccumEffector _vaccumEffector;
  22. private readonly IEnvironment _environment;
  23. private readonly AgConfig _options;
  24. private readonly AgState _state;
  25. private readonly IUi _ui;
  26. private static Thread _thread;
  27. public static void Start(AgConfig agConfig, ArConfig arConfig)
  28. {
  29. var agServices = new ServiceCollection();
  30. agServices.AddOptions();
  31. agServices.AddSingleton<AgState>();
  32. agServices.AddSingleton<AgAgent>();
  33. agServices.AddSingleton<ArClient>();
  34. agServices.AddSingleton<IAgDustSensor, AgDustSensor>();
  35. agServices.AddSingleton<IAgBatterySensor, AgBatterySensor>();
  36. agServices.AddSingleton<IAgVaccumSensor, AgVaccumSensor>();
  37. agServices.AddSingleton<IAgPickedSensor, AgPickedSensor>();
  38. agServices.AddSingleton<IAgVaccumEffector, AgVaccumEffector>();
  39. agServices.AddSingleton<IAgEngineEffector, AgEngineEffector>();
  40. agServices.AddSingleton<IUi, UiConsole>();
  41. agServices.AddSingleton<IEnvironment, AgEnvironment>();
  42. agServices.AddTransient<IRoom, AgRoom>();
  43. agServices.Configure<AgConfig>(agConfig.CopyTo);
  44. agServices.Configure<ArConfig>(arConfig.CopyTo);
  45. var agProvider = agServices.BuildServiceProvider();
  46. var agThread = agProvider.GetService<AgAgent>();
  47. _thread = new Thread(agThread.Run)
  48. {
  49. Name = nameof(AgAgent)
  50. };
  51. _thread.Start();
  52. }
  53. public static void Join()
  54. {
  55. _thread.Join();
  56. }
  57. public AgAgent(IOptions<AgConfig> options,
  58. IEnvironment environment, AgState state, IUi ui,
  59. IAgEngineEffector engineEffector, IAgVaccumEffector vaccumEffector)
  60. {
  61. _engineEffector = engineEffector;
  62. _vaccumEffector = vaccumEffector;
  63. _environment = environment;
  64. _state = state;
  65. _ui = ui;
  66. _options = options.Value;
  67. _state.LastThinkTime = DateTime.MinValue;
  68. _state.ThinkTimeInterval = _options.ThinkTimeInterval;
  69. }
  70. private void Run()
  71. {
  72. var running = true;
  73. _environment.Setup();
  74. _state.DustyRooms = new List<IRoom>();
  75. while (running)
  76. {
  77. _environment.Update();
  78. _ui.Update();
  79. UpdateState();
  80. Think();
  81. Work();
  82. if (_options.SleepTime > 0)
  83. {
  84. Thread.Sleep(_options.SleepTime);
  85. }
  86. }
  87. }
  88. public void UpdateState()
  89. {
  90. if (_options.AutoAdjustThinkTimeInterval)
  91. {
  92. var dustyRooms = _environment.FindDustyRooms();
  93. if ((dustyRooms.Count < _state.DustyRooms.Count || !dustyRooms.Any()) && _state.ThinkTimeInterval < 7500)
  94. {
  95. _state.ThinkTimeInterval += _state.ThinkTimeInterval / 2;
  96. }
  97. else if (dustyRooms.Count > _state.DustyRooms.Count && _state.ThinkTimeInterval > 100)
  98. {
  99. _state.ThinkTimeInterval -= _state.ThinkTimeInterval / 2;
  100. }
  101. _state.DustyRooms = dustyRooms;
  102. }
  103. else
  104. {
  105. _state.DustyRooms = _environment.FindDustyRooms();
  106. }
  107. }
  108. public void Think()
  109. {
  110. if (_state.LastThinkTime.AddMilliseconds(_state.ThinkTimeInterval) <= DateTime.Now)
  111. {
  112. if (_state.Destination == null && _state.DustyRooms.Any())
  113. {
  114. _state.Destination = _state.DustyRooms.OrderBy(room => room.Distance(_engineEffector)).First();
  115. }
  116. _state.LastThinkTime = DateTime.Now;
  117. }
  118. }
  119. public void Work()
  120. {
  121. if (_environment.GetRoomState(_engineEffector.X, _engineEffector.Y).HasFlag(RoomState.Jewel))
  122. {
  123. _vaccumEffector.Pick();
  124. }
  125. if (_environment.GetRoomState(_engineEffector.X, _engineEffector.Y).HasFlag(RoomState.Dust))
  126. {
  127. _vaccumEffector.Vaccum();
  128. }
  129. if (_state.Destination != null && _engineEffector.IsInRoom(_state.Destination))
  130. {
  131. _state.Destination = null;
  132. }
  133. if (_state.Destination != null)
  134. {
  135. if (_state.Destination.X < _engineEffector.X)
  136. {
  137. _engineEffector.Move(-1, 0);
  138. }
  139. else if (_state.Destination.X > _engineEffector.X)
  140. {
  141. _engineEffector.Move(1, 0);
  142. }
  143. else if (_state.Destination.Y < _engineEffector.Y)
  144. {
  145. _engineEffector.Move(0, -1);
  146. }
  147. else if (_state.Destination.Y > _engineEffector.Y)
  148. {
  149. _engineEffector.Move(0, 1);
  150. }
  151. }
  152. }
  153. }
  154. }