using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Timers;
namespace AutobotManager
{
public class BotClass : INotifyPropertyChanged
{
public BotClass(int a_iBotInstanceId
, int a_iBotId
, String a_sAppPath
, String a_sBotLogic
, int a_iBotLogic
, String a_sAppArgs
, Form1 a_pParentForm
, BotManager a_pParentManager
)
{
m_iStdOutTraceCount = 0;
m_iStdErrTraceCount = 0;
m_iBotInctanceId = a_iBotInstanceId;
m_iBotId = a_iBotId;
m_sAppPath = a_sAppPath;
m_sBotLogic = a_sBotLogic;
m_iBotLogic = a_iBotLogic;
m_sAppArgs = a_sAppArgs;
m_StartTime = DateTime.Now;
m_pParentForm = a_pParentForm;
m_pParentManager = a_pParentManager;
String sWorkingDirectory = System.IO.Path.GetDirectoryName(a_sAppPath);
m_processCaller = new ProcessCaller(a_pParentForm);
m_processCaller.FileName = a_sAppPath;
m_processCaller.Arguments = a_sAppArgs;
m_processCaller.WorkingDirectory = sWorkingDirectory;
m_processCaller.m_pParent = this;
m_sLuaBotState = "NOT_SET";
m_processCaller.StdErrReceived += new DataReceivedHandler(this.writeErrorStream);
m_processCaller.StdOutReceived += new DataReceivedHandler(this.writeOutputStream);
m_processCaller.Completed += new EventHandler(this.processCompletedOrCanceled);
m_processCaller.Cancelled += new EventHandler(this.processCompletedOrCanceled);
m_processCaller.Failed += new System.Threading.ThreadExceptionEventHandler(this.processFailed);
m_eBotState = BotState.BotState_IDLE;
}
#region Methods
public BotState GetBotState() { return m_eBotState; }
public void SetBotState(BotState a_eState)
{
BotState a_eOldState = m_eBotState;
if (a_eOldState != a_eState)
{
m_eBotState = a_eState;
OnPropertyChanged("m_eBotState");
if (null != m_pParentManager)
m_pParentManager.BotStateChanged(this, a_eOldState);
}
}
public String GetLuaBotState() { return m_sLuaBotState; }
public void SetLuaBotState(String a_sState)
{
if (!m_sLuaBotState.Equals(a_sState))
{
String sOld = m_sLuaBotState;
m_sLuaBotState = a_sState;
OnPropertyChanged("m_sLuaBotState");
if (null != m_pParentManager)
m_pParentManager.BotLuaStatusChanged(this, sOld);
}
}
private void ParseLuaState(String a_sInput)
{
string sStatusStart = "BotStatus[";
int iStatusStartLen = sStatusStart.Length;
int iInputLen = a_sInput.Length;
int iIndex = a_sInput.LastIndexOf(sStatusStart);
if (iIndex >= 0 && (iIndex + iStatusStartLen) < iInputLen)
{
int iStartIndex = iIndex + iStatusStartLen;
int iEndIndex = a_sInput.IndexOf("]", iStartIndex);
if (iEndIndex > 0 && iEndIndex > iStartIndex)
{
SetLuaBotState(a_sInput.Substring(iStartIndex, iEndIndex - iStartIndex));
}
}
}
private void ParseMetrics(String a_sInput)
{
string sStatusStart = "BotMetricOn[";
string sStatusEnd = "]BotMetricOff";
int iStatusStartLen = sStatusStart.Length;
int iStatusEndLen = sStatusEnd.Length;
int iInputLen = a_sInput.Length;
int iCursor = 0;
do
{
int iStarting = a_sInput.IndexOf(sStatusStart, iCursor);
if(iStarting>=0)
{
iCursor += iStarting+iStatusStartLen;
if(iCursor<iInputLen)
{
int iLoc = a_sInput.IndexOf(sStatusEnd, iCursor);
if(iLoc > iCursor)
{
string sMetric = a_sInput.Substring(iCursor, iLoc-iCursor);
if (null != m_pParentManager)
m_pParentManager.BotMetricEncountered(this, sMetric);
iCursor += iLoc + iStatusEndLen;
}
else
{
iCursor = iInputLen;
}
}
}
else
{
iCursor = iInputLen;
}
}while (iCursor < iInputLen);
}
private int CustomStripStringOccurrences(ref String a_sInput, string sPattern)
{
int iLen = a_sInput.Length;
a_sInput = a_sInput.Replace(sPattern, "");
iLen -= a_sInput.Length;
int iCount = iLen / sPattern.Length;
if (iCount > 0 && 1 == a_sInput.Length && a_sInput[0] == '\n')
{
a_sInput = "";
}
return iCount;
}
private bool ParseTraced(ref String a_sInput, ref int a_iTraceCounter)
{
string sTraceStartString = "BOT_" + m_iBotId.ToString() + "_TraceOn[";
int iStartCount = CustomStripStringOccurrences(ref a_sInput, sTraceStartString);
bool bTrace = (a_iTraceCounter > 0 || iStartCount > 0);
a_iTraceCounter += iStartCount;
if (bTrace)
{
string sTraceEndString = "]BOT_" + m_iBotId.ToString() + "_TraceOff";
int iEndCount = CustomStripStringOccurrences(ref a_sInput, sTraceEndString);
a_iTraceCounter -= iEndCount;
}
return bTrace;
}
public void writeOutputStream(object sender, DataReceivedEventArgs e)
{
string sNew = e.Text;
bool bForceLog = ParseTraced(ref sNew, ref m_iStdOutTraceCount); // this will strip off the unnecessary trace commands
ParseLuaState(sNew);
ParseMetrics(sNew);
if (null != m_pParentForm)
m_pParentForm.MyLog(this, sNew, false, bForceLog);
}
public void writeErrorStream(object sender, DataReceivedEventArgs e)
{
string sNew = e.Text;
ParseLuaState(sNew);
bool bForceLog = ParseTraced(ref sNew, ref m_iStdErrTraceCount);
if (null != m_pParentForm)
m_pParentForm.MyLog(this, sNew, true, bForceLog);
}
public void processCompletedOrCanceled(object sender, EventArgs e)
{
if (GetBotState() != BotState.BotState_Dying)
{
if (null != m_pParentForm)
m_pParentForm.MyLog(this, "CRASHED-1", true, true);
}
else
{
if (null != m_pParentForm)
m_pParentForm.MyLog(this, "SHUTDOWN-1", false, true);
}
if (null != m_pParentManager)
m_pParentManager.BotDied(this);
}
public void processFailed(object sender, System.Threading.ThreadExceptionEventArgs e)
{
if (GetBotState() != BotState.BotState_Dying)
{
if (null != m_pParentForm)
m_pParentForm.MyLog(this, "CRASHED-2", true, true);
}
else
{
if (null != m_pParentForm)
m_pParentForm.MyLog(this, "SHUTDOWN-2", false, true);
}
if (null != m_pParentManager)
m_pParentManager.BotDied(this);
}
public void Start()
{
SetBotState(BotState.BotState_Running);
m_StartTime = DateTime.Now;
m_processCaller.Start();
}
public void Cancel()
{
SetBotState(BotState.BotState_Dying);
m_processCaller.Cancel();
}
public void ForceCancel()
{
m_pParentForm = null;
m_pParentManager = null;
SetBotState(BotState.BotState_Dying);
m_processCaller.Cancel();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var h = PropertyChanged;
if (null != h) h(this, new PropertyChangedEventArgs(propertyName));
}
#endregion // Methods
#region Data
private int m_iStdOutTraceCount;
private int m_iStdErrTraceCount;
private int m_iBotInctanceId;
private int m_iBotId;
private BotState m_eBotState;
private int m_iBotLogic;
private String m_sBotLogic;
private String m_sLuaBotState;
private ProcessCaller m_processCaller;
private DateTime m_StartTime;
private Form1 m_pParentForm;
private BotManager m_pParentManager;
private String m_sAppArgs;
private String m_sAppPath;
[DisplayName("Instance")]
[ReadOnly(true)]
public int BotInctanceId { get { return this.m_iBotInctanceId; } set { if (value != this.m_iBotInctanceId) { this.m_iBotInctanceId = value; OnPropertyChanged("m_iBotInctanceId"); } } }
[DisplayName("Bot ID")]
[ReadOnly(true)]
public int BotId { get { return this.m_iBotId; } set { if (value != this.m_iBotId) { this.m_iBotId = value; OnPropertyChanged("m_iBotId"); } } }
[DisplayName("Process State")]
[ReadOnly(true)]
public BotState ProcessState { get { return this.m_eBotState; } set { if (value != this.m_eBotState) { this.m_eBotState = value; OnPropertyChanged("m_eBotState"); } } }
[DisplayName("Bot Logic")]
[ReadOnly(true)]
public String BotLogic { get { return this.m_sBotLogic; } set { if (value != this.m_sBotLogic) { this.m_sBotLogic = value; OnPropertyChanged("m_sBotLogic"); } } }
[DisplayName("Lua State")]
[ReadOnly(true)]
public String LuaBotState { get { return this.m_sLuaBotState; } set { if (value != this.m_sLuaBotState) { this.m_sLuaBotState = value; OnPropertyChanged("m_sLuaBotState"); } } }
[Browsable(false)]
public int BotLogicID { get { return this.m_iBotLogic; } set { if (value != this.m_iBotLogic) { this.m_iBotLogic = value; OnPropertyChanged("m_iBotLogic"); } } }
[Browsable(false)]
public DateTime StartTime { get { return this.m_StartTime; } set { if (value != this.m_StartTime) { this.m_StartTime = value; OnPropertyChanged("m_StartTime"); } } }
#endregion //Data
};
}