1 /* 2 * Copyright (C) 2007 Jordi Mas i Hernàndez <jmas@softcatala.org> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public 15 * License along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 using System; 19 using System.Timers; 20 using System.ComponentModel; 21 22 using gbrainy.Core.Views; 23 using gbrainy.Core.Services; 24 25 namespace gbrainy.Core.Main 26 { 27 public class GameSession : IDrawable, IDrawRequest, IMouseEvent 28 { 29 [Flags] 30 public enum Types 31 { 32 None = 0, 33 LogicPuzzles = 2, 34 Memory = 4, 35 Calculation = 8, 36 VerbalAnalogies = 16, 37 Custom = 32, 38 AllGames = Memory | Calculation | LogicPuzzles | VerbalAnalogies 39 } 40 41 public enum SessionStatus 42 { 43 NotPlaying, 44 Playing, 45 Answered, 46 Finished, 47 } 48 49 private TimeSpan game_time; 50 private Game current_game; 51 private GameManager game_manager; 52 private System.Timers.Timer timer; 53 private bool paused; 54 private TimeSpan one_sec = TimeSpan.FromSeconds (1); 55 private SessionStatus status; 56 private ViewsControler controler; 57 private ISynchronizeInvoke synchronize; 58 private PlayerHistory player_history; 59 private int id; 60 private GameSessionHistoryExtended history; 61 private GameSessionPlayList play_list; 62 63 public event EventHandler DrawRequest; 64 public event EventHandler <UpdateUIStateEventArgs> UpdateUIElement; 65 66 GameSession(ITranslations translations)67 public GameSession (ITranslations translations) 68 { 69 Translations = translations; 70 id = 0; 71 game_manager = new GameManager (); 72 play_list = new GameSessionPlayList (game_manager); 73 game_time = TimeSpan.Zero; 74 75 timer = new System.Timers.Timer (); 76 timer.Elapsed += TimerUpdater; 77 timer.Interval = (1 * 1000); // 1 second 78 79 controler = new ViewsControler (translations, this); 80 Status = SessionStatus.NotPlaying; 81 player_history = new PlayerHistory (); 82 history = new GameSessionHistoryExtended (); 83 } 84 85 public int ID { 86 get {return id;} 87 } 88 89 public GameSessionHistoryExtended History { 90 get {return history;} 91 } 92 93 public GameTypes AvailableGames { 94 get { return game_manager.AvailableGameTypes; } 95 } 96 97 public PlayerHistory PlayerHistory { 98 set { player_history = value; } 99 get { return player_history; } 100 } 101 102 public ISynchronizeInvoke SynchronizingObject { 103 set { synchronize = value; } 104 get { return synchronize; } 105 } 106 107 public Types Type { 108 get { return play_list.GameType; } 109 set { play_list.GameType = value; } 110 } 111 112 public GameDifficulty Difficulty { 113 get { return play_list.Difficulty; } 114 set { play_list.Difficulty = value; } 115 } 116 117 public string GameTime { 118 get { return TimeSpanToStr (game_time);} 119 } 120 121 public bool Paused { 122 get {return paused; } 123 set {paused = value; } 124 } 125 126 public GameSessionPlayList PlayList { 127 get { return play_list; } 128 set { play_list = value; } 129 } 130 131 public Game CurrentGame { 132 get {return current_game; } 133 set { 134 current_game = value; 135 controler.Game = value; 136 } 137 } 138 139 public bool EnableTimer { 140 get {return timer.Enabled; } 141 set {timer.Enabled = value; } 142 } 143 144 public SessionStatus Status { 145 get {return status; } 146 set { 147 status = value; 148 controler.Status = value; 149 150 if (status == SessionStatus.Answered && CurrentGame != null) 151 CurrentGame.EnableMouseEvents (false); 152 } 153 } 154 155 public GameManager GameManager { 156 get { return game_manager;} 157 set { 158 game_manager = value; 159 play_list.GameManager = value; 160 } 161 } 162 163 public string TimePerGame { 164 get { 165 TimeSpan average; 166 167 average = (history.GamesPlayed > 0) ? TimeSpan.FromSeconds (game_time.TotalSeconds / history.GamesPlayed) : game_time; 168 return TimeSpanToStr (average); 169 } 170 } 171 172 private ITranslations Translations { get; set; } 173 174 public string StatusText { 175 get { 176 if (Status == SessionStatus.NotPlaying || Status == SessionStatus.Finished) 177 return string.Empty; 178 179 string played, time, game; 180 181 played = String.Format (Translations.GetString ("Games played: {0} (Score: {1})"), history.GamesPlayed, history.TotalScore); 182 time = String.Format (Translations.GetString ("Time: {0}"), 183 paused == false ? GameTime : Translations.GetString ("Paused")); 184 185 if (CurrentGame != null) { 186 // Translators: {0} is the name of the game 187 game = String.Format (Translations.GetString ("Game: {0}"), CurrentGame.Name); 188 // Translators: text in the status bar: games played - time - game name 189 return String.Format (Translations.GetString ("{0} - {1} - {2}"), played, time, game); 190 } else { 191 // Translators: text in the status bar: games played - time 192 return String.Format (Translations.GetString ("{0} - {1}"), played, time); 193 } 194 } 195 } 196 New()197 public void New () 198 { 199 if (Type == Types.None) 200 throw new InvalidOperationException ("You have to setup the GameSession type"); 201 202 id++; 203 if (Status != SessionStatus.NotPlaying) 204 End (); 205 206 history.Clear (); 207 game_time = TimeSpan.Zero; 208 timer.SynchronizingObject = SynchronizingObject; 209 EnableTimer = true; 210 } 211 End()212 public void End () 213 { 214 // Making a deep copy of GameSessionHistory type (base class) for serialization 215 player_history.SaveGameSession (history.Copy ()); 216 217 if (CurrentGame != null) { 218 CurrentGame.DrawRequest -= GameDrawRequest; 219 CurrentGame.UpdateUIElement -= GameUpdateUIElement; 220 CurrentGame.Finish (); 221 } 222 223 EnableTimer = false; 224 timer.SynchronizingObject = null; 225 226 paused = false; 227 CurrentGame = null; 228 Status = SessionStatus.Finished; 229 } 230 NextGame()231 public void NextGame () 232 { 233 try 234 { 235 if (CurrentGame != null) { 236 CurrentGame.DrawRequest -= GameDrawRequest; 237 CurrentGame.UpdateUIElement -= GameUpdateUIElement; 238 CurrentGame.Finish (); 239 } 240 241 history.GamesPlayed++; 242 CurrentGame = play_list.GetPuzzle (); 243 CurrentGame.Translations = Translations; 244 CurrentGame.SynchronizingObject = SynchronizingObject; 245 CurrentGame.DrawRequest += GameDrawRequest; 246 CurrentGame.UpdateUIElement += GameUpdateUIElement; 247 248 CurrentGame.Begin (); 249 250 CurrentGame.GameTime = TimeSpan.Zero; 251 Status = SessionStatus.Playing; 252 } 253 catch (Exception e) 254 { 255 Console.WriteLine ("GameSession.NextGame {0}", e); 256 } 257 } 258 Pause()259 public void Pause () 260 { 261 EnableTimer = false; 262 paused = true; 263 264 if (CurrentGame != null) 265 CurrentGame.EnableMouseEvents (false); 266 } 267 Resume()268 public void Resume () 269 { 270 EnableTimer = true; 271 paused = false; 272 273 if (CurrentGame != null) 274 CurrentGame.EnableMouseEvents (true); 275 } 276 ScoreGame(string answer)277 public bool ScoreGame (string answer) 278 { 279 int game_score; 280 281 if (CurrentGame == null || Status == SessionStatus.Answered) 282 return false; 283 284 game_score = CurrentGame.Score (answer); 285 history.UpdateScore (CurrentGame.Type, Difficulty, game_score); 286 287 Status = SessionStatus.Answered; 288 return (game_score > 0 ? true : false); 289 } 290 TimerUpdater(object source, ElapsedEventArgs e)291 private void TimerUpdater (object source, ElapsedEventArgs e) 292 { 293 lock (this) { 294 if (CurrentGame == null) 295 return; 296 297 game_time = game_time.Add (one_sec); 298 CurrentGame.GameTime = CurrentGame.GameTime + one_sec; 299 } 300 301 if (UpdateUIElement == null) 302 return; 303 304 UpdateUIElement (this, new UpdateUIStateEventArgs (UpdateUIStateEventArgs.EventUIType.Time, null)); 305 } 306 TimeSpanToStr(TimeSpan time)307 static private string TimeSpanToStr (TimeSpan time) 308 { 309 DateTime dtime; 310 311 // Convert it to DateTime to be able to use CultureSensitive formatting 312 dtime = new DateTime (1970, 1, 1, time.Hours, time.Minutes, time.Seconds); 313 314 return dtime.Hour > 0 ? dtime.ToString ("hh:mm:ss") : dtime.ToString ("mm:ss"); 315 } 316 GameUpdateUIElement(object obj, UpdateUIStateEventArgs args)317 public void GameUpdateUIElement (object obj, UpdateUIStateEventArgs args) 318 { 319 if (UpdateUIElement != null) 320 UpdateUIElement (this, args); 321 } 322 323 // A game has requested a redraw, scale the request to the object 324 // subscribed to GameSession.GameDrawRequest GameDrawRequest(object o, EventArgs args)325 public void GameDrawRequest (object o, EventArgs args) 326 { 327 if (DrawRequest != null) 328 DrawRequest (this, EventArgs.Empty); 329 } 330 Draw(CairoContextEx gr, int width, int height, bool rtl)331 public virtual void Draw (CairoContextEx gr, int width, int height, bool rtl) 332 { 333 controler.CurrentView.Draw (gr, width, height, rtl); 334 } 335 MouseEvent(object obj, MouseEventArgs args)336 public void MouseEvent (object obj, MouseEventArgs args) 337 { 338 if (controler.CurrentView as IMouseEvent != null) 339 (controler.CurrentView as IMouseEvent).MouseEvent (this, args); 340 } 341 } 342 } 343