[dasher] Re-implement dynamic mode speed control:



commit 825887a0dcbdcc0c08a354c9c7b7ed82292749a4
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Wed Jun 17 19:09:36 2009 +0100

    Re-implement dynamic mode speed control:
    
    Periodically increase speed as long as in a 'running' state; decrease
    every time we start to reverse.
    
    (Controlled by new settings for time period, increase and decrease,
    added to both existing dynamic modes: LP_DYNAMIC_SPEED_{FREQ, INC, DEC}
    respectively).

 ChangeLog                                 |   10 ++
 Src/DasherCore/DynamicFilter.cpp          |   27 +++++
 Src/DasherCore/DynamicFilter.h            |   11 +--
 Src/DasherCore/OneButtonDynamicFilter.cpp |    7 +-
 Src/DasherCore/Parameters.h               |   14 ++-
 Src/DasherCore/TwoButtonDynamicFilter.cpp |  152 +----------------------------
 Src/DasherCore/TwoButtonDynamicFilter.h   |   33 ------
 7 files changed, 59 insertions(+), 195 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a9990af..92f45d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2009-06-17  Alan Lawrence <acl33 inf phy cam ac uk>
 
+	* Re-implement dynamic mode speed control:
+	Periodically increase speed as long as in a 'running' state;
+	decrease every time we start to reverse.
+	(Controlled by new settings for time period, increase
+	and decrease, added to both existing dynamic modes:
+	LP_DYNAMIC_SPEED_{FREQ, INC, DEC} respectively).
+
+
+2009-06-17  Alan Lawrence <acl33 inf phy cam ac uk>
+
 	* Remove CDasherModel parameter to inputfilter constructor.
 	* Make DynamicFilter's states observable and changeable by
 	subclasses, and create a CButtonMultiPress subclass for
diff --git a/Src/DasherCore/DynamicFilter.cpp b/Src/DasherCore/DynamicFilter.cpp
index 8a7563c..6b05d90 100644
--- a/Src/DasherCore/DynamicFilter.cpp
+++ b/Src/DasherCore/DynamicFilter.cpp
@@ -37,6 +37,13 @@ bool CDynamicFilter::Timer(int iTime, CDasherView *m_pDasherView, CDasherModel *
   }
   if (isPaused()) return false;
   if (isReversing()) return m_pDasherModel->OneStepTowards(41943,2048, iTime, pAdded, pNumDeleted);
+  //moving forwards. Check auto speed control...
+  if (GetLongParameter(BP_AUTO_SPEEDCONTROL) && m_iSpeedControlTime < iTime)
+  {
+	  if (m_iSpeedControlTime > 0) //has actually been set?
+        SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) * (1.0 + GetLongParameter(LP_DYNAMIC_SPEED_INC)/100.0));
+	  m_iSpeedControlTime = iTime + 1000*GetLongParameter(LP_DYNAMIC_SPEED_FREQ);
+  }
   return TimerImpl(iTime, m_pDasherView, m_pDasherModel, pAdded, pNumDeleted);
 }
 
@@ -131,3 +138,23 @@ void CDynamicFilter::Event(int iTime, int iButton, int iType, CDasherModel *pMod
     }
   }
 }
+
+void CDynamicFilter::reverse()
+{
+  m_iState = 1;
+  if (GetBoolParameter(BP_AUTO_SPEEDCONTROL))
+  {
+	//treat reversing as a sign of distress --> slow down!
+	SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) *
+					 (1.0 - GetLongParameter(LP_DYNAMIC_SPEED_DEC)/100.0));
+  }
+}
+
+void CDynamicFilter::run(int iSubclassState)
+{
+  DASHER_ASSERT(iSubclassState>=0);
+  if (m_iState<2) //wasn't running previously
+    m_iSpeedControlTime = 0; //will be set in Timer()
+  m_iState = iSubclassState+2;
+}
+
diff --git a/Src/DasherCore/DynamicFilter.h b/Src/DasherCore/DynamicFilter.h
index 86dd06e..b960e13 100644
--- a/Src/DasherCore/DynamicFilter.h
+++ b/Src/DasherCore/DynamicFilter.h
@@ -50,11 +50,8 @@ class CDynamicFilter : public CInputFilter {
   bool isRunning(int &iSubclassState)
     {if (m_iState < 2) return false; iSubclassState = m_iState-2; return true;}
   virtual void pause() {m_iState = 0;}
-  virtual void reverse() {m_iState = 1;}
-  virtual void run(int iSubclassState) {
-    DASHER_ASSERT(iSubclassState>=0);
-    m_iState = iSubclassState+2;
-  }
+  virtual void reverse();
+  virtual void run(int iSubclassState);
 
   virtual bool TimerImpl(int Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, Dasher::VECTOR_SYMBOL_PROB *pAdded, int *pNumDeleted) = 0;
 
@@ -62,9 +59,9 @@ class CDynamicFilter : public CInputFilter {
     int m_iState; // 0 = paused, 1 = reversing, >=2 = running (extensible by subclasses)
     int m_iHeldId;
     int m_iKeyDownTime;
-  
+    int m_iSpeedControlTime;
+	
     CUserLogBase *m_pUserLog;
-
 };
 
 #endif
diff --git a/Src/DasherCore/OneButtonDynamicFilter.cpp b/Src/DasherCore/OneButtonDynamicFilter.cpp
index ab5fccc..727232b 100644
--- a/Src/DasherCore/OneButtonDynamicFilter.cpp
+++ b/Src/DasherCore/OneButtonDynamicFilter.cpp
@@ -32,7 +32,12 @@ static SModuleSettings sSettings[] = {
   /* TRANSLATORS: Multiple button presses are special (like a generalisation on double clicks) in some situations. This is the number of times a button must be pressed to count as a multiple press.*/
   {LP_MULTIPRESS_COUNT,T_LONG, 2, 10, 1, 1, _("Multiple press count")},
   /* TRANSLATORS: Backoff = reversing in Dasher to correct mistakes. This allows a single button to be dedicated to activating backoff, rather than using multiple presses of other buttons.*/
-  {BP_BACKOFF_BUTTON,T_BOOL, -1, -1, -1, -1, _("Enable backoff button")}
+  {BP_BACKOFF_BUTTON,T_BOOL, -1, -1, -1, -1, _("Enable backoff button")},
+  {BP_SLOW_START,T_BOOL, -1, -1, -1, -1, _("Slow startup")},
+  {LP_SLOW_START_TIME, T_LONG, 0, 10000, 1000, 100, _("Startup time")},
+  {LP_DYNAMIC_SPEED_INC, T_LONG, 1, 100, 1, 1, _("%age by which to automatically increase speed")},
+  {LP_DYNAMIC_SPEED_FREQ, T_LONG, 1, 1000, 1, 1, _("Time after which to automatically increase speed (secs)")},
+  {LP_DYNAMIC_SPEED_DEC, T_LONG, 1, 99, 1, 1, _("%age by which to decrease speed upon reverse")}
 };
 
 COneButtonDynamicFilter::COneButtonDynamicFilter(Dasher::CEventHandler * pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface)
diff --git a/Src/DasherCore/Parameters.h b/Src/DasherCore/Parameters.h
index ab20a9a..9bc5a34 100644
--- a/Src/DasherCore/Parameters.h
+++ b/Src/DasherCore/Parameters.h
@@ -44,7 +44,7 @@ enum {
   BP_COMPASSMODE, BP_SOCKET_INPUT_ENABLE, BP_SOCKET_DEBUG, 
   BP_OLD_STYLE_PUSH, BP_CIRCLE_START, BP_GLOBAL_KEYBOARD, 
   BP_DELAY_VIEW, BP_CONVERSION_MODE, BP_PAUSE_OUTSIDE, BP_BACKOFF_BUTTON, 
-  BP_TWOBUTTON_REVERSE, BP_SLOW_START, BP_TWOBUTTON_SPEED, END_OF_BPS
+  BP_TWOBUTTON_REVERSE, BP_SLOW_START, END_OF_BPS
 };
 
 enum { 
@@ -59,8 +59,9 @@ enum {
   LP_BOOSTFACTOR, LP_AUTOSPEED_SENSITIVITY, LP_SOCKET_PORT, LP_SOCKET_INPUT_X_MIN, LP_SOCKET_INPUT_X_MAX,
   LP_SOCKET_INPUT_Y_MIN, LP_SOCKET_INPUT_Y_MAX, LP_OX, LP_OY, LP_MAX_Y, LP_INPUT_FILTER, 
   LP_CIRCLE_PERCENT, LP_TWO_BUTTON_OFFSET, LP_HOLD_TIME, LP_MULTIPRESS_TIME, LP_MULTIPRESS_COUNT, 
-  LP_SLOW_START_TIME, LP_DYNAMIC_MEDIAN_FACTOR, LP_CONVERSION_ORDER, LP_CONVERSION_TYPE,
-  LP_DEMO_SPRING, LP_DEMO_NOISE_MEM, LP_DEMO_NOISE_MAG, LP_MAXZOOM, END_OF_LPS
+  LP_SLOW_START_TIME, LP_CONVERSION_ORDER, LP_CONVERSION_TYPE,
+  LP_DEMO_SPRING, LP_DEMO_NOISE_MEM, LP_DEMO_NOISE_MAG, LP_MAXZOOM, 
+  LP_DYNAMIC_SPEED_INC, LP_DYNAMIC_SPEED_FREQ, LP_DYNAMIC_SPEED_DEC, END_OF_LPS
 };
 
 enum {
@@ -160,7 +161,6 @@ static bp_table boolparamtable[] = {
   {BP_BACKOFF_BUTTON, "BackoffButton", PERS, true, "Whether to enable the extra backoff button in dynamic mode"},
   {BP_TWOBUTTON_REVERSE, "TwoButtonReverse", PERS, false, "Reverse the up/down buttons in two button mode"},
   {BP_SLOW_START, "SlowStart", PERS, false, "Start at low speed and insrease"},
-  {BP_TWOBUTTON_SPEED, "TwoButtonSpeed", PERS, true, "Two button mode auto speed control"}
 };
 
 static lp_table longparamtable[] = {
@@ -211,13 +211,15 @@ static lp_table longparamtable[] = {
   {LP_MULTIPRESS_TIME, "MultipressTime", PERS, 1000, "Time in which multiple presses must occur, in ms"},
   {LP_MULTIPRESS_COUNT, "MultipressCount", PERS, 2, "Time in which multiple presses must occur to count"},
   {LP_SLOW_START_TIME, "SlowStartTime", PERS, 1000, "Time over which slow start occurs"},
-  {LP_DYNAMIC_MEDIAN_FACTOR, "DynamicMedianFactor", PERS, 30, "Percentage of the median at which dynamic mode auto speed control kicks in"},
   {LP_CONVERSION_ORDER, "ConversionOrder", PERS, 0, "Conversion ordering"},
   {LP_CONVERSION_TYPE, "ConversionType", PERS, 0, "Conversion type"},
   {LP_DEMO_SPRING, "DemoSpring", PERS, 100, "Springyness in Demo-mode"},
   {LP_DEMO_NOISE_MEM, "DemoNoiseMem", PERS, 100, "Memory parameter for noise in Demo-mode"},
   {LP_DEMO_NOISE_MAG, "DemoNoiseMag", PERS, 325, "Magnitude of noise in Demo-mode"},
-  {LP_MAXZOOM, "ClickMaxZoom", PERS, 200, "Maximum zoom possible in click mode (times 10)"}
+  {LP_MAXZOOM, "ClickMaxZoom", PERS, 200, "Maximum zoom possible in click mode (times 10)"},
+  {LP_DYNAMIC_SPEED_INC, "DynamicSpeedInc", PERS, 1, "%age by which dynamic mode auto speed control increases speed"},
+  {LP_DYNAMIC_SPEED_FREQ, "DynamicSpeedFreq", PERS, 10, "Seconds after which dynamic mode auto speed control increases speed"},
+  {LP_DYNAMIC_SPEED_DEC, "DynamicSpeedDec", PERS, 10, "%age by which dynamic mode auto speed control decreases speed on reverse"},
 };
 
 static sp_table stringparamtable[] = {
diff --git a/Src/DasherCore/TwoButtonDynamicFilter.cpp b/Src/DasherCore/TwoButtonDynamicFilter.cpp
index 057f9b0..a7d490f 100644
--- a/Src/DasherCore/TwoButtonDynamicFilter.cpp
+++ b/Src/DasherCore/TwoButtonDynamicFilter.cpp
@@ -38,25 +38,13 @@ static SModuleSettings sSettings[] = {
   {BP_TWOBUTTON_REVERSE,T_BOOL, -1, -1, -1, -1, _("Reverse up and down buttons")},
   {BP_SLOW_START,T_BOOL, -1, -1, -1, -1, _("Slow startup")},
   {LP_SLOW_START_TIME, T_LONG, 0, 10000, 1000, 100, _("Startup time")},
-  {BP_TWOBUTTON_SPEED,T_BOOL, -1, -1, -1, -1, _("Auto speed control")},
-  /* TRANSLATORS: The threshold time above which auto speed control is used. */
-  {LP_DYNAMIC_MEDIAN_FACTOR, T_LONG, 10, 200, 100, 10, _("Auto speed threshold")}
+  {LP_DYNAMIC_SPEED_INC, T_LONG, 1, 100, 1, 1, _("%age by which to automatically increase speed")},
+  {LP_DYNAMIC_SPEED_FREQ, T_LONG, 1, 1000, 1, 1, _("Time after which to automatically increase speed (secs)")},
+  {LP_DYNAMIC_SPEED_DEC, T_LONG, 1, 99, 1, 1, _("%age by which to decrease speed upon reverse")}
 };
 
 CTwoButtonDynamicFilter::CTwoButtonDynamicFilter(Dasher::CEventHandler * pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface)
-  : CButtonMultiPress(pEventHandler, pSettingsStore, pInterface, 14, 1, _("Two Button Dynamic Mode")) { 
-
-  m_iLastTime = -1;
-
-  m_pTree = new SBTree(2000);
-  m_pTree->Add(2000);
-  m_pTree->Add(2000);
-}
-
-CTwoButtonDynamicFilter::~CTwoButtonDynamicFilter() {
-  if(m_pTree)
-    delete m_pTree;
-}
+  : CButtonMultiPress(pEventHandler, pSettingsStore, pInterface, 14, 1, _("Two Button Dynamic Mode")) { }
 
 bool CTwoButtonDynamicFilter::DecorateView(CDasherView *pView) {
   CDasherScreen *pScreen(pView->Screen());
@@ -117,15 +105,11 @@ void CTwoButtonDynamicFilter::ActionButton(int iTime, int iButton, int iType, CD
     pModel->Offset(iFactor * GetLongParameter(LP_TWO_BUTTON_OFFSET));
     if(pUserLog)
       pUserLog->KeyDown(iButton, iType, 3);
-    if(GetBoolParameter(BP_TWOBUTTON_SPEED))
-      AutoSpeedSample(iTime, pModel);
   }
   else if((iButton == 3) || (iButton == 4)) {
     pModel->Offset(iFactor * -GetLongParameter(LP_TWO_BUTTON_OFFSET));
     if(pUserLog)
       pUserLog->KeyDown(iButton, iType, 4);
-    if(GetBoolParameter(BP_TWOBUTTON_SPEED))
-      AutoSpeedSample(iTime, pModel);
   }
   else {
     if(pUserLog)
@@ -140,134 +124,6 @@ bool CTwoButtonDynamicFilter::GetSettings(SModuleSettings **pSettings, int *iCou
   return true;
 };
 
-void CTwoButtonDynamicFilter::AutoSpeedSample(int iTime, CDasherModel *pModel) {
-  if(m_iLastTime == -1) {
-    m_iLastTime = iTime;
-    return;
-  }
-
-  if(pModel->IsSlowdown(iTime))
-    return;
-
-  int iDiff(iTime - m_iLastTime);
-  m_iLastTime = iTime;
-  if(m_pTree) {
-    int iMedian(m_pTree->GetOffset(m_pTree->GetCount() / 2));
-    if((iDiff <= 300) || (iDiff < (iMedian * GetLongParameter(LP_DYNAMIC_MEDIAN_FACTOR)) / 100)) {
-      pModel->TriggerSlowdown();
-    }
-    m_pTree->Add(iDiff);
-  }
-  else m_pTree = new SBTree(iDiff);  
-
-  m_deOffsetQueue.push_back(iDiff);
-
-  while(m_deOffsetQueue.size() > 10) {
-    m_pTree = m_pTree->Delete(m_deOffsetQueue.front());
-    m_deOffsetQueue.pop_front();
-  }
-}
-
-void CTwoButtonDynamicFilter::AutoSpeedUndo(int iCount) {
-  for(int i(0); i < iCount; ++i) {
-    if(m_deOffsetQueue.size() == 0)
-      return;
-
-    if(m_pTree)
-      m_pTree = m_pTree->Delete(m_deOffsetQueue.back());
-    m_deOffsetQueue.pop_back();
-  }
-}
-
-CTwoButtonDynamicFilter::SBTree::SBTree(int iValue) {
-  m_iValue = iValue;
-  m_pLeft = NULL;
-  m_pRight = NULL;
-  m_iCount = 1;
-}
-
-CTwoButtonDynamicFilter::SBTree::~SBTree() {
-  if(m_pLeft)
-    delete m_pLeft;
-
-  if(m_pRight)
-    delete m_pRight;
-}
-
-void CTwoButtonDynamicFilter::SBTree::Add(int iValue) {
-  ++m_iCount;
-
-  if(iValue > m_iValue) {
-    if(m_pRight)
-      m_pRight->Add(iValue);
-    else
-      m_pRight = new SBTree(iValue);
-  }
-  else {
-    if(m_pLeft)
-      m_pLeft->Add(iValue);
-    else
-      m_pLeft = new SBTree(iValue);
-  }
-}
-
-CTwoButtonDynamicFilter::SBTree* CTwoButtonDynamicFilter::SBTree::Delete(int iValue) {
-  // Hmm... deleting is awkward in binary trees
-
-  if(iValue == m_iValue) {
-    if(!m_pLeft) {
-      SBTree *pOldRight = m_pRight;
-      m_pRight = NULL;
-      delete this;
-      return pOldRight;
-    }
-    else {
-      SBTree *pOldLeft = m_pLeft;
-      pOldLeft->SetRightMost(m_pRight);
-      m_pLeft = NULL;
-      m_pRight = NULL;
-      delete this;
-      return pOldLeft;
-    }
-  }
-  else if(iValue > m_iValue) {
-    --m_iCount;
-    m_pRight = m_pRight->Delete(iValue);
-  }
-  else {
-    --m_iCount;
-    m_pLeft = m_pLeft->Delete(iValue);
-  }
-
-  return this;
-}
-
-void CTwoButtonDynamicFilter::SBTree::SetRightMost(CTwoButtonDynamicFilter::SBTree* pNewTree) {
-  if(pNewTree)
-    m_iCount += pNewTree->GetCount();
-
-  if(m_pRight)
-    m_pRight->SetRightMost(pNewTree);
-  else
-    m_pRight = pNewTree;
-}
-
-int CTwoButtonDynamicFilter::SBTree::GetOffset(int iOffset) {
-  if(m_pLeft && (m_pLeft->GetCount() > iOffset))
-    return m_pLeft->GetOffset(iOffset);
-  else if((m_pLeft && (m_pLeft->GetCount() == iOffset)) || (!m_pLeft && (iOffset == 0)))
-    return m_iValue;
-  else if(m_pLeft)
-    return m_pRight->GetOffset(iOffset - m_pLeft->GetCount() - 1);
-  else
-    return m_pRight->GetOffset(iOffset - 1);
-}
-
-void CTwoButtonDynamicFilter::RevertPresses(int iCount) {
-  if(GetBoolParameter(BP_TWOBUTTON_SPEED))
-    AutoSpeedUndo(iCount);
-}
-
 bool CTwoButtonDynamicFilter::GetMinWidth(int &iMinWidth) {
   iMinWidth = 1024;
   return true;
diff --git a/Src/DasherCore/TwoButtonDynamicFilter.h b/Src/DasherCore/TwoButtonDynamicFilter.h
index 0a227a7..5219657 100644
--- a/Src/DasherCore/TwoButtonDynamicFilter.h
+++ b/Src/DasherCore/TwoButtonDynamicFilter.h
@@ -30,7 +30,6 @@
 class CTwoButtonDynamicFilter : public CButtonMultiPress {
  public:
   CTwoButtonDynamicFilter(Dasher::CEventHandler * pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface);
-  ~CTwoButtonDynamicFilter();
 
   // Inherited methods
   virtual bool DecorateView(CDasherView *pView);
@@ -45,38 +44,6 @@ class CTwoButtonDynamicFilter : public CButtonMultiPress {
  private:
   virtual bool TimerImpl(int Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, Dasher::VECTOR_SYMBOL_PROB *pAdded, int *pNumDeleted);
   virtual void ActionButton(int iTime, int iButton, int iType, CDasherModel *pModel, CUserLogBase *pUserLog);
-
-  virtual void RevertPresses(int iCount);
-
-  void AutoSpeedSample(int iTime, CDasherModel *pModel);
-  void AutoSpeedUndo(int iCount);
-
-  class SBTree {
-  public:
-    SBTree(int iValue);
-    ~SBTree();
-
-    void Add(int iValue);
-    SBTree* Delete(int iValue);
-
-    int GetCount() {
-      return m_iCount;
-    };
-
-    int GetOffset(int iOffset);
-
-    void SetRightMost(SBTree* pNewTree);
-
-  private:
-    int m_iValue;
-    SBTree *m_pLeft;
-    SBTree *m_pRight;
-    int m_iCount;
-  };
-
-  int m_iLastTime;
-  SBTree *m_pTree;
-  std::deque<int> m_deOffsetQueue;
 };
 /// @}
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]