Newer
Older
Import / projects / Gameloft / bne_lib / tools / AutobotManager / src / BotClass.cs
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
    };
}