/*
* 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;
}
}
}
}