[chronojump] CairoPaintBarplotPreEncoder uses new FeedbackEncoder class, adding more stuff to the Cairo graph



commit c4c13807831ef7d00bb79632d37ba7bb46f3d3ee
Author: Xavier de Blas <xaviblas gmail com>
Date:   Tue Mar 22 17:38:38 2022 +0100

    CairoPaintBarplotPreEncoder uses new FeedbackEncoder class, adding more stuff to the Cairo graph

 src/gui/app1/chronojump.cs     |   5 +-
 src/gui/app1/encoder.cs        |  10 +-
 src/gui/encoderGraphObjects.cs |   2 +-
 src/gui/eventExecute.cs        | 233 ++++++++++++++++++++++++++++++++++++++---
 src/gui/usefulObjects.cs       |  10 +-
 5 files changed, 237 insertions(+), 23 deletions(-)
---
diff --git a/src/gui/app1/chronojump.cs b/src/gui/app1/chronojump.cs
index 525c84a39..433d94f98 100644
--- a/src/gui/app1/chronojump.cs
+++ b/src/gui/app1/chronojump.cs
@@ -487,6 +487,7 @@ public partial class ChronoJumpWindow
        
        ConfirmWindowJumpRun confirmWinJumpRun; //for deleting jumps and RJ jumps (and runs)
        ReportWindow reportWin;
+       FeedbackEncoder feedback;
        FeedbackWindow feedbackWin;
        GenericWindow genericWin;
                
@@ -682,6 +683,7 @@ public partial class ChronoJumpWindow
 
                createComboSessionLoadTags(true);
 
+               feedback = new FeedbackEncoder (preferences);
                feedbackWin = FeedbackWindow.Create();
                //to have objects ok to be able to be readed before viewing the feedbackWin
                feedbackWin.View(Constants.BellModes.ENCODERGRAVITATORY, preferences, encoderRhythm, false); 
//not viewWindow
@@ -7817,7 +7819,7 @@ LogB.Debug("mc finished 5");
                                                                secondaryVariableStr, 
preferences.encoderCaptureShowLoss,
                                                                false, //not capturing
                                                                findEccon(true),
-                                                               feedbackWin,
+                                                               feedback,
                                                                encoderConfigurationCurrent.has_inertia,
                                                                configChronojump.PlaySoundsFromFile,
                                                                captureCurvesBarsData,
@@ -7826,6 +7828,7 @@ LogB.Debug("mc finished 5");
                                                                
sendMaxPowerSpeedForceIntersession(preferences.encoderCaptureMainVariable),
                                                                
sendMaxPowerSpeedForceIntersessionDate(preferences.encoderCaptureMainVariable),
                                                                
preferences.encoderCaptureInertialDiscardFirstN,
+                                                               preferences.encoderCaptureShowNRepetitions,
                                                                preferences.volumeOn,
                                                                preferences.gstreamer);
                                                prepareEncoderBarplotCairo ();
diff --git a/src/gui/app1/encoder.cs b/src/gui/app1/encoder.cs
index 2874f00a3..e8999687d 100644
--- a/src/gui/app1/encoder.cs
+++ b/src/gui/app1/encoder.cs
@@ -5901,7 +5901,7 @@ public partial class ChronoJumpWindow
                                                secondaryVariable, preferences.encoderCaptureShowLoss,
                                                false, //not capturing
                                                findEccon(true),
-                                               feedbackWin,
+                                               feedback,
                                                encoderConfigurationCurrent.has_inertia,
                                                configChronojump.PlaySoundsFromFile,
                                                captureCurvesBarsData,
@@ -5910,6 +5910,7 @@ public partial class ChronoJumpWindow
                                                
sendMaxPowerSpeedForceIntersession(preferences.encoderCaptureMainVariable),
                                                
sendMaxPowerSpeedForceIntersessionDate(preferences.encoderCaptureMainVariable),
                                                preferences.encoderCaptureInertialDiscardFirstN,
+                                               preferences.encoderCaptureShowNRepetitions,
                                                preferences.volumeOn,
                                                preferences.gstreamer);
                        prepareEncoderBarplotCairo ();
@@ -6038,6 +6039,7 @@ public partial class ChronoJumpWindow
                        return;
 
                cairoPaintBarsPre = new CairoPaintBarplotPreEncoder (
+                               preferences,
                                encoder_capture_curves_bars_drawingarea_cairo, 
preferences.fontType.ToString(),
                                currentPerson.Name, "", 3,
                                prepareEventGraphBarplotEncoder);
@@ -6791,7 +6793,7 @@ public partial class ChronoJumpWindow
                                                        secondaryVariable, preferences.encoderCaptureShowLoss,
                                                        true, //capturing
                                                        findEccon(true),
-                                                       feedbackWin,
+                                                       feedback,
                                                        encoderConfigurationCurrent.has_inertia,
                                                        configChronojump.PlaySoundsFromFile,
                                                        captureCurvesBarsData,
@@ -6800,6 +6802,7 @@ public partial class ChronoJumpWindow
                                                        
sendMaxPowerSpeedForceIntersession(preferences.encoderCaptureMainVariable),
                                                        
sendMaxPowerSpeedForceIntersessionDate(preferences.encoderCaptureMainVariable),
                                                        preferences.encoderCaptureInertialDiscardFirstN,
+                                                       preferences.encoderCaptureShowNRepetitions,
                                                        preferences.volumeOn,
                                                        preferences.gstreamer);
                                        prepareEncoderBarplotCairo ();
@@ -7393,7 +7396,7 @@ public partial class ChronoJumpWindow
                                                        secondaryVariable, preferences.encoderCaptureShowLoss,
                                                        false, //not capturing
                                                        findEccon(true),
-                                                       feedbackWin,
+                                                       feedback,
                                                        encoderConfigurationCurrent.has_inertia,
                                                        configChronojump.PlaySoundsFromFile,
                                                        captureCurvesBarsData,
@@ -7402,6 +7405,7 @@ public partial class ChronoJumpWindow
                                                        
sendMaxPowerSpeedForceIntersession(preferences.encoderCaptureMainVariable),
                                                        
sendMaxPowerSpeedForceIntersessionDate(preferences.encoderCaptureMainVariable),
                                                        preferences.encoderCaptureInertialDiscardFirstN,
+                                                       preferences.encoderCaptureShowNRepetitions,
                                                        preferences.volumeOn,
                                                        preferences.gstreamer);
                                        prepareEncoderBarplotCairo ();
diff --git a/src/gui/encoderGraphObjects.cs b/src/gui/encoderGraphObjects.cs
index 66a9e98dc..cbf1e645a 100644
--- a/src/gui/encoderGraphObjects.cs
+++ b/src/gui/encoderGraphObjects.cs
@@ -130,7 +130,7 @@ public class EncoderGraphDoPlot
                graphHeight = drawingarea.Allocation.Height;
        }
 
-       //preferences can change        
+       //preferences can change
        public void NewPreferences (Preferences preferences)
        {
                this.preferences = preferences;
diff --git a/src/gui/eventExecute.cs b/src/gui/eventExecute.cs
index 5dbce049d..c4abcf087 100644
--- a/src/gui/eventExecute.cs
+++ b/src/gui/eventExecute.cs
@@ -3372,15 +3372,17 @@ public class CairoManageRunDoubleContacts
 public class CairoPaintBarplotPreEncoder : CairoPaintBarsPre
 {
        private PrepareEventGraphBarplotEncoder pegbe;
+       private Preferences preferences;
 
-       //private ArrayList data; //data is related to mainVariable (barplot)
-       private List<PointF> dataA_l; //data is related to mainVariable (barplot)
-       private List<PointF> dataB_l; //data is related to mainVariable (barplot)
+       //copied from gui/encoderGraphObjects (using ArrayList)
+       private ArrayList data; //data is related to mainVariable (barplot)
        private ArrayList dataSecondary; //dataSecondary is related to secondary variable (by default range)
        private ArrayList dataRangeOfMovement; //ROM, need it to discard last rep for loss. Is not the same 
as dataSecondary because maybe user selected another variable as secondary. only checks con.
        private ArrayList dataWorkJ;
        private ArrayList dataImpulse;
 
+       private List<PointF> dataA_l; //data is related to mainVariable (barplot)
+       private List<PointF> dataB_l; //data is related to mainVariable (barplot)
        private List<Cairo.Color> colorMain_l;
        private List<Cairo.Color> colorSecondary_l;
        private List<string> names_l;
@@ -3393,11 +3395,12 @@ public class CairoPaintBarplotPreEncoder : CairoPaintBarsPre
 
        //isLastCaptured: if what we are showing is currentJumpRj then true, if is a selection from treeview 
and id != currentJumpRj then is false (meaning selected)
 
-       public CairoPaintBarplotPreEncoder (DrawingArea darea, string fontStr,
+       public CairoPaintBarplotPreEncoder (Preferences preferences, DrawingArea darea, string fontStr,
                        string personName, string testName, int pDN,
                        PrepareEventGraphBarplotEncoder pegbe)
        {
                this.pegbe = pegbe;
+               NewPreferences (preferences);
 
                initialize (darea, fontStr, mode, personName, testName, pDN);
        }
@@ -3415,21 +3418,106 @@ public class CairoPaintBarplotPreEncoder : CairoPaintBarsPre
 
        protected override void paintSpecific()
        {
-               fillDataVariables ();
+               //TODO: reorg/rename this
+               fillDataVariables1 ();
+               fillDataVariables2 ();
+
                paintSpecificDo ();
        }
 
-       private void fillDataVariables ()
+       //preferences can change
+       public void NewPreferences (Preferences preferences)
        {
-               //data = new ArrayList (pegbe.data9Variables.Count); //data is related to mainVariable 
(barplot)
-               dataA_l = new List<PointF>(); //data is related to mainVariable (barplot)
-               dataB_l = new List<PointF>(); //data is related to mainVariable (barplot)
+               this.preferences = preferences;
+
+               pegbe.discardFirstN = preferences.encoderCaptureInertialDiscardFirstN;
+               pegbe.showNRepetitions = preferences.encoderCaptureShowNRepetitions;
+
+               /*
+               if(layout_encoder_capture_curves_bars != null)
+                       layout_encoder_capture_curves_bars.FontDescription =
+                               Pango.FontDescription.FromString 
(preferences.GetFontTypeWithSize(preferences.encoderCaptureBarplotFontSize));
+               */
+       }
+
+       public void ShowMessage(string message, bool showLine, bool big)
+       {
+               //TODO
+       }
+
+       private void fillDataVariables1 () //copied from gui/encoderGraphObjects fillDataVariables()
+       {
+               data = new ArrayList (pegbe.data9Variables.Count); //data is related to mainVariable (barplot)
                dataSecondary = new ArrayList (pegbe.data9Variables.Count); //dataSecondary is related to 
secondary variable (by default range)
                dataRangeOfMovement = new ArrayList (pegbe.data9Variables.Count);
                dataWorkJ = new ArrayList (pegbe.data9Variables.Count);
                dataImpulse = new ArrayList (pegbe.data9Variables.Count);
                bool lastIsEcc = false;
-               //int count = 0;
+               int count = 0;
+
+               //discard repetitions according to pegbe.showNRepetitions
+               foreach(EncoderBarsData ebd in pegbe.data9Variables)
+               {
+                       //LogB.Information(string.Format("count: {0}, value: {1}", count, 
ebd.GetValue(pegbe.mainVariable)));
+                       //when capture ended, show all repetitions
+                       if(pegbe.showNRepetitions == -1 || ! pegbe.capturing)
+                       {
+                               data.Add(ebd.GetValue(pegbe.mainVariable));
+                               if(pegbe.secondaryVariable != "")
+                                       dataSecondary.Add(ebd.GetValue(pegbe.secondaryVariable));
+                               dataRangeOfMovement.Add(ebd.GetValue(Constants.RangeAbsolute));
+                               dataWorkJ.Add(ebd.GetValue(Constants.WorkJ));
+                               dataImpulse.Add(ebd.GetValue(Constants.Impulse));
+                       }
+                       else {
+                               if(pegbe.eccon == "c" && ( pegbe.data9Variables.Count <= 
pegbe.showNRepetitions ||      //total repetitions are less than show repetitions threshold ||
+                                               count >= pegbe.data9Variables.Count - pegbe.showNRepetitions 
) )        //count is from the last group of reps (reps that have to be shown)
+                               {
+                                       data.Add(ebd.GetValue(pegbe.mainVariable));
+                                       if(pegbe.secondaryVariable != "")
+                                               dataSecondary.Add(ebd.GetValue(pegbe.secondaryVariable));
+                                       dataRangeOfMovement.Add(ebd.GetValue(Constants.RangeAbsolute));
+                                       dataWorkJ.Add(ebd.GetValue(Constants.WorkJ));
+                                       dataImpulse.Add(ebd.GetValue(Constants.Impulse));
+                               }
+                               else if(pegbe.eccon != "c" && (
+                                               pegbe.data9Variables.Count <= 2 * pegbe.showNRepetitions ||
+                                               count >= pegbe.data9Variables.Count - 2 * 
pegbe.showNRepetitions) )
+                               {
+                                       if(! Util.IsEven(count +1))     //if it is "impar"
+                                       {
+                                               LogB.Information("added ecc");
+                                               data.Add(ebd.GetValue(pegbe.mainVariable));
+                                               if(pegbe.secondaryVariable != "")
+                                                       
dataSecondary.Add(ebd.GetValue(pegbe.secondaryVariable));
+                                               
dataRangeOfMovement.Add(ebd.GetValue(Constants.RangeAbsolute));
+                                               dataWorkJ.Add(ebd.GetValue(Constants.WorkJ));
+                                               dataImpulse.Add(ebd.GetValue(Constants.Impulse));
+                                               lastIsEcc = true;
+                                       } else {                        //it is "par"
+                                               if(lastIsEcc)
+                                               {
+                                                       data.Add(ebd.GetValue(pegbe.mainVariable));
+                                                       if(pegbe.secondaryVariable != "")
+                                                               
dataSecondary.Add(ebd.GetValue(pegbe.secondaryVariable));
+                                                       
dataRangeOfMovement.Add(ebd.GetValue(Constants.RangeAbsolute));
+                                                       dataWorkJ.Add(ebd.GetValue(Constants.WorkJ));
+                                                       dataImpulse.Add(ebd.GetValue(Constants.Impulse));
+                                                       LogB.Information("added con");
+                                                       lastIsEcc = false;
+                                               }
+                                       }
+                               }
+                       }
+                       //LogB.Information("data workJ: " + dataWorkJ[count].ToString());
+                       count ++;
+               }
+       }
+
+       private void fillDataVariables2 ()
+       {
+               dataA_l = new List<PointF>(); //data is related to mainVariable (barplot)
+               dataB_l = new List<PointF>(); //data is related to mainVariable (barplot)
 
                colorMain_l = new List<Cairo.Color>();
                colorSecondary_l = new List<Cairo.Color>();
@@ -3443,12 +3531,129 @@ public class CairoPaintBarplotPreEncoder : CairoPaintBarsPre
                //final color of the bar
                Cairo.Color colorBar = new Cairo.Color();
 
-               //discard repetitions according to showNRepetitions
+               int count = 0;
+
+               //Get max min avg values of this set
+               double maxThisSetForGraph = -100000;
+               double maxThisSetForCalc = -100000;
+               double minThisSet = 100000;
+               /*
+                * if ! Preferences.EncoderPhasesEnum.BOTH, eg: ECC, we can graph max CON (that maybe is the 
highest value) , but for calculations we want only the max ECC value, so:
+                * maxThisSetForGraph will be to plot the margins,
+                * maxThisSetForCalc will be to calculate feedback (% of max)
+                */
+
+               //only used for loss. For loss only con phase is used
+               double maxThisSetValidAndCon = maxThisSetForCalc;
+               double minThisSetValidAndCon = minThisSet;
+               //we need the position to draw the loss line and maybe to manage that the min should be after 
the max (for being real loss)
+               int maxThisSetValidAndConPos = 0;
+               int minThisSetValidAndConPos = 0;
+
+               //know not-discarded phases
+               double countValid = 0;
+               double sumValid = 0;
+               double workTotal = 0; //can be J or Kcal (shown in cal)
+               double impulseTotal = 0;
+
+               foreach(double d in data)
+               {
+                       if(d > maxThisSetForGraph)
+                               maxThisSetForGraph = d;
+
+                       if(pegbe.eccon == "c" ||
+                                       preferences.encoderCaptureFeedbackEccon == 
Preferences.EncoderPhasesEnum.BOTH ||
+                                       preferences.encoderCaptureFeedbackEccon == 
Preferences.EncoderPhasesEnum.ECC && ! Util.IsEven(count +1) || //odd (impar)
+                                       preferences.encoderCaptureFeedbackEccon == 
Preferences.EncoderPhasesEnum.CON && Util.IsEven(count +1) ) //even (par)
+                       {
+                               if(d > maxThisSetForCalc)
+                                       maxThisSetForCalc = d;
+                       }
+
+                       if(d < minThisSet)
+                               minThisSet = d;
+
+                       if( pegbe.hasInertia && pegbe.discardFirstN > 0 &&
+                                         ((pegbe.eccon == "c" && count < pegbe.discardFirstN) || 
(pegbe.eccon != "c" && count < pegbe.discardFirstN * 2)) )
+                               LogB.Information("Discarded phase");
+                       else if(pegbe.eccon == "c" ||
+                                       preferences.encoderCaptureFeedbackEccon == 
Preferences.EncoderPhasesEnum.BOTH ||
+                                       preferences.encoderCaptureFeedbackEccon == 
Preferences.EncoderPhasesEnum.ECC && ! Util.IsEven(count +1) || //odd (impar)
+                                       preferences.encoderCaptureFeedbackEccon == 
Preferences.EncoderPhasesEnum.CON && Util.IsEven(count +1) ) //even (par)
+                       {
+                               countValid ++;
+                               sumValid += d;
+                               bool needChangeMin = false;
+
+                               if(pegbe.eccon == "c" || Util.IsEven(count +1)) //par
+                               {
+                                       if(d > maxThisSetValidAndCon) {
+                                               maxThisSetValidAndCon = d;
+                                               maxThisSetValidAndConPos = count;
+
+                                               //min rep has to be after max
+                                               needChangeMin = true;
+                                       }
+                                       if(needChangeMin || (d < minThisSetValidAndCon &&
+                                                               Convert.ToDouble(dataRangeOfMovement[count]) 
= .7 * Convert.ToDouble(dataRangeOfMovement[maxThisSetValidAndConPos])
+                                                               //ROM of this rep cannot be lower than 70% of 
ROM of best rep (helps to filter when you leave the weight on the bar...)
+                                                           ) ) {
+                                               minThisSetValidAndCon = d;
+                                               minThisSetValidAndConPos = count;
+                                       }
+                               }
+                       }
+
+                       count ++;
+               }
+               if(maxThisSetForCalc <= 0)
+               {
+                       if(countValid > 0 &&
+                                       (pegbe.mainVariable != Constants.Range && pegbe.mainVariable != 
Constants.RangeAbsolute &&
+                                        pegbe.mainVariable != Constants.MeanSpeed && pegbe.mainVariable != 
Constants.MaxSpeed) )
+                               //TODO:
+                               /*
+                               ShowMessage(
+                                               Catalog.GetString("Main variable:") + " " + 
Catalog.GetString(pegbe.mainVariable) + "\n\n" +
+                                               Catalog.GetString("Bars are not shown because the displaced 
mass is 0."),
+                                               false, false);
+                                               */
+
+                       return;
+               }
+
+               double maxAbsoluteForCalc = maxThisSetForCalc;
+               //can be on meanPower, meanSpeed, meanForce
+               if(! pegbe.relativeToSet)
+               {
+                       //relative to historical of this person
+
+                       /*
+                        *
+                        * if there's a set captured but without repetitions saved, 
maxPowerSpeedForceIntersession will be 0
+                        * and current set (loaded or captured) will have a power that will be out of the 
graph
+                        * for this reason use maxAbsolute or maxThisSet, whatever is higher
+                        *
+                        * if ! relativeToSet, then Preferences.EncoderPhasesEnum.BOTH, so maxAbsoluteForCalc 
== maxAbsoluteForGraph
+                        */
+                       if(pegbe.maxPowerSpeedForceIntersession > maxAbsoluteForCalc)
+                       {
+                               maxAbsoluteForCalc = pegbe.maxPowerSpeedForceIntersession;
+                               //maxAbsoluteForGraph = maxPowerSpeedForceIntersession;
+                       }
+               }
+
+               LogB.Information("maxAbsoluteForCalc = " + maxAbsoluteForCalc.ToString());
+               pegbe.feedback.ResetBestSetValue(FeedbackEncoder.BestSetValueEnum.CAPTURE_MAIN_VARIABLE);
+               pegbe.feedback.UpdateBestSetValue(
+                               FeedbackEncoder.BestSetValueEnum.CAPTURE_MAIN_VARIABLE, maxAbsoluteForCalc);
+
+               //discard repetitions according to pegbe.showNRepetitions
                //int countToDraw = pegbe.data9Variables.Count;
                //foreach(EncoderBarsData ebd in pegbe.data9Variables)
                //for (int count = 0; count < pegbe.data9Variables.Count; count ++)
 //             int countNames = 0;
-               for (int count = (pegbe.data9Variables.Count -1); count >= 0; count --)
+               for (count = (pegbe.data9Variables.Count -1); count >= 0; count --)
                {
                        EncoderBarsData ebd = (EncoderBarsData) pegbe.data9Variables[count];
 
@@ -3463,8 +3668,8 @@ public class CairoPaintBarplotPreEncoder : CairoPaintBarsPre
                        }
 
                        //select pen color for bars and sounds
-                       string myColor = pegbe.feedbackWin.AssignColorAutomatic(
-                                       FeedbackWindow.BestSetValueEnum.CAPTURE_MAIN_VARIABLE, 
ebd.GetValue(pegbe.mainVariable), phaseEnum);
+                       string myColor = pegbe.feedback.AssignColorAutomatic(
+                                       FeedbackEncoder.BestSetValueEnum.CAPTURE_MAIN_VARIABLE, 
ebd.GetValue(pegbe.mainVariable), phaseEnum);
 
                        bool discarded = false;
                        if(pegbe.hasInertia) {
diff --git a/src/gui/usefulObjects.cs b/src/gui/usefulObjects.cs
index d9f4f52ed..63b822e31 100644
--- a/src/gui/usefulObjects.cs
+++ b/src/gui/usefulObjects.cs
@@ -394,7 +394,7 @@ public class PrepareEventGraphBarplotEncoder
        public bool showLoss;
        public bool capturing;
        public string eccon;
-       public FeedbackWindow feedbackWin;
+       public FeedbackEncoder feedback;
        public bool hasInertia;
        public bool playSoundsFromFile;
        public ArrayList data9Variables;
@@ -403,6 +403,7 @@ public class PrepareEventGraphBarplotEncoder
        public double maxPowerSpeedForceIntersession; //it will be one of these 3
        public string maxPowerSpeedForceIntersessionDate;
        public int discardFirstN;
+       public int showNRepetitions;
        public bool volumeOn;
        public Preferences.GstreamerTypes gstreamer;
 
@@ -413,12 +414,12 @@ public class PrepareEventGraphBarplotEncoder
                        string mainVariable, double mainVariableHigher, double mainVariableLower,
                        string secondaryVariable, bool showLoss,
                        bool capturing, string eccon,
-                       FeedbackWindow feedbackWin,
+                       FeedbackEncoder feedback,
                        bool hasInertia, bool playSoundsFromFile,
                        ArrayList data9Variables, Gtk.ListStore encoderCaptureListStore,
                        bool relativeToSet,
                        double maxPowerSpeedForceIntersession, string maxPowerSpeedForceIntersessionDate,
-                       int discardFirstN, bool volumeOn, Preferences.GstreamerTypes gstreamer)
+                       int discardFirstN, int showNRepetitions, bool volumeOn, Preferences.GstreamerTypes 
gstreamer)
 
        {
                this.mainVariable = mainVariable;
@@ -428,7 +429,7 @@ public class PrepareEventGraphBarplotEncoder
                this.showLoss = showLoss;
                this.capturing = capturing;
                this.eccon = eccon;
-               this.feedbackWin = feedbackWin;
+               this.feedback = feedback;
                this.hasInertia = hasInertia;
                this.playSoundsFromFile = playSoundsFromFile;
                this.data9Variables = data9Variables;
@@ -437,6 +438,7 @@ public class PrepareEventGraphBarplotEncoder
                this.maxPowerSpeedForceIntersession = maxPowerSpeedForceIntersession;
                this.maxPowerSpeedForceIntersessionDate = maxPowerSpeedForceIntersessionDate;
                this.discardFirstN = discardFirstN;
+               this.showNRepetitions = showNRepetitions;
                this.volumeOn = volumeOn;
                this.gstreamer = gstreamer;
        }


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