[chronojump] RunEncoder export C# code
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] RunEncoder export C# code
- Date: Wed, 3 Mar 2021 10:44:18 +0000 (UTC)
commit 9ada38803805fe3926b655adbb4e577be69b31c5
Author: Xavier de Blas <xaviblas gmail com>
Date: Wed Mar 3 11:42:52 2021 +0100
RunEncoder export C# code
glade/app1.glade | 56 ++++++
src/forceSensor.cs | 1 +
src/gui/app1/runEncoder.cs | 2 +-
src/gui/app1/runEncoderAnalyze.cs | 24 +++
src/runEncoder.cs | 405 ++++++++++++++++++++++++++++++++++++--
src/util.cs | 7 +
6 files changed, 480 insertions(+), 15 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index b7942309..f46b95c4 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -26709,6 +26709,62 @@ Concentric</property>
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <widget class="GtkButton"
id="button_run_encoder_export_current_session">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked"
handler="on_button_run_encoder_export_current_session_clicked" swapped="no"/>
+ <child>
+ <widget class="GtkHBox" id="hbox182">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="label111">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">Export</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkImage"
id="image_force_sensor_analyze_table_save1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property
name="stock">gtk-missing-image</property>
+ </widget>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkImage"
id="image_force_sensor_analyze_table_save_2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property
name="stock">gtk-missing-image</property>
+ </widget>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index 9cf8caa8..7df09d43 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -1568,6 +1568,7 @@ public class ForceSensorGraphAB
}
+//this class creates the rows of each force sensor AB for the csv input multi that is read by R
public class ForceSensorGraphABExport: ForceSensorGraphAB
{
public string fullURL;
diff --git a/src/gui/app1/runEncoder.cs b/src/gui/app1/runEncoder.cs
index 5feae744..c939e9fd 100644
--- a/src/gui/app1/runEncoder.cs
+++ b/src/gui/app1/runEncoder.cs
@@ -1085,7 +1085,7 @@ public partial class ChronoJumpWindow
Preferences.RunEncoderShouldPlotVariable(Preferences.RunEncoderPlotVariables.FITTEDPOWER),
triggerListRunEncoder);
- reg.CallR(imageWidth, imageHeight);
+ reg.CallR(imageWidth, imageHeight, true);
DateTime runEncoderGraphStarted = DateTime.Now;
//TODO: check better if png is saved and have a cancel button
diff --git a/src/gui/app1/runEncoderAnalyze.cs b/src/gui/app1/runEncoderAnalyze.cs
index aa0022c3..46987ab4 100644
--- a/src/gui/app1/runEncoderAnalyze.cs
+++ b/src/gui/app1/runEncoderAnalyze.cs
@@ -235,4 +235,28 @@ public partial class ChronoJumpWindow
string myString = string.Format(Catalog.GetString("Saved to {0}"), exportFileName);
new DialogMessage(Constants.MessageTypes.INFO, myString);
}
+
+ RunEncoderExport runEncoderExport;
+ private void on_button_run_encoder_export_current_session_clicked (object o, EventArgs args)
+ {
+ runEncoderExport = new RunEncoderExport (
+ true, //includeImages //TODO
+ UtilAll.IsWindows(),
+ -1, //all persons
+ currentSession.UniqueID,
+ preferences.runEncoderMinAccel,
+
Preferences.RunEncoderShouldPlotVariable(Preferences.RunEncoderPlotVariables.RAWACCEL),
+
Preferences.RunEncoderShouldPlotVariable(Preferences.RunEncoderPlotVariables.FITTEDACCEL),
+
Preferences.RunEncoderShouldPlotVariable(Preferences.RunEncoderPlotVariables.RAWFORCE),
+
Preferences.RunEncoderShouldPlotVariable(Preferences.RunEncoderPlotVariables.FITTEDFORCE),
+
Preferences.RunEncoderShouldPlotVariable(Preferences.RunEncoderPlotVariables.RAWPOWER),
+
Preferences.RunEncoderShouldPlotVariable(Preferences.RunEncoderPlotVariables.FITTEDPOWER),
+ preferences.CSVExportDecimalSeparatorChar //decimalIsPointAtExport
(write)
+ );
+
+ //runEncoderExport.Start(selectedFileName); //file or folder
+ runEncoderExport.Start("runEncoderExport.csv"); //file or folder
+
+ //TODO: continue with cancel stuff, ...
+ }
}
diff --git a/src/runEncoder.cs b/src/runEncoder.cs
index d2921cbc..19f320b9 100644
--- a/src/runEncoder.cs
+++ b/src/runEncoder.cs
@@ -20,7 +20,9 @@
using System;
using System.IO; //for detect OS //TextWriter
+using System.Collections; //ArrayList
using System.Collections.Generic; //List<T>
+using System.Threading;
using Mono.Unix;
public class RunEncoder
@@ -172,6 +174,9 @@ public class RunEncoder
public static string GetScript() {
return System.IO.Path.Combine(UtilEncoder.GetSprintPath(), "sprintEncoder.R");
}
+ public static string GetCSVInputMulti() {
+ return Path.Combine(Path.GetTempPath(), "cj_race_analyzer_input_multi.csv");
+ }
//this contains only Pulses;Time(useconds);Force(N)
public static string GetCSVFileName() {
return Path.Combine(Path.GetTempPath(), "cj_race_analyzer_data.csv");
@@ -208,6 +213,10 @@ public class RunEncoder
get { return uniqueID; }
set { uniqueID = value; }
}
+ public int PersonID
+ {
+ get { return personID; }
+ }
public int ExerciseID
{
get { return exerciseID; }
@@ -401,6 +410,299 @@ public class RunEncoderCSV
}
}
+public class RunEncoderExport
+{
+ public Gtk.Button Button_done;
+
+ //passed variables
+ /*
+ private Gtk.Notebook notebook;
+ private Gtk.ProgressBar progressbar;
+ private Gtk.Label labelResult;
+ */
+ private bool includeImages;
+ private string exportURL; //folder or .csv depending on includeImages
+ private bool isWindows;
+ private int personID; // -1: all
+ private int sessionID;
+ private double startAccel;
+ private bool plotRawAccel;
+ private bool plotFittedAccel;
+ private bool plotRawForce;
+ private bool plotFittedForce;
+ private bool plotRawPower;
+ private bool plotFittedPower;
+ private char exportDecimalSeparator;
+
+ private static Thread thread;
+ private static bool cancel;
+ private static bool noData;
+ private static bool cannotCopy;
+ private static string messageToProgressbar;
+
+ private List<RunEncoder> re_l;
+ ArrayList personSession_l;
+ private ArrayList reEx_l;
+ private int imageWidth = 900; //nothing is displayed, remove when R script has been adapted
+ private int imageHeight = 600; //nothing is displayed, remove when R script has been adapted
+
+ //constructor
+ public RunEncoderExport (
+// Gtk.Notebook notebook,
+// Gtk.ProgressBar progressbar,
+// Gtk.Label labelResult,
+ bool includeImages,
+ bool isWindows,
+ int personID,
+ int sessionID,
+ double startAccel,
+ bool plotRawAccel, bool plotFittedAccel,
+ bool plotRawForce, bool plotFittedForce,
+ bool plotRawPower, bool plotFittedPower,
+ char exportDecimalSeparator
+ )
+ {
+// this.notebook = notebook;
+// this.progressbar = progressbar;
+// this.labelResult = labelResult;
+ this.includeImages = includeImages;
+ this.isWindows = isWindows;
+ this.personID = personID;
+ this.sessionID = sessionID;
+ this.startAccel = startAccel;
+ this.plotRawAccel = plotRawAccel;
+ this.plotFittedAccel = plotFittedAccel;
+ this.plotRawForce = plotRawForce;
+ this.plotFittedForce = plotFittedForce;
+ this.plotRawPower = plotRawPower;
+ this.plotFittedPower = plotFittedPower;
+ this.exportDecimalSeparator = exportDecimalSeparator;
+
+ Button_done = new Gtk.Button();
+ }
+
+ ///public method
+ public void Start(string exportURL)
+ {
+ this.exportURL = exportURL;
+
+ cancel = false;
+ noData = false;
+ cannotCopy = false;
+// progressbar.Fraction = 0;
+ messageToProgressbar = "";
+// notebook.CurrentPage = 1;
+
+ //create progressbar and graph files dirs or delete their contents
+ createOrEmptyDir(Util.GetRunEncoderTempProgressDir());
+ createOrEmptyDir(Util.GetRunEncoderTempGraphsDir());
+
+ thread = new Thread (new ThreadStart (runEncoderExportDo));
+ GLib.Idle.Add (new GLib.IdleHandler (pulseRunEncoderExportGTK));
+ thread.Start();
+ }
+
+ private void createOrEmptyDir(string dir)
+ {
+ if( ! Directory.Exists(dir))
+ Directory.CreateDirectory (dir);
+ else {
+ DirectoryInfo dirInfo = new DirectoryInfo(dir);
+ foreach (FileInfo file in dirInfo.GetFiles())
+ file.Delete();
+ }
+ }
+
+ public void Cancel()
+ {
+ cancel = true;
+ }
+
+ private bool pulseRunEncoderExportGTK ()
+ {
+ if(! thread.IsAlive || cancel)
+ {
+ LogB.Information("pulseRunEncoderExportGTK ending here");
+ LogB.ThreadEnded();
+
+ //Button_done.Click();
+
+ return false;
+ }
+
+ Thread.Sleep (100);
+ return true;
+ }
+
+ private void runEncoderExportDo()
+ {
+ getData();
+
+ if(re_l.Count == 0)
+ {
+ LogB.Information("There's no data");
+ noData = true;
+ return;
+ }
+
+ processRunEncoderSets();
+ }
+
+ private void getData ()
+ {
+ re_l = SqliteRunEncoder.Select(false, -1, personID, sessionID);
+ personSession_l = SqlitePersonSession.SelectCurrentSessionPersons(sessionID, true);
+ reEx_l = SqliteRunEncoderExercise.Select (false, -1, false);
+ }
+
+ private bool processRunEncoderSets ()
+ {
+ Person p = new Person();
+ PersonSession ps = new PersonSession();
+
+ List<RunEncoderGraphExport> rege_l = new List<RunEncoderGraphExport>();
+
+ int count = 1;
+ foreach(RunEncoder re in re_l)
+ {
+ // 1) checks
+ //check fs is ok
+ if(re == null || ! Util.FileExists(re.FullURL))
+ continue;
+
+ //check fs has data
+ List<string> contents = Util.ReadFileAsStringList(re.FullURL);
+ if(contents.Count < 3)
+ {
+ //new DialogMessage(Constants.MessageTypes.WARNING, Constants.FileEmptyStr());
+ //return;
+ continue;
+ }
+
+ // 2) get the person
+ bool found = false;
+ foreach(PersonAndPS paps in personSession_l)
+ {
+ if(paps.p.UniqueID == re.PersonID)
+ {
+ p = paps.p;
+ ps = paps.ps;
+
+ found = true;
+ break;
+ }
+ }
+ if(! found)
+ continue;
+
+ // 3) get the exercise
+ found = false;
+ RunEncoderExercise reEx = new RunEncoderExercise();
+ foreach(RunEncoderExercise reExTemp in reEx_l)
+ if(reExTemp.UniqueID == re.ExerciseID)
+ {
+ reEx = reExTemp;
+ found = true;
+ break;
+ }
+ if(! found)
+ continue;
+
+ // 4) create the export row
+ string title = Util.ChangeSpaceAndMinusForUnderscore(p.Name) + "-" +
+ Util.ChangeSpaceAndMinusForUnderscore(reEx.Name);
+
+ RunEncoderGraphExport rege = new RunEncoderGraphExport (
+ re.FullURL,
+ ps.Weight, ps.Height,
+ re.Device,
+ re.Temperature, re.Distance,
+ reEx, title, re.DateTimePublic,
+ re.Comments
+ );
+ rege_l.Add(rege);
+
+ }
+
+ // call the graph
+
+ if(rege_l.Count > 0)
+ {
+ RunEncoderGraph reg = new RunEncoderGraph(
+ startAccel,
+ plotRawAccel, plotFittedAccel,
+ plotRawForce, plotFittedForce,
+ plotRawPower, plotFittedPower,
+ //triggerList,
+ rege_l,
+ exportDecimalSeparator,
+ includeImages
+ );
+
+ bool success = reg.CallR(imageWidth -5, imageHeight -5, false);
+ }
+
+ return true;
+ }
+
+}
+
+//this class creates the rows of each force sensor AB for the csv input multi that is read by R
+public class RunEncoderGraphExport
+{
+ private string fullURL;
+ private double mass;
+ private double personHeight;
+ private RunEncoder.Devices device;
+ private double tempC;
+ private int testLength;
+ private RunEncoderExercise rex;
+ private string title;
+ private string datetime;
+ private string comments;
+
+ public RunEncoderGraphExport(
+ string fullURL,
+ double mass, double personHeight,
+ RunEncoder.Devices device,
+ double tempC, int testLength,
+ RunEncoderExercise rex, string title, string datetime,
+ string comments)
+ {
+ this.fullURL = fullURL; //filename
+ this.mass = mass;
+ this.personHeight = personHeight;
+ this.device = device;
+ this.tempC = tempC;
+ this.testLength = testLength;
+ this.rex = rex;
+ this.title = title;
+ this.datetime = datetime;
+ this.comments = comments;
+ }
+
+ public string ToCSVRowOnExport()
+ {
+ return fullURL + ";" +
+ Util.ConvertToPoint(mass) + ";" +
+ Util.ConvertToPoint(personHeight / 100.0) + ";" + //in meters
+ device.ToString() + ";" +
+ Util.ConvertToPoint(tempC) + ";" +
+ testLength.ToString() + ";" +
+ rex.SegmentMeters.ToString() + ";" +
+ title + ";" +
+ datetime + ";" +
+ Util.RemoveChar(comments, ';'); //TODO: check this really removes
+ }
+
+ public static string PrintCSVHeaderOnExport()
+ {
+ return "fullURL;mass;personHeight;device;tempC;testLength;" +
+ "splitLength;" + //segmentMeters on C#, splitLength on R
+ "title;datetime;comments";
+ }
+}
+
public class RunEncoderGraph
{
private int testLength;
@@ -419,8 +721,11 @@ public class RunEncoderGraph
private bool plotRawPower;
private bool plotFittedPower;
private TriggerList triggerList;
+ private char exportDecimalSeparator;
+ private bool includeImagesOnExport;
- public RunEncoderGraph(int testLength, double mass, double personHeight, double tempC,
RunEncoder.Devices device,
+ private void assignGenericParams(
+ int testLength, double mass, double personHeight, double tempC, RunEncoder.Devices
device,
RunEncoderExercise rex,
string title, string datetime, double startAccel,
bool plotRawAccel, bool plotFittedAccel,
@@ -446,14 +751,65 @@ public class RunEncoderGraph
this.triggerList = triggerList;
}
- public bool CallR(int graphWidth, int graphHeight)
+ //constructor for 1 set
+ public RunEncoderGraph(
+ int testLength, double mass, double personHeight, double tempC, RunEncoder.Devices
device,
+ RunEncoderExercise rex,
+ string title, string datetime, double startAccel,
+ bool plotRawAccel, bool plotFittedAccel,
+ bool plotRawForce, bool plotFittedForce,
+ bool plotRawPower, bool plotFittedPower,
+ TriggerList triggerList)
+ {
+ assignGenericParams(
+ testLength, mass, personHeight, tempC, device,
+ rex,
+ title, datetime, startAccel,
+ plotRawAccel, plotFittedAccel,
+ plotRawForce, plotFittedForce,
+ plotRawPower, plotFittedPower,
+ triggerList);
+
+ this.exportDecimalSeparator = '.'; //TODO
+ this.includeImagesOnExport = false;
+ }
+
+ //constructor for export (many sets of possible different persons)
+ public RunEncoderGraph(
+ double startAccel,
+ bool plotRawAccel, bool plotFittedAccel,
+ bool plotRawForce, bool plotFittedForce,
+ bool plotRawPower, bool plotFittedPower,
+ //TriggerList triggerList,
+ List<RunEncoderGraphExport> rege_l,
+ char exportDecimalSeparator,
+ bool includeImagesOnExport
+ )
+ {
+ assignGenericParams(
+ 0, 0, 0, 0, RunEncoder.Devices.MANUAL, //TODO do not pass to assignParams
+ new RunEncoderExercise(), //TODO do not pass to assignParams
+ "----", "----", startAccel, //TODO do not pass to assignParams
+ plotRawAccel, plotFittedAccel,
+ plotRawForce, plotFittedForce,
+ plotRawPower, plotFittedPower,
+ new TriggerList() //TODO do not pass to assignParams
+ );
+
+ this.exportDecimalSeparator = exportDecimalSeparator;
+ this.includeImagesOnExport = includeImagesOnExport;
+
+ writeMultipleFilesCSV(rege_l);
+ }
+
+ public bool CallR(int graphWidth, int graphHeight, bool singleOrMultiple)
{
LogB.Information("\nrunEncoder CallR ----->");
- writeOptionsFile(graphWidth, graphHeight);
+ writeOptionsFile(graphWidth, graphHeight, singleOrMultiple);
return ExecuteProcess.CallR(RunEncoder.GetScript());
}
- private void writeOptionsFile(int graphWidth, int graphHeight)
+ private void writeOptionsFile(int graphWidth, int graphHeight, bool singleOrMultiple)
{
string scriptsPath = UtilEncoder.GetSprintPath();
if(UtilAll.IsWindows())
@@ -464,18 +820,18 @@ public class RunEncoderGraph
string scriptOptions =
"#scriptsPath\n" + UtilEncoder.GetScriptsPath() + "\n" +
- "#filename\n" + RunEncoder.GetCSVFileName() + "\n" +
- "#mass\n" + Util.ConvertToPoint(mass) + "\n" +
- "#personHeight\n" + Util.ConvertToPoint(personHeight / 100.0) + "\n" +
//send it in meters
- "#tempC\n" + tempC + "\n" +
- "#testLength\n" + testLength.ToString() + "\n" +
+ "#filename\n" + RunEncoder.GetCSVFileName() + "\n" + //unused on
multiple
+ "#mass\n" + Util.ConvertToPoint(mass) + "\n" + //unused on
multiple
+ "#personHeight\n" + Util.ConvertToPoint(personHeight / 100.0) + "\n" +
//unused on multiple //send it in meters
+ "#tempC\n" + tempC + "\n" + //unused on multiple
+ "#testLength\n" + testLength.ToString() + "\n" + //unused on multiple
"#os\n" + UtilEncoder.OperatingSystemForRGraphs() + "\n" +
"#graphWidth\n" + graphWidth.ToString() + "\n" +
"#graphHeight\n" + graphHeight.ToString() + "\n" +
- "#device\n" + device.ToString() + "\n" +
- "#segmentMeters\n" + rex.SegmentMeters + "\n" +
- "#title\n" + title + "\n" +
- "#datetime\n" + datetime + "\n" +
+ "#device\n" + device.ToString() + "\n" + //unused on multiple
+ "#segmentMeters\n" + rex.SegmentMeters + "\n" + //unused on multiple
+ "#title\n" + title + "\n" + //unused on multiple
+ "#datetime\n" + datetime + "\n" + //unused on multiple
"#startAccel\n" + Util.ConvertToPoint(startAccel) + "\n" +
"#plotRawAccel\n" + Util.BoolToRBool(plotRawAccel) + "\n" +
"#plotFittedAccel\n" + Util.BoolToRBool(plotFittedAccel) + "\n" +
@@ -484,7 +840,10 @@ public class RunEncoderGraph
"#plotRawPower\n" + Util.BoolToRBool(plotRawPower) + "\n" +
"#plotFittedPower\n" + Util.BoolToRBool(plotFittedPower) + "\n" +
printTriggers(TriggerList.Type3.ON) + "\n" +
- printTriggers(TriggerList.Type3.OFF);
+ printTriggers(TriggerList.Type3.OFF) + "\n" +
+ "#singleOrMultiple\n" + Util.BoolToRBool(singleOrMultiple) + "\n" +
+ "#decimalCharAtExport\n" + exportDecimalSeparator + "\n" +
+ "#includeImagesOnExport\n" + Util.BoolToRBool(includeImagesOnExport) + "\n";
TextWriter writer = File.CreateText(Path.GetTempPath() + "Roptions.txt");
@@ -494,6 +853,24 @@ public class RunEncoderGraph
((IDisposable)writer).Dispose();
}
+ private void writeMultipleFilesCSV(List<RunEncoderGraphExport> rege_l)
+ {
+ LogB.Information("writeMultipleFilesCSV start");
+ TextWriter writer = File.CreateText(RunEncoder.GetCSVInputMulti());
+
+ //write header
+ writer.WriteLine(RunEncoderGraphExport.PrintCSVHeaderOnExport());
+
+ //write fsgAB_l for
+ foreach(RunEncoderGraphExport rege in rege_l)
+ writer.WriteLine(rege.ToCSVRowOnExport());
+
+ writer.Flush();
+ writer.Close();
+ ((IDisposable)writer).Dispose();
+ LogB.Information("writeMultipleFilesCSV end");
+ }
+
private string printTriggers(TriggerList.Type3 type3)
{
return triggerList.ToRCurvesString(type3);
diff --git a/src/util.cs b/src/util.cs
index 79d3ff1f..342c9f4e 100644
--- a/src/util.cs
+++ b/src/util.cs
@@ -1115,6 +1115,13 @@ public class Util
}
}
+ public static string GetRunEncoderTempProgressDir() {
+ return Path.Combine(Path.GetTempPath(), "chronojump_race_analyzer_progress");
+ }
+ public static string GetRunEncoderTempGraphsDir() {
+ return Path.Combine(Path.GetTempPath(), "chronojump_race_analyzer_graphs");
+ }
+
/*
* <--------------- end of force sensor suff
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]