PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/ppcp/units/unit2/src/AntisocialRobots/MainWindow.xaml.cs

#
C# | 299 lines | 208 code | 34 blank | 57 comment | 52 complexity | 70b2c38bc0b88ba03f4f59cb754039fd MD5 | raw file
  1. //--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // File: MainWindow.xaml.cs
  6. //
  7. //--------------------------------------------------------------------------
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.Threading.Tasks;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Input;
  15. using System.Windows.Media;
  16. using System.Windows.Shapes;
  17. using System.Windows.Threading;
  18. namespace AntisocialRobots
  19. {
  20. /// <summary>Interaction logic for MainWindow.xaml</summary>
  21. public partial class MainWindow : Window
  22. {
  23. int ROOM_SIZE = 200;
  24. int NEW_ROOM_SIZE = 0;
  25. RobotSimulation _robotSim;
  26. List<Ellipse> _robotVis;
  27. /// <summary>
  28. /// The color of the next robot to be created. To cycle the colors, we use this
  29. /// algorithm: one of R, G, and B is zero; the other two cycle from 240 down to 10 and 10
  30. /// up to 240.
  31. /// </summary>
  32. Color _nextColor = Color.FromRgb(240, 10, 0);
  33. /// <summary>
  34. /// Calculates frames per second, by measuring the time required to display FramesPerSample
  35. /// frames.
  36. /// </summary>
  37. Stopwatch _framesPerSecondStopwatch = new Stopwatch();
  38. /// <summary>The number of frames included in one frames per second measurement.</summary>
  39. const int FramesPerSample = 10;
  40. /// <summary>Initializes an instance of this class.</summary>
  41. public MainWindow()
  42. {
  43. InitializeComponent();
  44. // Initializes robot state
  45. Action clearState = () => {
  46. if (NEW_ROOM_SIZE != 0)
  47. {
  48. ROOM_SIZE = NEW_ROOM_SIZE;
  49. NEW_ROOM_SIZE = 0;
  50. }
  51. _robotSim = new RobotSimulation(ROOM_SIZE);
  52. _robotVis = new List<Ellipse>();
  53. Room.Children.Clear();
  54. };
  55. clearState();
  56. // When F5 is pressed, reset state
  57. KeyDown += (_, e) => { if (e.Key == Key.F5) clearState(); };
  58. // or when button pressed
  59. RestartButton.Click += (_, e) => { clearState(); };
  60. // Render loop, started when the window loads
  61. Action recomputeAndRedraw = null;
  62. recomputeAndRedraw = delegate {
  63. Dispatcher.BeginInvoke((Action)delegate {
  64. // handle the case where the user changed the room size
  65. // but there are no robots in the room
  66. if (_robotSim.Robots.Count == 0 &&
  67. NEW_ROOM_SIZE != 0 &&
  68. NEW_ROOM_SIZE != ROOM_SIZE)
  69. clearState();
  70. if (!_robotSim.FoundBug)
  71. {
  72. PerformSimulationStep();
  73. }
  74. recomputeAndRedraw();
  75. }, DispatcherPriority.Background);
  76. };
  77. Loaded += delegate {
  78. _framesPerSecondStopwatch.Start();
  79. recomputeAndRedraw();
  80. };
  81. comboBox1.SelectedItem = room200;
  82. }
  83. /// <summary>
  84. /// Called when the size of the RoomParent (the control containing the canvas that
  85. /// displays the robots) changes.
  86. /// </summary>
  87. private void RoomParent_SizeChanged(object sender, SizeChangedEventArgs e)
  88. {
  89. // Set size to the width/height of the largest square that fits within
  90. // RoomParent (the control containing the canvas that holds robots)
  91. double size = Math.Min(RoomParent.ActualWidth, RoomParent.ActualHeight);
  92. // Room is set to be 1.0 units wide x 1.0 units high -- apply a scaling
  93. // transform so that it fills RoomParent
  94. RoomScaleTransform.ScaleX = size;
  95. RoomScaleTransform.ScaleY = size;
  96. // Center Room within the RoomParent
  97. double marginX = (RoomParent.ActualWidth - size) / 2;
  98. double marginY = (RoomParent.ActualHeight - size) / 2;
  99. Room.Margin = new Thickness(marginX, marginY, 0, 0);
  100. }
  101. /// <summary>Called when the user clicks on the canvas containing the robots.</summary>
  102. private void Room_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  103. {
  104. if (!_robotSim.FoundBug)
  105. CreateRobot(MousePositionToRoomPoint(e));
  106. }
  107. /// <summary>
  108. /// Called when the users moves the mouse, or holds the mouse button, over the canvas
  109. /// containing the robots.
  110. /// </summary>
  111. private void Room_MouseMove(object sender, MouseEventArgs e)
  112. {
  113. if (!_robotSim.FoundBug && e.MouseDevice.LeftButton == MouseButtonState.Pressed)
  114. CreateRobot(MousePositionToRoomPoint(e));
  115. }
  116. /// <summary>Creates a robot, which is placed at a given location with the room.</summary>
  117. /// <param name="pt">Where the robot should be placed, in RoomPoint coordinates.</param>
  118. void CreateRobot(RoomPoint pt)
  119. {
  120. Robot robot = _robotSim.CreateRobot(pt);
  121. if (robot == null)
  122. return;
  123. var ellipse =
  124. new Ellipse() {
  125. Width = 1.0 / ROOM_SIZE,
  126. Height = 1.0 / ROOM_SIZE,
  127. HorizontalAlignment = HorizontalAlignment.Left,
  128. VerticalAlignment = VerticalAlignment.Top,
  129. Fill = new SolidColorBrush(_nextColor)
  130. };
  131. _robotVis.Add(ellipse);
  132. // Add the robot to Room
  133. Room.Children.Add(ellipse);
  134. // Set the position of the robot within Room
  135. SetRobotElementPosition(ellipse, pt);
  136. // Advance _nextColor to the next color to use
  137. MoveNextColor();
  138. }
  139. /// <summary>Advances to the next color in the rotation.</summary>
  140. private void MoveNextColor()
  141. {
  142. if (_nextColor.B == 0)
  143. {
  144. _nextColor.R = (byte)Math.Max((int)_nextColor.R - 10, 0);
  145. _nextColor.G = (byte)Math.Max((int)_nextColor.G + 10, 0);
  146. if (_nextColor.R == 0)
  147. {
  148. _nextColor.G = 240;
  149. _nextColor.B = 10;
  150. }
  151. }
  152. else if (_nextColor.G > 0)
  153. {
  154. _nextColor.G = (byte)Math.Max((int)_nextColor.G - 10, 0);
  155. _nextColor.B = (byte)Math.Max((int)_nextColor.B + 10, 0);
  156. if (_nextColor.G == 0)
  157. {
  158. _nextColor.B = 240;
  159. _nextColor.R = 10;
  160. }
  161. }
  162. else
  163. {
  164. _nextColor.B = (byte)Math.Max((int)_nextColor.B - 10, 0);
  165. _nextColor.R = (byte)Math.Max((int)_nextColor.R + 10, 0);
  166. if (_nextColor.B == 0)
  167. {
  168. _nextColor.R = 240;
  169. _nextColor.G = 10;
  170. }
  171. }
  172. }
  173. /// <summary>Sets the position of the Robot.Element for a given robot to a given point.</summary>
  174. /// <param name="robot">The robot.</param>
  175. /// <param name="pt">The location in RoomPoint coordinates.</param>
  176. void SetRobotElementPosition(Ellipse e, RoomPoint pt)
  177. {
  178. Canvas.SetLeft(e, ((double)pt.X) / ROOM_SIZE);
  179. Canvas.SetTop(e, ((double)pt.Y) / ROOM_SIZE);
  180. }
  181. /// <summary>Converts a mouse position to a RoomPoint.</summary>
  182. /// <param name="e">The event arguments containing the mouse position.</param>
  183. RoomPoint MousePositionToRoomPoint(MouseEventArgs e)
  184. {
  185. Point pt = e.GetPosition(Room);
  186. var rmPt = new RoomPoint((int)(pt.X * ROOM_SIZE), (int)(pt.Y * ROOM_SIZE));
  187. // If pt.x/y == 1.0f, than we'll get an invalid RoomPoint
  188. if (rmPt.X == ROOM_SIZE) rmPt.X--;
  189. if (rmPt.Y == ROOM_SIZE) rmPt.Y--;
  190. return rmPt;
  191. }
  192. /// <summary>Performs one step of the simulation.</summary>
  193. void PerformSimulationStep()
  194. {
  195. // Calculate a new position for each robot, update _roomCells and each
  196. // Robot.Location with that information
  197. if (naiveparallel.IsChecked.Value)
  198. {
  199. if (chkLock.IsChecked.Value)
  200. _robotSim.UpdateMode = RobotSimulation.FrameUpdateMode.Parallel_WithFineGrainedLocks1;
  201. else
  202. _robotSim.UpdateMode = RobotSimulation.FrameUpdateMode.ParallelNoLocks;
  203. }
  204. else if (stripedparallel.IsChecked.Value)
  205. {
  206. _robotSim.UpdateMode = RobotSimulation.FrameUpdateMode.StrippedParallel;
  207. }
  208. else
  209. { // sequential
  210. _robotSim.UpdateMode = RobotSimulation.FrameUpdateMode.Sequential;
  211. }
  212. _robotSim.PerformFrameUpdate();
  213. #region BugDiagnosis
  214. if (chkCompare.IsChecked.Value && !_robotSim.FoundBug && _robotSim.CheckInvariant())
  215. {
  216. var r1 = _robotSim.Robot1;
  217. var r2 = _robotSim.Robot2;
  218. var conflictLocation = _robotSim.ConflictLocation;
  219. // show an error
  220. MessageBox.Show(
  221. "robot " + r1.Id + "'s location is (" + r1.Location.X + "," + r1.Location.Y + ") but robot " +
  222. r2.Id + " occupies that location. Click OK to see the conflicting robots in the previous frame."
  223. );
  224. var conflictCell = new Rectangle() {
  225. Width = 1.0 / ROOM_SIZE,
  226. Height = 1.0 / ROOM_SIZE,
  227. Fill = new LinearGradientBrush(
  228. Colors.Red, Colors.Gray, new Point(0, 0), new Point(1, 1))
  229. };
  230. Room.Children.Add(conflictCell);
  231. Canvas.SetLeft(conflictCell, ((double)conflictLocation.X) / ROOM_SIZE);
  232. Canvas.SetTop(conflictCell, ((double)conflictLocation.Y) / ROOM_SIZE);
  233. _robotSim.RestoreRoom();
  234. }
  235. #endregion
  236. // update the on-screen position of all robots
  237. var ellipses = _robotVis.GetEnumerator();
  238. foreach (Robot robot in _robotSim.Robots)
  239. {
  240. ellipses.MoveNext();
  241. SetRobotElementPosition(ellipses.Current, robot.Location);
  242. }
  243. // Update statistics
  244. if ((_robotSim.FrameIdx % FramesPerSample) == 0)
  245. {
  246. double fps = (1000 / (double)_framesPerSecondStopwatch.ElapsedMilliseconds) * FramesPerSample;
  247. txtStatus.Text = String.Format("{0} robots, {1:n1} fps", _robotSim.Robots.Count, fps);
  248. _framesPerSecondStopwatch.Restart();
  249. }
  250. }
  251. private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
  252. {
  253. if (comboBox1.SelectedItem == room10)
  254. NEW_ROOM_SIZE = 10;
  255. else if (comboBox1.SelectedItem == room20)
  256. NEW_ROOM_SIZE = 20;
  257. else if (comboBox1.SelectedItem == room50)
  258. NEW_ROOM_SIZE = 50;
  259. else if (comboBox1.SelectedItem == room100)
  260. NEW_ROOM_SIZE = 100;
  261. else if (comboBox1.SelectedItem == room200)
  262. NEW_ROOM_SIZE = 200;
  263. }
  264. }
  265. }