/* * MiniGameManager.cs * Authors: Mike DeMauro * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.IO; using System.Text; using Util; namespace ColonySim { /// /// This class loads and saves mini game statistics /// The statistics are used to choose the next minigame to prompt. /// This class tracks time interval between mini game prompts, /// and modifies the interval using the statistics. /// internal class MiniGameManager { #region Fields private const string DATA_FILE = "MiniGameStatistics.dat"; private readonly MiniGameInfo[] mMiniGames; private MiniGameInfo mCurrentMiniGame; #region //TODO: make configurable //Default amount of time between mini game prompts (in seconds) private const double mDefaultInterval = 300; //Max amount of time between mini game prompts (in seconds) private const double mMaxInterval = 500; //Min amount of time between mini game prompts (in seconds) private const double mMinInterval = 100; //Amount of time the interval is reduced by per rejection (in seconds) private const double mTimePenaltyPerRejection = 5; #endregion private double mCurrentInterval; private double mTimer; #endregion #region Properties public MiniGameInfo CurrentMiniGame { get { return mCurrentMiniGame; } set { mCurrentMiniGame = value; } } public double CurrentInterval { get { return mCurrentInterval; } } public double Timer { get { return mTimer; } set { mTimer = value; } } #endregion public MiniGameManager() { mMiniGames = AssemblyLocator.AllKnownMiniGames.ToArray(); loadMinigameStatistics(); mCurrentInterval = mDefaultInterval; } /// /// Reads the minigame statistics from file /// private void loadMinigameStatistics() { if(File.Exists(GameScreen.GlobalRootStorageDirectory + UserProfileUtility.OutputDirectory + DATA_FILE)) { string[] data = File.ReadAllLines(GameScreen.GlobalRootStorageDirectory + UserProfileUtility.OutputDirectory + DATA_FILE); for(int i = 0; i < data.Length; i+=4) { foreach(MiniGameInfo m in mMiniGames) { if (m.DisplayName == data[i]) { m.NumPlayed = int.Parse(data[i + 1]); m.NumPrompts = int.Parse(data[i + 1]); m.NumRejects = int.Parse(data[i + 1]); } } } } } /// /// Writes the minigame statistics to file /// private void saveMinigameStatistics() { StringBuilder sb = new StringBuilder(); foreach (MiniGameInfo m in mMiniGames) { sb.AppendLine(m.DisplayName); sb.AppendLine(m.NumPlayed.ToString()); sb.AppendLine(m.NumPrompts.ToString()); sb.AppendLine(m.NumRejects.ToString()); } if (sb.Length > 0) { File.WriteAllText(GameScreen.GlobalRootStorageDirectory + UserProfileUtility.OutputDirectory + DATA_FILE, sb.ToString()); } } /// /// Sets the current mini game to a randomly chosen one /// public MiniGameInfo GetRandomMiniGame() { int totalWeight = 0; int[] weights = new int[mMiniGames.Length]; for(int i = 0; i < mMiniGames.Length; ++i) { weights[i] = 1 + Math.Max(mMiniGames[i].NumRejects - mMiniGames[i].NumPlayed, 0); totalWeight += weights[i]; } int weight = Util.Random.Next(totalWeight); for (int i = 0; i < weights.Length; ++i) { if (weights[i] > weight) { return mMiniGames[i]; } weight -= weights[i]; } throw new Exception("This shouldn't happen, mathematically."); } /// /// Resets the timer. /// public void ResetTimer() { mTimer = 0f; } /// /// Updates the CurrentInterval based on mini game statistics /// /// /// TODO /// public void UpdateInterval() { double delta = 0; foreach (MiniGameInfo m in mMiniGames) { delta += m.NumRejects - m.NumPlayed; } mCurrentInterval = mDefaultInterval - delta * mTimePenaltyPerRejection; if (mCurrentInterval < mMinInterval) { mCurrentInterval = mMinInterval; } else if(mCurrentInterval > mMaxInterval) { mCurrentInterval = mMaxInterval; } } } }