Example #1
0
void CMUSHclientDoc::ResetOneTimer (CTimer * timer_item)
  {
CmcDateTime tNow = CmcDateTime::GetTimeNow();
CmcDateTimeSpan tsOneDay (1, 0, 0, 0);

  if (!timer_item->bEnabled)    // ignore un-enabled timers
    return;

// so we can see when it is likely to fire next 

  timer_item->tWhenFired = tNow;

// for timers that go off "at" a time, find today's date, and move the time in

  if (timer_item->iType == CTimer::eAtTime)
    {

    timer_item->tFireTime = CmcDateTime (tNow.GetYear (), tNow.GetMonth (), 
                                         tNow.GetDay (),  timer_item->iAtHour, 
                                         timer_item->iAtMinute, timer_item->fAtSecond);

// if this time has passed, go onto tomorrow

    if (timer_item->tFireTime < tNow)
      timer_item->tFireTime += tsOneDay;
    }
  else    // for periodic timers, find "now" and add the period to it
    timer_item->tFireTime = tNow + CmcDateTimeSpan (0,    // now plus the interval
                                              timer_item->iEveryHour, 
                                              timer_item->iEveryMinute, 
                                              timer_item->fEverySecond)
                                 - CmcDateTimeSpan (0,    // minus the offset
                                              timer_item->iOffsetHour, 
                                              timer_item->iOffsetMinute, 
                                              timer_item->fOffsetSecond);

  } // end of CMUSHclientDoc::ResetOneTimer
Example #2
0
void CMUSHclientDoc::CheckTimerList (CTimerMap & TimerMap)
  {
CTimer * timer_item;
CString strTimerName;
CmcDateTime tNow = CmcDateTime::GetTimeNow();
CmcDateTimeSpan tsOneDay (1, 0, 0, 0);

// check for deleted chat sessions

  for (POSITION chatpos = m_ChatList.GetHeadPosition (); chatpos; )
    {
    POSITION oldpos = chatpos;
    CChatSocket * pSocket = m_ChatList.GetNext (chatpos);
    if (pSocket->m_bDeleteMe)
      {
      m_ChatList.RemoveAt (oldpos);
      delete pSocket;
      break;    // list is no longer valid
      }
    }

  set <string> firedTimersList;
  POSITION pos;

// iterate through all timers for this document - first build list of them

  for (pos = TimerMap.GetStartPosition(); pos; )
    {


    TimerMap.GetNextAssoc (pos, strTimerName, timer_item);

    if (!timer_item->bEnabled)    // ignore un-enabled timers
      continue;

    // no timer activity whilst closed or in the middle of connecting, or if not enabled

    if (!timer_item->bActiveWhenClosed)
      if (m_iConnectPhase != eConnectConnectedToMud)
        continue;

    // if not ready to fire yet, ignore it

    if (timer_item->tFireTime > tNow)
      continue;

    firedTimersList.insert ((LPCTSTR) strTimerName);       // add to list of fired timers
    }


  // now process list, checking timer still exists in case a script deleted one
  // see: http://www.gammon.com.au/forum/?id=10358

  for (set <string>::iterator it = firedTimersList.begin ();
       it != firedTimersList.end ();
       it++)
    {
    // get next fired timer from list
    strTimerName = it->c_str ();

    // check still exists, get pointer if so
    if (!TimerMap.Lookup (strTimerName, timer_item))
      continue;

    timer_item->nMatched++;   // count timer matches
    timer_item->tWhenFired = tNow;  // when it fired

    m_iTimersFiredCount++;
    m_iTimersFiredThisSessionCount++;

//    TRACE1 ("Fired at = %10.8f\n", timer_item->tWhenFired.m_dt);

    if (timer_item->strLabel.IsEmpty ())
      Trace ("Fired unlabelled timer ");
    else
      Trace ("Fired timer %s", (LPCTSTR) timer_item->strLabel);

//    TRACE1 ("Fire time = %10.8f\n", timer_item->tFireTime.m_dt);

// update fire time - before calling the script, in case it takes a long time

    if (timer_item->iType == CTimer::eAtTime)
      timer_item->tFireTime += tsOneDay;
    else
      timer_item->tFireTime += CmcDateTimeSpan (0,    // add the interval
                                          timer_item->iEveryHour, 
                                          timer_item->iEveryMinute, 
                                          timer_item->fEverySecond);

    // in case clock changes or some such thing, make sure timer will be due to
    // fire in the future, not the past, or it might go mad and keep firing

    if (timer_item->tFireTime <= tNow)
      ResetOneTimer (timer_item);

    // if one-shot, disable it, so if the timer routine finds it again while
    // it is still executing (eg. due to a syntax error dialog box) then
    // it won't fire again.

    if (timer_item->bOneShot)
      timer_item->bEnabled = false;


// send timer message, if this timer list is "active"

    CString strExtraOutput;

    timer_item->bExecutingScript = true;     // cannot be deleted now
    m_iCurrentActionSource = eTimerFired;
    SendTo (timer_item->iSendTo, 
            timer_item->strContents, 
            timer_item->bOmitFromOutput, // omit from output
            timer_item->bOmitFromLog,    // omit from log
            TFormat ("Timer: %s", (LPCTSTR) timer_item->strLabel),
            timer_item->strVariable,
            strExtraOutput
            );
    m_iCurrentActionSource = eUnknownActionSource;
    timer_item->bExecutingScript = false;     // can be deleted now

    // display any stuff sent to output window

    if (!strExtraOutput.IsEmpty ())
       DisplayMsg (strExtraOutput, strExtraOutput.GetLength (), COMMENT);

// invoke script subroutine, if any

    if (!timer_item->strProcedure.IsEmpty ())
      if (CheckScriptingAvailable ("Timer", timer_item->dispid, timer_item->strProcedure))
         continue;

    if (timer_item->dispid != DISPID_UNKNOWN)        // if we have a dispatch id
      {
      
      CString strType = "timer";
      CString strReason =  TFormat ("processing timer \"%s\"", 
                                    (LPCTSTR) timer_item->strLabel);

      // get unlabelled timer's internal name
      const char * pLabel = timer_item->strLabel;
      if (pLabel [0] == 0)
        pLabel = GetTimerRevMap () [timer_item].c_str ();

      if (GetScriptEngine () && GetScriptEngine ()->IsLua ())
        {
        list<double> nparams;
        list<string> sparams;
        sparams.push_back (pLabel);
        timer_item->bExecutingScript = true;     // cannot be deleted now
        GetScriptEngine ()->ExecuteLua (timer_item->dispid, 
                                       timer_item->strProcedure, 
                                       eTimerFired,
                                       strType, 
                                       strReason,
                                       nparams,
                                       sparams, 
                                       timer_item->nInvocationCount);
        timer_item->bExecutingScript = false;     // can be deleted now
        }   // end of Lua
      else
        {
        // prepare for the arguments (so far, 1 which is the timer name)
  
        // WARNING - arguments should appear in REVERSE order to what the sub expects them!

        enum
          {
          eTimerName,
          eArgCount,     // this MUST be last
          };    

        COleVariant args [eArgCount];
        DISPPARAMS params = { args, NULL, eArgCount, 0 };

  //      args [eTimerName] = strTimerName;
        args [eTimerName] = pLabel;
        timer_item->bExecutingScript = true;     // cannot be deleted now
        ExecuteScript (timer_item->dispid,  
                       timer_item->strProcedure,
                       eTimerFired,
                       strType, 
                       strReason,
                       params, 
                       timer_item->nInvocationCount);
        timer_item->bExecutingScript = false;     // can be deleted now

        } // not Lua
      }     // end of having a dispatch ID


    // If they passed the wrong arguments to the timer routine, the dialog box
    // might appear, and the timer be deleted, before we get a chance to
    // do this code, in which case the timer has gone.
    // Just get it again to be sure ...  [#430]

    if (!TimerMap.Lookup (strTimerName, timer_item))
      return;

// if one-shot timer, delete from list

    if (timer_item->bOneShot)
      {
      TimerMap.RemoveKey (strTimerName);
      delete timer_item;
      SortTimers ();
      }
    }   // end of processing each timer

  } // end of CMUSHclientDoc::CheckTimerMap
Example #3
0
void CTimerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);

  if(!pDX->m_bSaveAndValidate)
    {
    if (m_current_timer && m_current_timer->bIncluded)
      m_strIncluded = "(included)";
    else 
      m_strIncluded.Empty ();
    }

	//{{AFX_DATA_MAP(CTimerDlg)
	DDX_Control(pDX, IDC_SEND_TO, m_ctlSendTo);
	DDX_Control(pDX, IDC_SCRIPT_NAME, m_ctlProcedure);
	DDX_Control(pDX, IDC_TIMER_CONTENTS, m_ctlContents);
	DDX_Control(pDX, IDC_BUTTON_AT, m_ctlButtonAt);
	DDX_Check(pDX, IDC_ENABLED, m_bEnabled);
	DDX_Text(pDX, IDC_TIMER_LABEL, m_strLabel);
	DDX_Text(pDX, IDC_AT_HOUR, m_iAtHour);
	DDV_MinMaxInt(pDX, m_iAtHour, 0, 23);
	DDX_Text(pDX, IDC_AT_MINUTE, m_iAtMinute);
	DDV_MinMaxInt(pDX, m_iAtMinute, 0, 59);
	DDX_Text(pDX, IDC_INTERVAL_HOUR, m_iEveryHour);
	DDV_MinMaxInt(pDX, m_iEveryHour, 0, 23);
	DDX_Text(pDX, IDC_INTERVAL_MINUTE, m_iEveryMinute);
	DDV_MinMaxInt(pDX, m_iEveryMinute, 0, 59);
	DDX_Text(pDX, IDC_OFFSET_HOUR, m_iOffsetHour);
	DDV_MinMaxInt(pDX, m_iOffsetHour, 0, 23);
	DDX_Text(pDX, IDC_OFFSET_MINUTE, m_iOffsetMinute);
	DDV_MinMaxInt(pDX, m_iOffsetMinute, 0, 59);
	DDX_MinMaxString(pDX, IDC_TIMER_CONTENTS, m_strContents);
	DDV_MinMaxString(pDX, m_strContents, 0, 32000);
	DDX_Radio(pDX, IDC_BUTTON_EVERY, m_iType);
	DDX_Text(pDX, IDC_SCRIPT_NAME, m_strProcedure);
	DDX_Check(pDX, IDC_ONE_SHOT_TIMER, m_bOneShot);
	DDX_Check(pDX, IDC_TEMPORARY, m_bTemporary);
	DDX_Check(pDX, IDC_ACTIVE_WHEN_CLOSED, m_bActiveWhenClosed);
	DDX_Text(pDX, IDC_GROUP, m_strGroup);
	DDX_CBIndex(pDX, IDC_SEND_TO, m_iSendTo);
	DDX_Text(pDX, IDC_VARIABLE, m_strVariable);
	DDX_Text(pDX, IDC_INCLUDED, m_strIncluded);
	DDX_Check(pDX, IDC_OMIT_FROM_OUTPUT, m_bOmitFromOutput);
	DDX_Check(pDX, IDC_OMIT_FROM_LOG, m_bOmitFromLog);
	DDX_Text(pDX, IDC_AT_SECOND, m_fAtSecond);
	DDV_MinMaxDouble(pDX, m_fAtSecond, 0., 59.99999);
	DDX_Text(pDX, IDC_INTERVAL_SECOND, m_fEverySecond);
	DDV_MinMaxDouble(pDX, m_fEverySecond, 0., 59.99999);
	DDX_Text(pDX, IDC_OFFSET_SECOND, m_fOffsetSecond);
	DDV_MinMaxDouble(pDX, m_fOffsetSecond, 0., 59.99999);
	//}}AFX_DATA_MAP

  if(pDX->m_bSaveAndValidate)
    {

    
    m_strLabel.TrimLeft ();
    m_strLabel.TrimRight ();

    m_strProcedure.TrimLeft ();
    m_strProcedure.TrimRight ();

    m_strGroup.TrimLeft ();
    m_strGroup.TrimRight ();

    if (m_iType == CTimer::eInterval)
      {
      CmcDateTimeSpan ts1 (0, m_iEveryHour, m_iEveryMinute, m_fEverySecond);
      CmcDateTimeSpan ts2 (0, m_iOffsetHour, m_iOffsetMinute, m_fOffsetSecond);

      if (ts1 <= CmcDateTimeSpan (0, 0, 0, 0))
          {
          ::TMessageBox("The timer interval must be greater than zero.");
          DDX_Text(pDX, IDC_INTERVAL_HOUR, m_iEveryHour);
          pDX->Fail();
          }     // end of interval <= 0

      if(ts2 >= ts1)
          {
          ::TMessageBox("The timer offset must be less than the timer period.");
          DDX_Text(pDX, IDC_OFFSET_HOUR, m_iOffsetHour);
          pDX->Fail();
          }     // end of offset >= period
        }   // end of doing a periodical timer


    CString strTimerName;
    CTimer * timer_item;
    POSITION pos;

    for (pos = m_pTimerMap->GetStartPosition (); pos; )
      {
      m_pTimerMap->GetNextAssoc (pos, strTimerName, timer_item);

// don't compare against itself

      if (timer_item == m_current_timer)
        continue;

// now check the label for duplicates

      if (!m_strLabel.IsEmpty ())    // we can have duplicate blank names
        if (m_strLabel.CompareNoCase (timer_item->strLabel) == 0)
          {
          CString strMsg;
          strMsg = TFormat ("The timer label \"%s\" is already in the list of timers.",
                          (LPCTSTR) m_strLabel);
          ::UMessageBox(strMsg);
          DDX_Text(pDX, IDC_TIMER_LABEL, m_strLabel);
          pDX->Fail();
          }

      }   // end of checking each Timer

    if (!m_strLabel.IsEmpty ())    // we can have blank labels
      {

// check label is valid

      if (CheckLabel (m_strLabel))
        {
        ::TMessageBox ("The label must start with a letter and consist of letters"
                        ", numbers or the underscore character.");
        DDX_Text(pDX, IDC_TIMER_LABEL, m_strLabel);
        pDX->Fail();
        }

      }   // end of having non-blank label


    if (m_strVariable.IsEmpty ())    // we can have blank variables
      {
      if (m_iSendTo == eSendToVariable)
        {
        ::TMessageBox("When sending to a variable you must specify a variable name. ",
                        MB_ICONSTOP);
        DDX_Text(pDX, IDC_VARIABLE, m_strVariable);
        pDX->Fail();
        }
      }
    else
      {

// check variable name is valid

      if (CheckLabel (m_strVariable))
        {
        ::TMessageBox("The variable name must start with a letter and consist of letters"
                        ", numbers or the underscore character.");
        DDX_Text(pDX, IDC_VARIABLE, m_strVariable);
        pDX->Fail();
        }

      }   // end of having non-blank variable


    // check for speed walking OK, unless they are substituting

    if (m_iSendTo == eSendToSpeedwalk)
      {

      CString strResult = m_pDoc->DoEvaluateSpeedwalk (m_strContents);

      if (!strResult.IsEmpty ())
        {
        if (strResult [0] == '*')    // error in speedwalk string?
          {
          ::UMessageBox (strResult.Mid (1));  // already translated, I think
          DDX_Text(pDX, IDC_TIMER_CONTENTS, m_strContents);
          pDX->Fail();
          }   // end of error message
        } // end of non-empty speedwalk          
      }   // end of speed walking wanted

    if(m_strContents.IsEmpty () && m_strProcedure.IsEmpty ())
        {
        ::TMessageBox("The timer contents cannot be blank unless you specify a script subroutine.");
        DDX_Text(pDX, IDC_TIMER_CONTENTS, m_strContents);
        pDX->Fail();
        }     // end of contents being blank


    if (!m_strProcedure.IsEmpty ())    // blank procedure is OK
      {

// check procedure is valid

      if (CheckLabel (m_strProcedure, true))
        {
        ::TMessageBox("The script subroutine name must start with a letter and consist of letters"
                        ", numbers or the underscore character.");
        DDX_Text(pDX, IDC_SCRIPT_NAME, m_strProcedure);
        pDX->Fail();
        }

      }   // end of having non-blank procedure

    }   // end of saving and validating

}