[chronojump] Encoder rhythm no-adaptative done!



commit b73e65c368654a5c08d229ddb1b7995f0c6f5d1d
Author: Xavier de Blas <xaviblas gmail com>
Date:   Thu Feb 15 13:50:46 2018 +0100

    Encoder rhythm no-adaptative done!

 glade/repetitive_conditions.glade |  269 ++++++++++++++++---------------
 src/encoderCapture.cs             |   44 +-----
 src/encoderRhythm.cs              |  321 ++++++++++++++++++++++++++++++++++---
 src/gui/encoder.cs                |   40 +++---
 src/gui/repetitiveConditions.cs   |   56 +++++--
 src/util.cs                       |    7 +-
 6 files changed, 507 insertions(+), 230 deletions(-)
---
diff --git a/glade/repetitive_conditions.glade b/glade/repetitive_conditions.glade
index 526ac37..ccc9a5b 100644
--- a/glade/repetitive_conditions.glade
+++ b/glade/repetitive_conditions.glade
@@ -3710,6 +3710,7 @@
                                                 <property name="secondary_icon_sensitive">True</property>
                                                 <property name="adjustment">2 0.10000000000000001 10 
0.10000000000000001 1 0</property>
                                                 <property name="digits">2</property>
+                                                <property name="snap_to_ticks">True</property>
                                                 <property name="numeric">True</property>
                                               </widget>
                                               <packing>
@@ -3897,71 +3898,37 @@
                                 <property name="can_focus">False</property>
                                 <property name="spacing">6</property>
                                 <child>
-                                  <widget class="GtkLabel" id="label48">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
+                                  <widget class="GtkCheckButton" id="check_rhythm_rest_reps">
                                     <property name="label" translatable="yes">Rest between 
repetitions</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <widget class="GtkSpinButton" id="spin_rhythm_rest_reps">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
-                                    <property name="invisible_char">●</property>
-                                    <property name="primary_icon_activatable">False</property>
-                                    <property name="secondary_icon_activatable">False</property>
-                                    <property name="primary_icon_sensitive">True</property>
-                                    <property name="secondary_icon_sensitive">True</property>
-                                    <property name="adjustment">1 0 99 0.10000000000000001 1 0</property>
-                                    <property name="digits">2</property>
-                                    <property name="numeric">True</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <widget class="GtkLabel" id="label49">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="label" translatable="yes">seconds</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="draw_indicator">True</property>
+                                    <signal name="toggled" handler="on_check_rhythm_rest_reps_toggled" 
swapped="no"/>
                                   </widget>
                                   <packing>
                                     <property name="expand">False</property>
                                     <property name="fill">False</property>
-                                    <property name="position">2</property>
+                                    <property name="position">0</property>
                                   </packing>
                                 </child>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkAlignment" id="alignment26">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="left_padding">30</property>
                                 <child>
-                                  <widget class="GtkVBox" id="vbox_rhythm_rest_after">
-                                    <property name="visible">True</property>
+                                  <widget class="GtkHBox" id="hbox_rhythm_rest_reps_value">
                                     <property name="can_focus">False</property>
-                                    <property name="spacing">10</property>
+                                    <property name="spacing">6</property>
                                     <child>
-                                      <widget class="GtkLabel" id="label54">
+                                      <widget class="GtkSpinButton" id="spin_rhythm_rest_reps">
                                         <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="xalign">0</property>
-                                        <property name="label" translatable="yes">On encoder gravitatory 
rest is done ...</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="invisible_char">●</property>
+                                        <property name="primary_icon_activatable">False</property>
+                                        <property name="secondary_icon_activatable">False</property>
+                                        <property name="primary_icon_sensitive">True</property>
+                                        <property name="secondary_icon_sensitive">True</property>
+                                        <property name="adjustment">1 0 99 0.10000000000000001 1 0</property>
+                                        <property name="digits">1</property>
+                                        <property name="snap_to_ticks">True</property>
+                                        <property name="numeric">True</property>
                                       </widget>
                                       <packing>
                                         <property name="expand">False</property>
@@ -3970,109 +3937,76 @@
                                       </packing>
                                     </child>
                                     <child>
-                                      <widget class="GtkHBox" id="hbox_rhythm_rest_after">
+                                      <widget class="GtkLabel" id="label49">
                                         <property name="visible">True</property>
                                         <property name="can_focus">False</property>
-                                        <property name="spacing">12</property>
-                                        <child>
-                                          <widget class="GtkRadioButton" id="radio_rest_after_ecc">
-                                            <property name="label" translatable="yes">after 
eccentric</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="active">True</property>
-                                            <property name="draw_indicator">True</property>
-                                          </widget>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">False</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <widget class="GtkRadioButton" id="radio_rest_after_con">
-                                            <property name="label" translatable="yes">after 
concentric</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">False</property>
-                                            <property name="active">True</property>
-                                            <property name="draw_indicator">True</property>
-                                            <property name="group">radio_rest_after_ecc</property>
-                                          </widget>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">False</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
+                                        <property name="label" translatable="yes">seconds</property>
                                       </widget>
                                       <packing>
-                                        <property name="expand">True</property>
-                                        <property name="fill">True</property>
+                                        <property name="expand">False</property>
+                                        <property name="fill">False</property>
                                         <property name="position">1</property>
                                       </packing>
                                     </child>
                                   </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
                                 </child>
                               </widget>
                               <packing>
                                 <property name="expand">False</property>
                                 <property name="fill">False</property>
-                                <property name="position">3</property>
+                                <property name="position">2</property>
                               </packing>
                             </child>
                             <child>
-                              <widget class="GtkAlignment" id="alignment23">
+                              <widget class="GtkHBox" id="hbox38">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="top_padding">10</property>
+                                <property name="spacing">8</property>
                                 <child>
-                                  <widget class="GtkHBox" id="hbox38">
+                                  <widget class="GtkCheckButton" id="check_rhythm_use_clusters">
+                                    <property name="label" translatable="yes">Use clusters</property>
                                     <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="spacing">8</property>
-                                    <child>
-                                      <widget class="GtkCheckButton" id="check_rhythm_use_clusters">
-                                        <property name="label" translatable="yes">Use clusters</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">False</property>
-                                        <property name="draw_indicator">True</property>
-                                        <signal name="toggled" 
handler="on_check_rhythm_use_clusters_toggled" swapped="no"/>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="draw_indicator">True</property>
+                                    <signal name="toggled" handler="on_check_rhythm_use_clusters_toggled" 
swapped="no"/>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkButton" id="button_use_clusters_help">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <signal name="clicked" handler="on_button_use_clusters_help_clicked" 
swapped="no"/>
                                     <child>
-                                      <widget class="GtkButton" id="button_use_clusters_help">
+                                      <widget class="GtkImage" id="image_clusters_info">
                                         <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">True</property>
-                                        <signal name="clicked" handler="on_button_use_clusters_help_clicked" 
swapped="no"/>
-                                        <child>
-                                          <widget class="GtkImage" id="image_clusters_info">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="stock">gtk-missing-image</property>
-                                          </widget>
-                                        </child>
+                                        <property name="can_focus">False</property>
+                                        <property name="stock">gtk-missing-image</property>
                                       </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">1</property>
-                                      </packing>
                                     </child>
                                   </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
                                 </child>
                               </widget>
                               <packing>
                                 <property name="expand">False</property>
                                 <property name="fill">False</property>
-                                <property name="position">4</property>
+                                <property name="position">3</property>
                               </packing>
                             </child>
                             <child>
@@ -4193,6 +4127,86 @@
                               <packing>
                                 <property name="expand">False</property>
                                 <property name="fill">False</property>
+                                <property name="position">4</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkVBox" id="vbox_rhythm_rest_after">
+                                <property name="can_focus">False</property>
+                                <property name="spacing">10</property>
+                                <child>
+                                  <widget class="GtkAlignment" id="alignment26">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="top_padding">10</property>
+                                    <child>
+                                      <widget class="GtkLabel" id="label54">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">On encoder gravitatory 
rest is done ...</property>
+                                      </widget>
+                                    </child>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkAlignment" id="alignment27">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="left_padding">30</property>
+                                    <child>
+                                      <widget class="GtkHBox" id="hbox_rhythm_rest_after">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="spacing">12</property>
+                                        <child>
+                                          <widget class="GtkRadioButton" id="radio_rest_after_ecc">
+                                            <property name="label" translatable="yes">after 
eccentric</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="active">True</property>
+                                            <property name="draw_indicator">True</property>
+                                          </widget>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">False</property>
+                                            <property name="position">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <widget class="GtkRadioButton" id="radio_rest_after_con">
+                                            <property name="label" translatable="yes">after 
concentric</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">False</property>
+                                            <property name="draw_indicator">True</property>
+                                            <property name="group">radio_rest_after_ecc</property>
+                                          </widget>
+                                          <packing>
+                                            <property name="expand">False</property>
+                                            <property name="fill">False</property>
+                                            <property name="position">1</property>
+                                          </packing>
+                                        </child>
+                                      </widget>
+                                    </child>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
                                 <property name="position">5</property>
                               </packing>
                             </child>
@@ -4238,7 +4252,7 @@
                       <widget class="GtkLabel" id="label27">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="label">Configure adaptative rhythm</property>
+                        <property name="label">Configure rhythm</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -4258,10 +4272,9 @@
               </packing>
             </child>
             <child>
-              <widget class="GtkLabel" id="label47">
+              <widget class="GtkLabel" id="label_rhythm_tab">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="label" translatable="yes">Rhythm</property>
               </widget>
               <packing>
                 <property name="position">1</property>
diff --git a/src/encoderCapture.cs b/src/encoderCapture.cs
index 1d16a9c..5bf2f61 100644
--- a/src/encoderCapture.cs
+++ b/src/encoderCapture.cs
@@ -40,15 +40,6 @@ public abstract class EncoderCapture
        public int EncoderCapturePointsCaptured;
        public int EncoderCapturePointsPainted;
 
-       //encoderRhythm stuff
-       private bool useRhythm;
-       private bool rhythmRepsOrPhases;
-       public int RhythmNRep; //used to know rest between clusters
-       public bool RhythmEcconUp;
-       private Gtk.Button fakeButtonRhythm;
-
-       protected bool gravitatoryOrInertial; //currently only used for encoderRhythm
-
        // ---- protected stuff ----
        protected int widthG;
        protected int heightG;
@@ -123,7 +114,7 @@ public abstract class EncoderCapture
        //if cont (continuous mode), then will not end when too much time passed before start
        public void InitGlobal (int widthG, int heightG, int time, int timeEnd,
                        bool cont, string eccon, string port, bool capturingInertialBG, bool showOnlyBars,
-                       bool simulated, bool useRhythm, bool rhythmRepsOrPhases)
+                       bool simulated)
        {
                this.widthG = widthG;
                this.heightG = heightG;
@@ -132,11 +123,6 @@ public abstract class EncoderCapture
                this.capturingInertialBG = capturingInertialBG;
                this.showOnlyBars = showOnlyBars;
                this.simulated = simulated;
-               this.useRhythm = useRhythm;
-               this.rhythmRepsOrPhases = rhythmRepsOrPhases;
-
-               if(useRhythm)
-                       fakeButtonRhythm = new Gtk.Button();
 
                //---- a) open port -----
                if(simulated)
@@ -163,9 +149,6 @@ public abstract class EncoderCapture
                recordingTime = time * 1000;
                recordedTimeCont = 1; //not 0 to not have divide by zero problems
 
-               RhythmNRep = 0;
-               RhythmEcconUp = true;
-
                encoderReaded = new List<int>();
                encoderReadedInertialDisc = new List<int>();
 
@@ -582,22 +565,6 @@ public abstract class EncoderCapture
                                                        lastDirectionStoredIsUp = ecc.up;
                                                }
 
-                                               /*
-                                                * manage encoderRhythm stuff
-                                                * also on "c" send info if we ended ecc phase
-                                                */
-                                               if( useRhythm && (shouldSendCurveBool || (eccon == "c" && ! 
ecc.up)) )
-                                               {
-                                                       RhythmEcconUp = ecc.up;
-
-                                                       //on gravitatory phase ends at up, on inertial the 
opposite
-                                                       if(gravitatoryOrInertial == ecc.up)
-                                                               RhythmNRep ++;
-
-                                                       //if phases always send the phase. On reps only when 
change rep
-                                                       if(! rhythmRepsOrPhases || gravitatoryOrInertial == 
ecc.up)
-                                                               fakeButtonRhythm.Click();
-                                               }
                                        }
 
                                        //on inertial is different
@@ -887,11 +854,6 @@ public abstract class EncoderCapture
        public void Finish() {
                finish = true;
        }
-
-       public Button FakeButtonRhythm
-       {
-               get { return fakeButtonRhythm; }
-       }
 }
 
 
@@ -911,8 +873,6 @@ public class EncoderCaptureGravitatory : EncoderCapture
                
                //just a default value, unused until a curve has been accepted
                lastDirectionStoredIsUp = true;
-
-               gravitatoryOrInertial = true;
        }
 }
 
@@ -926,8 +886,6 @@ public class EncoderCaptureInertial : EncoderCapture
        protected override void initSpecific()
        {
                realHeightG = 2 * 5000 ; //5 meters up / 5 meters down
-
-               gravitatoryOrInertial = false;
        }
 
        public override void InitCalibrated(int angleNow)
diff --git a/src/encoderRhythm.cs b/src/encoderRhythm.cs
index 1f2c620..b67e3d7 100644
--- a/src/encoderRhythm.cs
+++ b/src/encoderRhythm.cs
@@ -35,6 +35,8 @@ public class EncoderRhythm
        public int RepsCluster;
        public double RestClustersSeconds; //rest between clusters
 
+       // Constructors ---------------------
+
        public EncoderRhythm()
        {
                Active = false;
@@ -70,6 +72,8 @@ public class EncoderRhythm
                RestClustersSeconds = restClustersSeconds;
        }
 
+       // Public methods ------------------
+
        //this also affects to encoder automatic end time. Is deactivated if UseClusters()
        public bool UseClusters()
        {
@@ -98,8 +102,284 @@ public class EncoderRhythm
 
                return 0;
        }
+
+       public override string ToString()
+       {
+               return
+                       "EncoderRhythm:" +
+                       "\nActive: " + Active.ToString() +
+                       "\nRepsOrPhases: " + RepsOrPhases.ToString() +
+                       "\nRepSeconds: " + RepSeconds.ToString() +
+                       "\nEccSeconds: " + EccSeconds.ToString() +
+                       "\nConSeconds: " + ConSeconds.ToString() +
+                       "\nRestRepsSeconds: " + RestRepsSeconds.ToString() +
+                       "\nRestAfterEcc: " + RestAfterEcc.ToString() +
+                       "\nRepsCluster: " + RepsCluster.ToString() +
+                       "\nRestClustersSeconds: " + RestClustersSeconds.ToString() +
+                       "\n";
+       }
 }
 
+/*
+ * this is fixed rhythm starting when first repetition ends
+ * easy to follow. not adaptative
+ */
+public class EncoderRhythmExecute
+{
+       public bool FirstPhaseDone;
+       private DateTime phaseStartDT;
+       private EncoderRhythm encoderRhythm;
+       private int nreps;
+
+       private double fraction;
+       private string textRepetition;
+       private string textRest;
+
+       //private double fractionRest;
+
+       //REPETITION is doing the repetition (no differentiate between ecc/con)
+       //ECC is ECC phase using phases
+       //CON is CON phase using phases
+       //RESTRESP is rest between repetitions
+       //RESTCLUSTER is rest between clusters
+       enum phases { REPETITION, ECC, CON, RESTREP, RESTCLUSTER }
+       phases currentPhase;
+
+       private bool gravitatory = true;
+       /*
+        * on inertial rest is after ecc.
+        * on gravitatory rest can be after ecc or con (see RestAfterEcc)
+        */
+
+
+       // Constructor ---------------------
+
+       public EncoderRhythmExecute(EncoderRhythm encoderRhythm, bool gravitatory)
+       {
+               this.encoderRhythm = encoderRhythm;
+               //this.eccon_ec = eccon_ec;
+               this.gravitatory = gravitatory;
+
+               FirstPhaseDone = false;
+               textRepetition = "";
+               textRest = "";
+
+               phaseStartDT = DateTime.MinValue;
+               nreps = 1; //start with 1 because it's the phase user will do before calling here
+       }
+
+       // Public methods ------------------
+
+       public void FirstPhaseDo(bool up)
+       {
+               if(FirstPhaseDone)
+                       return;
+
+               FirstPhaseDone = true;
+               phaseStartDT = DateTime.Now;
+
+               if(encoderRhythm.RepsOrPhases)
+                       currentPhase = getNextPhase(phases.REPETITION);
+               else if(up)
+                       currentPhase = getNextPhase(phases.CON);
+               else
+                       currentPhase = getNextPhase(phases.ECC);
+       }
+
+       //useful for fraction of the repetition and the rest time
+       public void CalculateFractionsAndText()
+       {
+               //double fraction = 0;
+               TimeSpan span = DateTime.Now - phaseStartDT;
+               double phaseSeconds = span.TotalSeconds;
+
+               //check if should end phase
+               if(shouldEndPhase(phaseSeconds))
+               {
+                       phaseStartDT = DateTime.Now;
+                       phaseSeconds = 0;
+
+                       //check if should end rep
+                       if(endPhaseShouldEndRep())
+                               nreps ++;
+
+                       //change to next phase
+                       currentPhase = getNextPhase(currentPhase);
+               }
+
+               setFractionAndText(phaseSeconds);
+       }
+
+       // Private methods ------------------
+
+       private bool shouldEndPhase(double phaseSeconds)
+       {
+               if(currentPhase == phases.REPETITION && phaseSeconds > encoderRhythm.RepSeconds)
+                       return true;
+               if(currentPhase == phases.ECC && phaseSeconds > encoderRhythm.EccSeconds)
+                      return true;
+               if(currentPhase == phases.CON && phaseSeconds > encoderRhythm.ConSeconds)
+                      return true;
+               if(currentPhase == phases.RESTREP && phaseSeconds > encoderRhythm.RestRepsSeconds)
+                      return true;
+               if(currentPhase == phases.RESTCLUSTER && phaseSeconds > encoderRhythm.RestClustersSeconds)
+                      return true;
+
+               return false;
+       }
+
+       private bool endPhaseShouldEndRep()
+       {
+               if(currentPhase == phases.REPETITION)
+                       return true;
+
+               if(gravitatory)
+               {
+                       if(currentPhase == phases.CON && ! encoderRhythm.RestAfterEcc) //ecc-con
+                               return true;
+
+                       if(currentPhase == phases.ECC && encoderRhythm.RestAfterEcc) //con-ecc
+                               return true;
+               } else {
+                       if(currentPhase == phases.ECC)
+                               return true;
+               }
+
+               return false;
+       }
+
+       private phases getNextPhase(phases previousPhase)
+       {
+               //manage what happens after cluster rest or if we should start a cluster rest
+               if(encoderRhythm.UseClusters())
+               {
+                       //check what happens after cluster rest
+                       if(previousPhase == phases.RESTCLUSTER)
+                       {
+                               if(encoderRhythm.RepsOrPhases)
+                                       return phases.REPETITION;
+                               else if(gravitatory && ! encoderRhythm.RestAfterEcc) //ecc-con
+                                       return phases.ECC;
+                               else // ! gravitatory or gravitatory resting after ecc
+                                       return phases.CON;
+                       }
+
+                       //check if we are on (REPETITION or ECC or CON) and we should start a cluster rest
+                       if
+                               ( nreps > 0 && nreps % encoderRhythm.RepsCluster == 0 &&
+                                 ( previousPhase == phases.REPETITION ||
+                                   ( previousPhase == phases.CON && gravitatory && ! 
encoderRhythm.RestAfterEcc ) ||
+                                   ( previousPhase == phases.ECC && ( ! gravitatory || 
encoderRhythm.RestAfterEcc ) )
+                                 )
+                               )
+                                       return phases.RESTCLUSTER;
+               }
+
+               if(encoderRhythm.RepsOrPhases)
+               {
+                       if(previousPhase == phases.REPETITION)
+                       {
+                               if(encoderRhythm.RestRepsSeconds == 0)
+                                       return phases.REPETITION;
+                               else
+                                       return phases.RESTREP;
+                       } else //RESTREP
+                                       return phases.REPETITION;
+               }
+
+               if(gravitatory && ! encoderRhythm.RestAfterEcc) //ecc-con
+               {
+                       if(previousPhase == phases.ECC)
+                               return phases.CON;
+                       else if(previousPhase == phases.CON)
+                       {
+                               if(encoderRhythm.RestRepsSeconds == 0)
+                                       return phases.ECC;
+                               else
+                                       return phases.RESTREP;
+                       }
+                       else //(previousPhase == phases.RESTREP)
+                               return phases.ECC;
+               }
+
+               else // ! gravitatory or gravitatory resting after ecc
+               {
+                       if(previousPhase == phases.CON)
+                               return phases.ECC;
+                       else if(previousPhase == phases.ECC)
+                       {
+                               if(encoderRhythm.RestRepsSeconds == 0)
+                                       return phases.CON;
+                               else
+                                       return phases.RESTREP;
+                       }
+                       else //(previousPhase == phases.RESTREP)
+                               return phases.CON;
+               }
+       }
+
+       private void setFractionAndText (double phaseSeconds)
+       {
+               textRepetition = "";
+
+               if(currentPhase == phases.REPETITION || currentPhase == phases.ECC || currentPhase == 
phases.CON)
+               {
+                       textRest = "";
+
+                       if(currentPhase == phases.REPETITION)
+                               fraction = Util.DivideSafeFraction(phaseSeconds, encoderRhythm.RepSeconds);
+                       if(currentPhase == phases.ECC)
+                       {
+                               fraction =  1 - Util.DivideSafeFraction(phaseSeconds, 
encoderRhythm.EccSeconds);
+                               textRepetition = "Excentric";
+                       }
+                       if(currentPhase == phases.CON)
+                       {
+                               fraction = Util.DivideSafeFraction(phaseSeconds, encoderRhythm.ConSeconds);
+                               textRepetition = "Concentric";
+                       }
+                       if(encoderRhythm.UseClusters())
+                               textRepetition += " (" +
+                                       ( (nreps % encoderRhythm.RepsCluster) +1 ).ToString() + "/" +
+                                       encoderRhythm.RepsCluster.ToString() + ")";
+               } else {
+                       //no change fraction
+                       double restTime = encoderRhythm.RestRepsSeconds - phaseSeconds;
+                       if(currentPhase == phases.RESTCLUSTER)
+                               restTime = encoderRhythm.RestClustersSeconds - phaseSeconds;
+
+                       textRest = "Resting " + Util.TrimDecimals(restTime, 1) + " s";
+               }
+               LogB.Information("currentPhase = " + currentPhase.ToString());
+       }
+
+       // Accessors ------------------
+
+       public double Fraction
+       {
+               get {
+                       if(fraction < 0)
+                               return 0;
+                       else if(fraction > 1)
+                               return 1;
+                       return fraction;
+               }
+       }
+
+       public string TextRepetition
+       {
+               get { return textRepetition; }
+       }
+
+       public string TextRest
+       {
+               get { return textRest; }
+       }
+}
+
+/*
+ * this code is adaptative and is quite difficult to follow, specially what's related to rest times between 
repetitions
+ *
 public class EncoderRhythmExecute
 {
        public string TextRepetition;
@@ -117,10 +397,9 @@ public class EncoderRhythmExecute
        //true is for con or ecc-con (gravitatory, always end on "con"), false is for con-ecc (inertial)
        //private       bool eccon_ec = true;
        private bool gravitatory = true;
-       /*
-        * on inertial rest is after ecc.
-        * on gravitatory rest can be after ecc or con (see RestAfterEcc)
-        */
+
+       //on inertial rest is after ecc.
+       //on gravitatory rest can be after ecc or con (see RestAfterEcc)
 
 
        //constructor
@@ -153,10 +432,8 @@ public class EncoderRhythmExecute
                return (nreps % encoderRhythm.RepsCluster == 0);
        }
 
-       /*
-        * if RepsOrPhases == true (by phases), then ChangePhase will be called when repetition ends
-        * else will be called when ecc or con ends
-        */
+        // if RepsOrPhases == true (by phases), then ChangePhase will be called when repetition ends
+        // else will be called when ecc or con ends
        public void ChangePhase(int nrep, bool up)
        {
                lastRepetitionDT = DateTime.Now;
@@ -178,12 +455,11 @@ public class EncoderRhythmExecute
                if(restClusterTimeEndedFlag)
                        return false;
 
-               /*
-                * We are resting when we done more than 0 repetitions, AND
-                * mod of repetitions by RepsCluster == 0 AND
-                * if repetition ends on c, whe have done c (or if it ends on e, we have done e)
-                */
-               //if(nreps > 0 && nreps % encoderRhythm.RepsCluster == 0 && lastIsUp == eccon_ec)
+                // We are resting when we done more than 0 repetitions, AND
+                // mod of repetitions by RepsCluster == 0 AND
+                // if repetition ends on c, whe have done c (or if it ends on e, we have done e)
+
+                //if(nreps > 0 && nreps % encoderRhythm.RepsCluster == 0 && lastIsUp == eccon_ec)
                if(nreps > 0 && nreps % encoderRhythm.RepsCluster == 0 && restBetweenRepetitions())
                {
                        if(totalSeconds < encoderRhythm.RestClustersSeconds)
@@ -220,11 +496,10 @@ public class EncoderRhythmExecute
                if(encoderRhythm.UseClusters() && firstInCluster())
                        restRepsSeconds = 0;
 
-               /*
-                * if ( (we ended concentric and it's ecc-con ||
-                *    we ended excentric and it's con-ecc) && totalSeconds < restRepsSeconds)
-                *    then there's a rest between repetitions
-                */
+                // if ( (we ended concentric and it's ecc-con ||
+                //   we ended excentric and it's con-ecc) && totalSeconds < restRepsSeconds)
+                //    then there's a rest between repetitions
+
                //if(lastIsUp == eccon_ec && totalSeconds < restRepsSeconds)
                if (totalSeconds < restRepsSeconds && restBetweenRepetitions())
                {
@@ -240,10 +515,9 @@ public class EncoderRhythmExecute
                TextRest = "";
                        fractionRest = 0;
 
-               /*
-                * if we ended con and repetition ends at con, then substract restRepsSeconds to totalSeconds 
to calculate fraction
-                * also when we done ecc and repetition ends at ecc
-                */
+               // if we ended con and repetition ends at con, then substract restRepsSeconds to totalSeconds 
to calculate fraction
+               // also when we done ecc and repetition ends at ecc
+
                //if(restRepsSeconds > 0 && lastIsUp == eccon_ec)
                if( restRepsSeconds > 0 && restBetweenRepetitions())
                        totalSeconds -= restRepsSeconds;
@@ -294,3 +568,4 @@ public class EncoderRhythmExecute
                }
        }
 }
+*/
diff --git a/src/gui/encoder.cs b/src/gui/encoder.cs
index ef690d5..d37bb29 100644
--- a/src/gui/encoder.cs
+++ b/src/gui/encoder.cs
@@ -5294,10 +5294,7 @@ public partial class ChronoJumpWindow
                                                portName,
                                                (encoderConfigurationCurrent.has_inertia && 
eCaptureInertialBG != null),
                                                configChronojump.EncoderCaptureShowOnlyBars,
-                                               currentSession.Name == Constants.SessionSimulatedName && 
testsActive,
-                                               (encoderRhythm.Active),
-                                               encoderRhythm.RepsOrPhases
-                                               );
+                                               currentSession.Name == Constants.SessionSimulatedName && 
testsActive);
 
                                if(encoderConfigurationCurrent.has_inertia && eCaptureInertialBG != null)
                                {
@@ -5327,9 +5324,6 @@ public partial class ChronoJumpWindow
                                {
                                        notebook_encoder_signal_comment_rhythm_and_triggers.Page = 1;
                                        image_encoder_rhythm_rest.Visible = encoderRhythm.UseRest();
-
-                                       eCapture.FakeButtonRhythm.Clicked -= new 
EventHandler(on_encoder_rhythm_changed);
-                                       eCapture.FakeButtonRhythm.Clicked += new 
EventHandler(on_encoder_rhythm_changed);
                                }
 
                                encoderRProcCapture.CutByTriggers = reallyCutByTriggers;
@@ -5350,10 +5344,7 @@ public partial class ChronoJumpWindow
                                                
chronopicRegister.ConnectedOfType(ChronopicRegisterPort.Types.ENCODER).Port,
                                                false,
                                                false,
-                                               false,
-                                               false, //encoderRhythm.Active
-                                               encoderRhythm.RepsOrPhases
-                                               );
+                                               false);
 
                                encoderRProcCapture.CutByTriggers = Preferences.TriggerTypes.NO_TRIGGERS; 
//do not cutByTriggers on inertial, yet.
 
@@ -5811,6 +5802,21 @@ public partial class ChronoJumpWindow
 
                        if(needToRefreshTreeviewCapture) 
                        {
+                               if(! encoderRhythmExecute.FirstPhaseDone)
+                               {
+                                       bool upOrDown = true;
+                                       string myEccon = findEccon(false);
+                                       if (myEccon == "c")
+                                               upOrDown = true;
+                                       else if (myEccon == "ec" || myEccon == "ecS")
+                                               upOrDown = false;
+                                       else // (myEccon == "ce" || myEccon == "ceS")
+                                               upOrDown = true;
+
+                                       LogB.Information(encoderRhythm.ToString());
+                                       encoderRhythmExecute.FirstPhaseDo(upOrDown);
+                               }
+
                                //LogB.Error("HERE YES");
                                //LogB.Error(encoderCaptureStringR);
 
@@ -6037,7 +6043,7 @@ public partial class ChronoJumpWindow
 
        private void updatePulsebarRhythm()
        {
-               if(! encoderRhythmExecute.FirstRepetitionDone())
+               if(! encoderRhythmExecute.FirstPhaseDone)
                {
                        encoder_pulsebar_rhythm_eccon.Fraction = 0;
                        label_encoder_rhythm_rest.Text = "";
@@ -6047,18 +6053,10 @@ public partial class ChronoJumpWindow
                }
 
                encoderRhythmExecute.CalculateFractionsAndText();
-               encoder_pulsebar_rhythm_eccon.Fraction = encoderRhythmExecute.FractionRepetition;
+               encoder_pulsebar_rhythm_eccon.Fraction = encoderRhythmExecute.Fraction;
                encoder_pulsebar_rhythm_eccon.Text = encoderRhythmExecute.TextRepetition;
                label_encoder_rhythm_rest.Text = encoderRhythmExecute.TextRest;
                image_encoder_rhythm_rest.Visible = encoderRhythmExecute.TextRest != "";
-
-               //TODO: this warning should appear also if value is 0, end of ecc phase
-               //image_encoder_rhythm_alert.Visible = (encoderRhythmExecute.FractionRepetition >= 1);
-       }
-       //no GTK here (just in case)
-       private void on_encoder_rhythm_changed(object o, EventArgs args)
-       {
-               encoderRhythmExecute.ChangePhase(eCapture.RhythmNRep, eCapture.RhythmEcconUp);
        }
 
        // -------------- drawingarea_encoder_analyze_instant
diff --git a/src/gui/repetitiveConditions.cs b/src/gui/repetitiveConditions.cs
index af2eda0..072f859 100644
--- a/src/gui/repetitiveConditions.cs
+++ b/src/gui/repetitiveConditions.cs
@@ -154,6 +154,7 @@ public class RepetitiveConditionsWindow
        [Widget] Gtk.Image image_repetitive_test_bad;
 
        //encoder rhythm
+       [Widget] Gtk.Label label_rhythm_tab;
        [Widget] Gtk.CheckButton check_rhythm_active;
        [Widget] Gtk.RadioButton radio_rhythm_together;
        [Widget] Gtk.RadioButton radio_rhythm_separated;
@@ -170,6 +171,9 @@ public class RepetitiveConditionsWindow
        [Widget] Gtk.SpinButton spin_rhythm_reps_cluster;
        [Widget] Gtk.SpinButton spin_rhythm_rest_clusters;
        [Widget] Gtk.Image image_clusters_info;
+       [Widget] Gtk.HBox hbox_rhythm_rest_reps_value;
+       [Widget] Gtk.CheckButton check_rhythm_rest_reps;
+
 
        const int FEEDBACKPAGE = 0;
        const int RHYTHMPAGE = 1;
@@ -207,6 +211,8 @@ public class RepetitiveConditionsWindow
                notebook_encoder_conditions.CurrentPage = 3; //power
 
                putNonStandardIcons();
+
+               label_rhythm_tab.Text = Catalog.GetString("Rhythm") + " / " + Catalog.GetString("Protocol");
        }
 
        static public RepetitiveConditionsWindow Create ()
@@ -617,18 +623,34 @@ public class RepetitiveConditionsWindow
 
        private void on_radio_rhythm_together_toggled (object o, EventArgs args)
        {
-               if(radio_rhythm_together.Active) {
+               if(radio_rhythm_together.Active)
                        notebook_duration_repetition.CurrentPage = 0;
-                       vbox_rhythm_rest_after.Visible = false;
-               } else {
+               else
                        notebook_duration_repetition.CurrentPage = 1;
-                       vbox_rhythm_rest_after.Visible = true;
-               }
+
+               should_show_vbox_rhythm_rest_after();
+       }
+
+       private void should_show_vbox_rhythm_rest_after()
+       {
+               vbox_rhythm_rest_after.Visible = ( check_rhythm_use_clusters.Active ||
+                               ( check_rhythm_rest_reps.Active && radio_rhythm_separated.Active ) );
+       }
+
+       private void on_check_rhythm_rest_reps_toggled (object o, EventArgs args)
+       {
+               if(check_rhythm_rest_reps.Active)
+                       hbox_rhythm_rest_reps_value.Visible = true;
+               else
+                       hbox_rhythm_rest_reps_value.Visible = false;
+
+               should_show_vbox_rhythm_rest_after();
        }
 
        private void on_check_rhythm_use_clusters_toggled (object o, EventArgs args)
        {
                vbox_rhythm_cluster.Visible = check_rhythm_use_clusters.Active;
+               should_show_vbox_rhythm_rest_after();
        }
 
        private void on_button_use_clusters_help_clicked (object o, EventArgs args)
@@ -658,13 +680,10 @@ public class RepetitiveConditionsWindow
        {
                check_rhythm_active.Active = encoderRhythm.Active;
 
-               if(encoderRhythm.RepsOrPhases) {
+               if(encoderRhythm.RepsOrPhases)
                        radio_rhythm_together.Active = true;
-                       vbox_rhythm_rest_after.Visible = false;
-               } else {
+               else
                        radio_rhythm_separated.Active = true;
-                       vbox_rhythm_rest_after.Visible = true;
-               }
 
                spin_rhythm_rep.Value = encoderRhythm.RepSeconds;
                spin_rhythm_ecc.Value = encoderRhythm.EccSeconds;
@@ -680,6 +699,9 @@ public class RepetitiveConditionsWindow
                else
                        notebook_duration_repetition.CurrentPage = 1;
 
+               if(encoderRhythm.RestRepsSeconds < 0.1)
+                       check_rhythm_rest_reps.Active = false;
+
                if(encoderRhythm.UseClusters()) {
                        check_rhythm_use_clusters.Active = true;
                        vbox_rhythm_cluster.Visible = true;
@@ -687,6 +709,8 @@ public class RepetitiveConditionsWindow
                        check_rhythm_use_clusters.Active = false;
                        vbox_rhythm_cluster.Visible = false;
                }
+
+               should_show_vbox_rhythm_rest_after();
        }
 
        public EncoderRhythm Encoder_rhythm_get_values()
@@ -695,11 +719,19 @@ public class RepetitiveConditionsWindow
                if(! check_rhythm_use_clusters.Active && reps_cluster > 1)
                        reps_cluster = 1;
 
+               //avoid problems like having spin values of: 1.38777878078145E-16 (true story)
+               double restReps = spin_rhythm_rest_reps.Value;
+               if(restReps < 0.1 || ! check_rhythm_rest_reps.Active)
+                       restReps = 0;
+               double restClusters = spin_rhythm_rest_clusters.Value;
+               if(restClusters < 0.1)
+                       restClusters = 0;
+
                return new EncoderRhythm(
                                check_rhythm_active.Active, radio_rhythm_together.Active,
                                spin_rhythm_rep.Value, spin_rhythm_ecc.Value, spin_rhythm_con.Value,
-                               spin_rhythm_rest_reps.Value, radio_rest_after_ecc.Active,
-                               reps_cluster, spin_rhythm_rest_clusters.Value);
+                               restReps, radio_rest_after_ecc.Active,
+                               reps_cluster, restClusters);
        }
 
 
diff --git a/src/util.cs b/src/util.cs
index 7f1a9a2..59cbb63 100644
--- a/src/util.cs
+++ b/src/util.cs
@@ -1813,11 +1813,12 @@ public class Util
        //avoids divide by zero
        //thought for being between 0, 1
        //ideal for progressBars
-       public static double DivideSafeFraction (double val1, double val2) {
-               if(val1 == 0 || val2 == 0)
+       public static double DivideSafeFraction (double num, double denom)
+       {
+               if(num == 0 || denom == 0)
                        return 0;
 
-               double result = val1 / val2;
+               double result = num / denom;
                
                if(result > 1)
                        result = 1;



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