PageRenderTime 64ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 0ms

/SuperMemory/Order/OrderViewModel.cs

https://github.com/antonkulaga/SuperMemory
C# | 339 lines | 219 code | 81 blank | 39 comment | 22 complexity | 4deb6507b6c42f139567b99615b5f804 MD5 | raw file
  1. using System;
  2. using System.Diagnostics.Contracts;
  3. using System.Linq;
  4. using System.Reactive;
  5. using System.Windows;
  6. using System.Windows.Input;
  7. using Smart.Classes.Collections;
  8. using Smart.Classes.Events;
  9. using Smart.Classes.Extensions;
  10. using Smart.Classes.Interfaces;
  11. using Smart.Classes.Subjects;
  12. using Smart.UI.Classes;
  13. using Smart.UI.Classes.Animations;
  14. using Smart.UI.Classes.Events;
  15. using Smart.UI.Panels;
  16. using Smart.UI.Widgets.Events;
  17. using System.Reactive.Linq;
  18. namespace SuperMemory.Order
  19. {
  20. public class OrderViewModel:IEventsHolder
  21. {
  22. private readonly FieldMatrix Matrix;
  23. private readonly PicsManager Imager;
  24. protected StateMachine<String> States;
  25. public OrderSettings Settings;
  26. [Pure]
  27. public OrderViewModel(OrderSettings settings)
  28. {
  29. this.EventManager = new SmartEventManager();
  30. this.Settings = settings;
  31. this.Matrix = new FieldMatrix(this.Settings.Cols.Value,this.Settings.Rows.Value);
  32. this.Imager = new PicsManager();
  33. }
  34. /// <summary>
  35. /// Inits main part of application logic
  36. /// Made public because i want to nake all the binding first
  37. /// </summary>
  38. public void Start()
  39. {
  40. InitEvents();
  41. InitStates();
  42. Contract.Assert(States.Current == OrderStates.ZERO_STATE);
  43. //Contract.Assert(States.NextPossibleState() == OrderStates.NON_GAME_STATE);
  44. this.States.GoTo(OrderStates.NON_GAME_STATE);
  45. }
  46. /// <summary>
  47. /// Starts play
  48. /// </summary>
  49. public void OnButtonClick()
  50. {
  51. if(this.States.ActiveTransitionsCount>0)return;
  52. switch (this.States.TargetState)
  53. {
  54. case OrderStates.ZERO_STATE: this.States.GoTo(OrderStates.NON_GAME_STATE); break;
  55. case OrderStates.NON_GAME_STATE: this.States.GoTo(OrderStates.MEMORIZE_STATE); break;
  56. case OrderStates.MEMORIZE_STATE: this.States.GoTo(OrderStates.POSITION_STATE); break;
  57. case OrderStates.POSITION_STATE: this.States.GoTo(OrderStates.GAME_COMPLETED_STATE); break;
  58. case OrderStates.GAME_COMPLETED_STATE: this.States.GoTo(OrderStates.NON_GAME_STATE); break;
  59. }
  60. }
  61. private void InitEvents()
  62. {
  63. this.AddEventHandler<String>(OrderEvents.GO_2_STATE, this.GoToState);
  64. }
  65. private void GoToState(String state)
  66. {
  67. this.States.GoTo(state);
  68. }
  69. private void InitStates()
  70. {
  71. States = new StateMachine<string> {PossibleStates = OrderStates.PossibleStates };
  72. States.GoTo(OrderStates.ZERO_STATE);
  73. States.State(OrderStates.POSITION_STATE).DoOnNext += On_Position_State;
  74. States.EachTimeTransition = new SimpleSubject<Transition<string>>(EachTimeTransition);
  75. States.TransitionFrom(OrderStates.NON_GAME_STATE).DoOnNext += this.From_NonGame_2_All;
  76. States.TransitionFrom(OrderStates.POSITION_STATE).DoOnNext += From_Position_2_All;
  77. States.TransitionFrom(OrderStates.MEMORIZE_STATE).DoOnNext += From_Memorize_2_All;
  78. States.TransitionTo(OrderStates.MEMORIZE_STATE).DoOnNext += From_All_2_Memorize;
  79. States.TransitionTo(OrderStates.NON_GAME_STATE).DoOnNext += this.From_All_2_NonGame;
  80. States.TransitionTo(OrderStates.POSITION_STATE).DoOnNext += From_All_2_Position;
  81. States.Transition(OrderStates.ZERO_STATE,OrderStates.NON_GAME_STATE).DoOnNext = Zero_2_NonGame;
  82. States.Transition(OrderStates.NON_GAME_STATE,OrderStates.MEMORIZE_STATE).DoOnNext += NonGame_2_Memorize;
  83. //States.Transition(OrderStates.MEMORIZE_STATE,OrderStates.POSITION_STATE).DoOnNext += Memorize_2_Position;
  84. States.TransitionContinuous(OrderStates.MEMORIZE_STATE, OrderStates.POSITION_STATE,false).AddCallback(Memorize_2_Position);
  85. // States.Transition(OrderStates.POSITION_STATE, OrderStates.NON_GAME_STATE).DoOnNext += Position_2_NonGame;
  86. States.TransitionContinuous(OrderStates.POSITION_STATE, OrderStates.GAME_COMPLETED_STATE,false).AddCallback(Position_2_GameCompleted);
  87. States.TransitionContinuous(OrderStates.GAME_COMPLETED_STATE, OrderStates.NON_GAME_STATE,false).AddCallback(GameCompleted_2_NonGame);
  88. }
  89. [ContractInvariantMethod]
  90. private void ObjectInvariant()
  91. {
  92. Contract.Invariant(this.Settings.ShowHints !=(this.States.Current == OrderStates.MEMORIZE_STATE || this.States.Current == OrderStates.POSITION_STATE));
  93. Contract.Invariant(Settings.ParamsEnabled== (this.States.Current==OrderStates.NON_GAME_STATE));
  94. // Contract.Invariant(this.Settings.SetupMemoAni().I);
  95. }
  96. #region From_All_2 STATE transitions
  97. /// <summary>
  98. /// Works every time the state changes
  99. /// </summary>
  100. /// <param name="transition"></param>
  101. private void EachTimeTransition(Transition<String> transition)
  102. {
  103. this.Settings.ButtonName = this.Settings.ButtonNames[transition.To];
  104. }
  105. private void From_All_2_NonGame(Transition<String> transition)
  106. {
  107. this.Settings.ShowHints = true;
  108. this.Settings.ParamsEnabled = true;
  109. }
  110. private void From_All_2_Memorize(Transition<String> transition)
  111. {
  112. this.Settings.InMemo = true;
  113. this.Settings.ShowHints = false;
  114. this.Settings.Results = this.Settings.Results.Add(new Results());
  115. }
  116. private void From_All_2_Position(Transition<String> transition)
  117. {
  118. this.Settings.ShowHints = false;
  119. }
  120. #endregion
  121. #region ACTIONS ON STATES
  122. private void On_Position_State(string state)
  123. {
  124. //writing time
  125. var r = Animator.LatestRender;
  126. this.States.TransitionFrom(OrderStates.POSITION_STATE).At().DoOnNext +=
  127. i => this.Settings.WriteTime(TimeSpan.FromMilliseconds(Animator.LatestRender - r));
  128. }
  129. #endregion
  130. #region TRANSITIONS BETWEEN STATES
  131. /// <summary>
  132. /// First transition
  133. /// </summary>
  134. /// <param name="transition"></param>
  135. private void Zero_2_NonGame(Transition<String> transition)
  136. {
  137. Contract.Requires(
  138. States.CurrentTransition.From == OrderStates.ZERO_STATE
  139. && States.CurrentTransition.To == OrderStates.NON_GAME_STATE
  140. && States.Current == OrderStates.ZERO_STATE);
  141. States.PossibleStates.Remove(OrderStates.ZERO_STATE);
  142. this.Settings.InMemo = false;
  143. //Imager.Init();
  144. }
  145. /// <summary>
  146. /// Transition which occurs when the player starts the game and goes to memorizing stage
  147. /// </summary>
  148. /// <param name="transition"></param>
  149. private void NonGame_2_Memorize(Transition<string> transition)
  150. {
  151. Contract.Requires(transition.From == OrderStates.NON_GAME_STATE && transition.To == OrderStates.MEMORIZE_STATE);
  152. // Contract.Ensures(false == (this.Field.DragEnabled && this.Tools.DragEnabled));
  153. Settings.SetupMemoAni().DoOnCompleted = this.States.GoToIfState(
  154. OrderStates.POSITION_STATE, OrderStates.MEMORIZE_STATE);
  155. Matrix.GenerateMatrix(Imager.CurrentImages, Settings.Icons.Value, Settings.Cols.Value, Settings.Rows.Value);
  156. //var nums = Matrix.Flatten(i => !i.Equals(Num2D.Emtpy)).ToList();
  157. var imgs = Matrix.NonEmptyIndexed()
  158. .Select(n => new Tuple<FrameworkElement, Point>(
  159. this.Imager.CurrentImages[n.Value]
  160. .SetColumn(n.Key.X).SetRow(n.Key.Y),
  161. new Point(1, 1))).ToList();
  162. var args = new MassiveRelativeResizeEvent(
  163. OrderEvents.APPEAR, imgs, new TimeSpan(0, 0, 0, 2), Easings.CubicEaseInOut);
  164. this.RunEvent(OrderEvents.APPEAR, args);
  165. //this.Field.DragEnabled = this.Tools.DragEnabled = false;
  166. }
  167. /// <summary>
  168. /// Transition which occures when the user comes from memorization to remembering and dragging
  169. /// </summary>
  170. /// <param name="transition"></param>
  171. private SimpleSubject<MoveToCellsEvent> Memorize_2_Position(Transition<string> transition)
  172. {
  173. Contract.Requires(transition.From == OrderStates.MEMORIZE_STATE && transition.To == OrderStates.POSITION_STATE);
  174. //Contract.Ensures(this.Field.DragEnabled && this.Tools.DragEnabled);
  175. var num = Num2D.Emtpy;
  176. var objects =
  177. Matrix.Flatten(i => !i.Equals(Num2D.Emtpy))
  178. .OrderBy(o => o.X).ThenBy(o => o.Y)
  179. .Select(
  180. o => new Tuple<FrameworkElement, CellsRegion>(
  181. this.Imager.CurrentImages[o], new CellsRegion(num.WrapInc(this.Settings.ToolsColsNum)))
  182. ).ToList();
  183. Contract.Assert(objects.Count == Settings.Icons.Value);
  184. return this.RunEvent(new MoveToCellsEvent(
  185. OrderEvents.MOVE_TO_INVENTORY, objects, new TimeSpan(0, 0, 0, 3), Easings.CubicEaseInOut));
  186. }
  187. private SimpleSubject<AnimationEvent<FrameworkElement>> Position_2_GameCompleted(Transition<string> obj)
  188. {
  189. this.RunEvent(OrderEvents.DISAPPEAR);
  190. this.Settings.Results.Head.Failures += this.Matrix.IconsLeft;
  191. this.Settings.ResultsUpdate();
  192. return this.RunEvent(new AnimationEvent<FrameworkElement>(OrderEvents.SHOW_POPUP, GameResults.Instance.WithDataContext(this.Settings), new TimeSpan(0, 0, 0, 1)));
  193. }
  194. private SimpleSubject<AnimationEvent<FrameworkElement>> GameCompleted_2_NonGame(Transition<string> obj)
  195. {
  196. return this.RunEvent(new AnimationEvent<FrameworkElement>(
  197. OrderEvents.HIDE_POPUP, GameResults.Instance, new TimeSpan(0, 0, 0, 1)));
  198. }
  199. #endregion
  200. #region TRANSITIONS like State_2_ALL
  201. private void From_NonGame_2_All(Transition<String> transition)
  202. {
  203. this.Settings.ParamsEnabled = false;
  204. }
  205. private void From_Memorize_2_All(Transition<String> transition)
  206. {
  207. this.Settings.InMemo = false;
  208. }
  209. private void From_Position_2_All(Transition<String> transition)
  210. {
  211. this.Settings.InMemo = false;
  212. this.Settings.ShowHints = true;
  213. }
  214. #endregion
  215. /// <summary>
  216. /// Decides if we should
  217. /// </summary>
  218. /// <param name="where"></param>
  219. /// <param name="what"></param>
  220. /// <returns></returns>
  221. public bool MoveElementTo(Num2D where, FrameworkElement what)
  222. {
  223. var pos = PicsManager.GetMemoryPosition(what);
  224. var num = this.Matrix[where];
  225. var allow = num.Equals(pos);
  226. if (allow)
  227. this.Matrix.IconsLeft -= 1;
  228. else
  229. this.Settings.Results.Head.Failures += 1;
  230. if (Matrix.IconsLeft == 0)
  231. this.States.GoTo(OrderStates.GAME_COMPLETED_STATE);
  232. return allow;
  233. }
  234. #region EVENT HOLDER IMPLEMENTATION
  235. public SimpleSubject<TEventArgs> RunEvent<TEventArgs>(string name, TEventArgs eventArgs)
  236. {
  237. return this.EventManager.RunEvent(name,eventArgs);
  238. }
  239. public bool HasEvent<TEvenrArgs>(string name)
  240. {
  241. return EventManager.HasEvent<TEvenrArgs>(name);
  242. }
  243. public SimpleSubject<TEventArgs> RunEvent<TEventArgs>(TEventArgs eventArgs) where TEventArgs : INamed
  244. {
  245. return EventManager.RunEvent(eventArgs);
  246. }
  247. public SimpleSubject<TEventArgs> RouteEventTo<TEventArgs>(string name, IEventsHolder where)
  248. {
  249. return this.EventManager.RouteEventTo<TEventArgs>(name, where);
  250. }
  251. public SimpleSubject<String> RunEvent(string eventArgs)
  252. {
  253. return EventManager.RunEvent(eventArgs);
  254. }
  255. public SmartEventManager EventManager { get; private set; }
  256. #endregion
  257. }
  258. }