/SudokuGrabber/ARSudokuSolver/src/com/sudoku/gui/Timer.java

https://github.com/tigerking/sudoku-grabber · Java · 289 lines · 95 code · 53 blank · 141 comment · 9 complexity · b20cc0bec73a493316100c6adee8fed8 MD5 · raw file

  1. /**
  2. * NetScramble: unscramble a network and connect all the terminals.
  3. *
  4. * This is an Android implementation of the KDE game "knetwalk".
  5. * The player is given a network diagram with the parts of the network
  6. * randomly rotated; he/she must rotate them to connect all the terminals
  7. * to the server.
  8. *
  9. * Original author:
  10. * QNetwalk, Copyright (C) 2004, Andi Peredri <andi@ukr.net>
  11. *
  12. * Ported to kde by:
  13. * Thomas Nagy <tnagyemail-mail@yahoo@fr>
  14. *
  15. * Cell-locking implemented by:
  16. * Reinhold Kainhofer <reinhold@kainhofer.com>
  17. *
  18. * Ported to Android by:
  19. * Ian Cameron Smith <johantheghost@yahoo.com>
  20. *
  21. * This program is free software; you can redistribute it and/or modify
  22. * it under the terms of the GNU General Public License version 2
  23. * as published by the Free Software Foundation (see COPYING).
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. * GNU General Public License for more details.
  29. */
  30. package com.sudoku.gui;
  31. import android.os.Bundle;
  32. import android.os.Handler;
  33. import android.os.SystemClock;
  34. /**
  35. * This class implements a simple periodic timer.
  36. */
  37. abstract class Timer
  38. extends Handler
  39. {
  40. // ******************************************************************** //
  41. // Constructor.
  42. // ******************************************************************** //
  43. /**
  44. * Construct a periodic timer with a given tick interval.
  45. *
  46. * @param ival Tick interval in ms.
  47. */
  48. public Timer(long ival) {
  49. mTickInterval = ival;
  50. mIsRunning = false;
  51. mAccumTime = 0;
  52. }
  53. // ******************************************************************** //
  54. // Timer Control.
  55. // ******************************************************************** //
  56. /**
  57. * Start the timer. step() will be called at regular intervals
  58. * until it returns true; then done() will be called.
  59. *
  60. * Subclasses may override this to do their own setup; but they
  61. * must then call super.start().
  62. */
  63. public void start() {
  64. if (mIsRunning)
  65. return;
  66. mIsRunning = true;
  67. long now = SystemClock.uptimeMillis();
  68. // Start accumulating time again.
  69. mLastLogTime = now;
  70. // Schedule the first event at once.
  71. mNextTime = now;
  72. postAtTime(runner, mNextTime);
  73. }
  74. /**
  75. * Stop the timer. step() will not be called again until it is
  76. * restarted.
  77. *
  78. * Subclasses may override this to do their own setup; but they
  79. * must then call super.stop().
  80. */
  81. public void stop() {
  82. if (mIsRunning) {
  83. mIsRunning = false;
  84. long now = SystemClock.uptimeMillis();
  85. mAccumTime += now - mLastLogTime;
  86. mLastLogTime = now;
  87. }
  88. }
  89. /**
  90. * Stop the timer, and reset the accumulated time and tick count.
  91. */
  92. public final void reset() {
  93. stop();
  94. mTickCount = 0;
  95. mAccumTime = 0;
  96. }
  97. /**
  98. * Query whether this Timer is running.
  99. *
  100. * @return true iff we're running.
  101. */
  102. public final boolean isRunning() {
  103. return mIsRunning;
  104. }
  105. /**
  106. * Get the accumulated time of this Timer.
  107. *
  108. * @return How long this timer has been running, in ms.
  109. */
  110. public final long getTime() {
  111. return mAccumTime;
  112. }
  113. // ******************************************************************** //
  114. // Handlers.
  115. // ******************************************************************** //
  116. /**
  117. * Subclasses override this to handle a timer tick.
  118. *
  119. * @param count The call count; 0 on the first call.
  120. * @param time The total time for which this timer has been
  121. * running, in ms. Reset by reset().
  122. * @return true if the timer should stop; this will
  123. * trigger a call to done(). false otherwise;
  124. * we will continue calling step().
  125. */
  126. protected abstract boolean step(int count, long time);
  127. /**
  128. * Subclasses may override this to handle completion of a run.
  129. */
  130. protected void done() { }
  131. // ******************************************************************** //
  132. // Implementation.
  133. // ******************************************************************** //
  134. /**
  135. * Handle a step of the animation.
  136. */
  137. private final Runnable runner = new Runnable() {
  138. public final void run() {
  139. if (mIsRunning) {
  140. long now = SystemClock.uptimeMillis();
  141. // Add up the time since the last step.
  142. mAccumTime += now - mLastLogTime;
  143. mLastLogTime = now;
  144. if (!step(mTickCount++, mAccumTime)) {
  145. // Schedule the next. If we've got behind, schedule
  146. // it for a tick after now. (Otherwise we'd end
  147. // up with a zillion events queued.)
  148. mNextTime += mTickInterval;
  149. if (mNextTime <= now)
  150. mNextTime += mTickInterval;
  151. postAtTime(runner, mNextTime);
  152. } else {
  153. mIsRunning = false;
  154. done();
  155. }
  156. }
  157. }
  158. };
  159. // ******************************************************************** //
  160. // State Save/Restore.
  161. // ******************************************************************** //
  162. /**
  163. * Save game state so that the user does not lose anything
  164. * if the game process is killed while we are in the
  165. * background.
  166. *
  167. * @param outState A Bundle in which to place any state
  168. * information we wish to save.
  169. */
  170. void saveState(Bundle outState) {
  171. // Accumulate all time up to now, so we know where we're saving.
  172. if (mIsRunning) {
  173. long now = SystemClock.uptimeMillis();
  174. mAccumTime += now - mLastLogTime;
  175. mLastLogTime = now;
  176. }
  177. outState.putLong("tickInterval", mTickInterval);
  178. outState.putBoolean("isRunning", mIsRunning);
  179. outState.putInt("tickCount", mTickCount);
  180. outState.putLong("accumTime", mAccumTime);
  181. }
  182. /**
  183. * Restore our game state from the given Bundle. If the saved
  184. * state was running, we will continue running.
  185. *
  186. * @param map A Bundle containing the saved state.
  187. * @return true if the state was restored OK; false
  188. * if the saved state was incompatible with the
  189. * current configuration.
  190. */
  191. boolean restoreState(Bundle map) {
  192. return restoreState(map, true);
  193. }
  194. /**
  195. * Restore our game state from the given Bundle.
  196. *
  197. * @param map A Bundle containing the saved state.
  198. * @param run If true, restore the saved runnning state;
  199. * otherwise restore to a stopped state.
  200. * @return true if the state was restored OK; false
  201. * if the saved state was incompatible with the
  202. * current configuration.
  203. */
  204. boolean restoreState(Bundle map, boolean run) {
  205. mTickInterval = map.getLong("tickInterval");
  206. mIsRunning = map.getBoolean("isRunning");
  207. mTickCount = map.getInt("tickCount");
  208. mAccumTime = map.getLong("accumTime");
  209. mLastLogTime = SystemClock.uptimeMillis();
  210. // If we were running, restart if requested, else stop.
  211. if (mIsRunning) {
  212. if (run)
  213. start();
  214. else
  215. mIsRunning = false;
  216. }
  217. return true;
  218. }
  219. // ******************************************************************** //
  220. // Member Data.
  221. // ******************************************************************** //
  222. // The tick interval in ms.
  223. private long mTickInterval = 0;
  224. // true iff the timer is running.
  225. private boolean mIsRunning = false;
  226. // Number of times step() has been called.
  227. private int mTickCount;
  228. // Time at which to execute the next step. We schedule each
  229. // step at this plus x ms; this gives us an even execution rate.
  230. private long mNextTime;
  231. // The accumulated time in ms for which this timer has been running.
  232. // Increments between start() and stop(); start(true) resets it.
  233. private long mAccumTime;
  234. // The time at which we last added to accumTime.
  235. private long mLastLogTime;
  236. }