[chronojump] Run execute double contacts revamped for 1.8.1
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] Run execute double contacts revamped for 1.8.1
- Date: Mon, 26 Mar 2018 16:41:02 +0000 (UTC)
commit 43e9723db1e6db67ab83089108bc4f75c32377f7
Author: Xavier de Blas <xaviblas gmail com>
Date: Mon Mar 26 18:36:48 2018 +0200
Run execute double contacts revamped for 1.8.1
src/Makefile.am | 1 +
src/constants.cs | 11 +-
src/execute/event.cs | 73 +++++++-
src/execute/run.cs | 461 ++++++++++++++++++++-------------------------
src/execute/runObjects.cs | 376 ++++++++++++++++++++++++++++++++++++
src/gui/chronojump.cs | 4 +-
src/gui/eventExecute.cs | 28 +++-
7 files changed, 694 insertions(+), 260 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index cefe1ec..547d8c1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -134,6 +134,7 @@ SOURCES = \
execute/event.cs\
execute/jump.cs\
execute/run.cs\
+ execute/runObjects.cs\
execute/pulse.cs\
execute/reactionTime.cs\
execute/multiChronopic.cs\
diff --git a/src/constants.cs b/src/constants.cs
index a85ba69..2e2af53 100644
--- a/src/constants.cs
+++ b/src/constants.cs
@@ -926,8 +926,17 @@ public class Constants
public enum EncoderAutoSaveCurve { ALL, NONE, BEST, FROM4TOPENULTIMATE }
+ //BIGGEST_TC will be the default mode.
+ // - at END of each track: track ends before the biggest TC (just before the trunk arrives)
+ // - at START of each track:
+ // - if starting on contact:
+ // time starts when leaving it. Usually will be with the biggest part (trunk),
+ // and maybe later there's a foot, so leaving the contact on the first time is the
beginning.
+ // - on speed start, if there are double contacts,
+ // - if "race starts at arriving at platform", then race will start before big tc (trunk)
+ // - else, race will start after big tc (trunk)
public enum DoubleContact {
- NONE, FIRST, AVERAGE, LAST
+ NONE, FIRST, AVERAGE, LAST, BIGGEST_TC
}
//DISPLACED means: total
diff --git a/src/execute/event.cs b/src/execute/event.cs
index f238086..cfd3874 100644
--- a/src/execute/event.cs
+++ b/src/execute/event.cs
@@ -57,6 +57,8 @@ public class EventExecute
}
protected eventType needUpdateGraphType;
+ protected bool needCallTrackDone;
+ protected bool needCheckIfTrackEnded; //Races with double contacts wait some ms to see if other
contact appears
protected bool needShowCountDown; //RSA
//protected string syncMessage;
@@ -82,6 +84,8 @@ public class EventExecute
protected ExecutingGraphData egd;
+ //for runs
+ public RunPhaseTimeList runPTL;
//better as private and don't inherit, don't know why
@@ -312,7 +316,22 @@ public class EventExecute
egd.Button_finish.Sensitive = true;
needSensitiveButtonFinish = false;
}
-
+
+ // races specific --------------------------------->
+
+ //Race track with DoubleContacts mode NONE
+ if(needCallTrackDone)
+ {
+ trackDone();
+ needCallTrackDone = false;
+ }
+ //Race track with DoubleContacts mode != NONE
+ if(needCheckIfTrackEnded && lastTfCheckTimeEnded())
+ {
+ trackDone();
+ needCheckIfTrackEnded = false;
+ }
+
//RSA
if(needShowCountDown)
{
@@ -325,6 +344,7 @@ public class EventExecute
needShowFeedbackMessage = false;
}
+ // <-------------------------- end of races specific
//check if it should finish by time
if(shouldFinishByTime()) {
@@ -333,6 +353,8 @@ public class EventExecute
}
}
+ // races specific --------------------------------->
+
private void runATouchPlatform() {
UtilGtk.PrintLabelWithTooltip(egd.Label_message, feedbackMessage);
}
@@ -340,7 +362,18 @@ public class EventExecute
public void RunANoStrides() {
UtilGtk.PrintLabelWithTooltip(egd.Label_message, feedbackMessage);
}
-
+
+ protected virtual bool lastTfCheckTimeEnded()
+ {
+ return true;
+ }
+
+ protected virtual void trackDone()
+ {
+ }
+
+ // <-------------------------- end of races specific
+
protected void progressBarEventOrTimePreExecution (bool isEvent, bool percentageMode, double events)
{
if (isEvent)
@@ -477,6 +510,11 @@ public class EventExecute
return "";
}
+ public RunPhaseTimeList RunPTL
+ {
+ get { return runPTL; }
+ }
+
//from confirm_window cancel button (thread has not started)
//this is NOT called when a event has started and user click on "Cancel"
protected void cancel_event_before_start(object o, EventArgs args)
@@ -548,6 +586,37 @@ public class EventExecute
}
+public class PhaseTime
+{
+ private bool contactIn;
+ private double duration;
+
+ public PhaseTime (bool contactIn, double duration)
+ {
+ this.contactIn = contactIn;
+ this.duration = duration;
+ }
+
+ public override string ToString()
+ {
+ string strMode = "IN";
+ if(! contactIn)
+ strMode = "OUT";
+
+ //TODO: use a printf mode to have always same digits
+ return "\n" + Math.Round(Util.DivideSafe(duration, 1000.0), 3) + " - " + strMode;
+ }
+
+ public bool IsContact
+ {
+ get { return contactIn; }
+ }
+ public double Duration
+ {
+ get { return duration; }
+ }
+}
+
public class InOut
{
private bool contactIn;
diff --git a/src/execute/run.cs b/src/execute/run.cs
index f72bba4..ce38782 100644
--- a/src/execute/run.cs
+++ b/src/execute/run.cs
@@ -56,8 +56,11 @@ public class RunExecute : EventExecute
protected double timestampDCContactTimes; //sum of the contact times that happen in small time
protected double timestampDCn; //number of flight times in double contacts period
+ //static because they are used on both threads at the same time
protected static RunExecuteInspector runEI;
-
+ protected static RunDoubleContact runDC;
+ //protected static RunPhaseTimeList runPTL;
+ protected static bool success;
public RunExecute() {
}
@@ -208,7 +211,7 @@ public class RunExecute : EventExecute
timestampDCInitValues();
- bool success = false;
+ success = false;
bool ok;
//prepare variables to allow being cancelled or finished
@@ -230,12 +233,8 @@ public class RunExecute : EventExecute
if (ok && !cancel) {
//LogB.Information("timestamp:" + timestamp);
- if (platformState == Chronopic.Plataforma.ON && loggedState == States.OFF)
+ if (has_arrived()) // timestamp is tf
{
- /*
- * ---------------------------- has arrived ---------------------
- */
-
loggedState = States.ON;
if(runPhase == runPhases.PRE_RUNNING) {
@@ -366,14 +365,10 @@ public class RunExecute : EventExecute
}
}
}
- else if (platformState == Chronopic.Plataforma.OFF && loggedState ==
States.ON)
+ else if (has_lifted()) // timestamp is tc
{
- /*
- * ------------------it's out has abandoned photocell
----------------------
- */
//don't record time
- //change the automata state
loggedState = States.OFF;
if(checkDoubleContactMode != Constants.DoubleContact.NONE &&
timestampDCn > 0)
@@ -413,6 +408,15 @@ public class RunExecute : EventExecute
} while ( ! success && ! cancel );
runEI.ChangePhase(RunExecuteInspector.Phases.END);
}
+
+ protected bool has_arrived()
+ {
+ return (platformState == Chronopic.Plataforma.ON && loggedState == States.OFF);
+ }
+ protected bool has_lifted()
+ {
+ return (platformState == Chronopic.Plataforma.OFF && loggedState == States.ON);
+ }
protected override bool shouldFinishByTime() {
return false; //this kind of events (simple runs) cannot be finished by time
@@ -530,7 +534,10 @@ public class RunExecute : EventExecute
public override string GetInspectorMessages()
{
- return runEI.ToString();
+ if(runPTL != null)
+ return runEI.ToString() + "\n\n" + runPTL.ToString() + "\n\n" +
runPTL.InListForPaintingToString();
+ else
+ return runEI.ToString();
}
public string RunnerName
@@ -547,16 +554,20 @@ public class RunIntervalExecute : RunExecute
double distanceTotal;
double timeTotal;
double distanceInterval;
- string intervalTimesString;
- double tracks; //double because if we limit by time (runType tracksLimited false), we do n.nn tracks
string limited; //the teorically values, eleven runs: "11=R" (time recorded in "time"), 10 seconds:
"10=T" (tracks recorded in tracks)
double limitAsDouble; //-1 for non limited (unlimited repetitive run until "finish" is clicked)
bool tracksLimited;
-
string distancesString; //if distances are variable (distanceInterval == -1), this is used
double distanceIntervalFixed; //if distanceInterval == -1, then Fixed is the corresponding base on
distancesString
- double lastTc; //useful to know time on contact platform because intervalTimesString does
not differentiate
+
+ //static because they are used on both threads at the same time
+ static double tracks; //double because if we limit by time (runType tracksLimited false), we do n.nn
tracks
+ static string intervalTimesString;
+ //since trackDone is called by PulseGTK (onTimer)
+ static double lastTc; //useful to know time on contact platform because intervalTimesString
does not differentiate
+ static double lastTf; //used when no double contacts mode
+ static DateTime timerLastTf; //this two will be protected and in runSimpleExecute
bool RSABellDone;
@@ -625,7 +636,9 @@ public class RunIntervalExecute : RunExecute
needUpdateEventProgressBar = false;
needUpdateGraph = false;
-
+ needCallTrackDone = false;
+ needCheckIfTrackEnded = false;
+
timesForSavingRepetitive = 1; //number of times that this repetive event needs for being
recorded in temporal table
//initialize eventDone as a RunInterval
@@ -633,11 +646,13 @@ public class RunIntervalExecute : RunExecute
}
+ private string equal;
+ private int countForSavingTempTable;
protected override void waitEvent ()
{
double timestamp = 0;
- bool success = false;
- string equal = "";
+ success = false;
+ equal = "";
//initialize variables
intervalTimesString = "";
@@ -645,12 +660,14 @@ public class RunIntervalExecute : RunExecute
bool ok;
timerCount = 0;
//bool initialized = false;
- int countForSavingTempTable = 0;
+ countForSavingTempTable = 0;
+
lastTc = 0;
distanceIntervalFixed = distanceInterval;
timestampDCInitValues();
-
+ timerLastTf = DateTime.MinValue;
+
//prepare variables to allow being cancelled or finished
if(! simulated)
Chronopic.InitCancelAndFinish();
@@ -662,23 +679,33 @@ public class RunIntervalExecute : RunExecute
checkDoubleContactTime
);
runEI.ChangePhase(RunExecuteInspector.Phases.START);
+
+ //initialize runDC
+ runDC = new RunDoubleContact(
+ checkDoubleContactMode,
+ checkDoubleContactTime
+ );
+ runPTL = new RunPhaseTimeList();
+
+ bool exitWaitEventBucle = false;
+ int countBucle = 0; //just for debug now
do {
if(simulated)
ok = true;
else
ok = cp.Read_event(out timestamp, out platformState);
-
-
- if (ok && !cancel && !finish) {
+
+ LogB.Information(string.Format("countBucle = {0}; platformState = {1}; lastTc = {2};
lastTf = {3}", countBucle, platformState, lastTc, lastTf));
+ countBucle ++;
+
+
+ if (ok && ! cancel && ! finish)
+ {
if(distanceInterval == -1)
distanceIntervalFixed =
Util.GetRunIVariableDistancesStringRow(distancesString, (int) tracks);
- if (platformState == Chronopic.Plataforma.ON && loggedState == States.OFF)
+ if (has_arrived()) //timestamp is TF
{
- /*
- * ---------------------------- has arrived ---------------------
- */
-
loggedState = States.ON;
//show RSA count down only on air
@@ -714,156 +741,24 @@ public class RunIntervalExecute : RunExecute
if(simulated)
timestamp = simulatedTimeLast * 1000; //conversion to
milliseconds
- //prevent double contact stuff
- string runEIString = "";
- if(checkDoubleContactMode != Constants.DoubleContact.NONE) {
- if(timestamp <= checkDoubleContactTime) {
- /*
- when checking double contact
- first time that timestamp <
checkDoubleContactTime
- and we arrived (it's a flight time)
- record this time as timestampDCFlightTimes
- */
- timestampDCn ++;
- timestampDCFlightTimes += timestamp;
-
runEI.ChangePhase(RunExecuteInspector.Phases.IN,
- string.Format("RUNNING,
DOUBLECONTACT, timestamp: {0}, " +
- "has been added to
timestampDCFlightTimes: {1}",
- Math.Round(timestamp/1000.0,
3),
-
Math.Round(timestampDCFlightTimes/1000.0, 3)
- ));
-
- continue;
- }
- else {
- if(timestampDCn > 0) {
- if(checkDoubleContactMode ==
-
Constants.DoubleContact.FIRST) {
- /* user want first flight
time,
- then add all DC times*/
-
- double timestampTemp =
timestamp;
- timestamp +=
timestampDCFlightTimes +
-
timestampDCContactTimes;
-
- runEIString =
string.Format("RUNNING, DoubleContactMode.FIRST, timestamp was: {0} " +
- "added
DCFlightTimes: {1} and DCContactTimes: {2}, " +
- "now
timestamp is: {3}",
-
Math.Round(timestampTemp/1000.0, 3), Math.Round(timestampDCFlightTimes/1000.0, 3),
-
Math.Round(timestampDCContactTimes/1000.0, 3), Math.Round(timestamp/1000.0, 3));
- }
- else if(checkDoubleContactMode ==
-
Constants.DoubleContact.LAST) {
- //user want last flight time,
take that
- // so we don't need to change
timestamp. Or we could do (it triggers a warning):
- // timestamp = timestamp;
-
- runEIString =
string.Format("RUNNING, DoubleContactMode.LAST " +
- "do not
change timestamp, timestamp is: {0}", timestamp/1000.0);
- }
- else { // checkDoubleContactMode ==
AVERAGE
- /* do the avg of all flights
and contacts
- then add to last timestamp
*/
- double timestampTemp =
timestamp;
- timestamp +=
-
(timestampDCFlightTimes +
-
timestampDCContactTimes)
- / timestampDCn;
-
- runEIString =
string.Format("RUNNING, DoubleContactMode.AVERAGE, timestamp was: {0} " +
- "added
(DCFlightTimes: {1} + DCContactTimes: {2}) / n: {3}, " +
- "now
timestamp is: {4}",
-
Math.Round(timestampTemp/1000.0, 3), Math.Round(timestampDCFlightTimes/1000.0, 3),
-
Math.Round(timestampDCContactTimes/1000.0, 3), timestampDCn,
-
Math.Round(timestamp/1000.0, 3));
- }
-
- //init values of timestampDC for next
track
- timestampDCInitValues();
- }
- }
- }
-
- //note in double contacts mode timestamp can have added
DCFlightTimes and DCContactTimes. So contact time is not only on lastTc
- double myRaceTime = lastTc + timestamp/1000.0;
-
- runEI.ChangePhase(RunExecuteInspector.Phases.IN, runEIString +
- string.Format("; timestamp: {0};
<b>trackTime: {1}</b>",
- Math.Round(timestamp/1000.0, 3),
Math.Round(myRaceTime, 3)));
-
- LogB.Information(string.Format("RACE ({0}) TC: {1}; TV: {2};
TOTALTIME: {3}", tracks, lastTc, timestamp/1000.0, myRaceTime));
-
- if(intervalTimesString.Length > 0) { equal = "="; }
- intervalTimesString = intervalTimesString + equal +
myRaceTime.ToString();
- updateTimerCountWithChronopicData(intervalTimesString);
- tracks ++;
-
- //save temp table if needed
- countForSavingTempTable ++;
- if(countForSavingTempTable == timesForSavingRepetitive) {
- writeRunInterval(true); //tempTable
- countForSavingTempTable = 0;
- }
-
- if(limitAsDouble == -1) {
- //has arrived, unlimited
- updateProgressBar= new UpdateProgressBar (
- true, //isEvent
- true, //unlimited: activity mode
- tracks
- );
- needUpdateEventProgressBar = true;
- }
- else {
- //has arrived, limited
- if (tracksLimited) {
- //has arrived, limited by tracks
- if(tracks >= limitAsDouble)
- {
- runPhase = runPhases.PLATFORM_END;
-
- //finished
- writeRunInterval(false); //tempTable
= false
- success = true;
- }
- //progressBarEventOrTimePreExecution(
- updateProgressBar= new UpdateProgressBar (
- true, //isEvent
- true, //tracksLimited:
percentageMode
- tracks
- );
- needUpdateEventProgressBar = true;
- } else {
- //has arrived, limited by time
- updateProgressBar= new UpdateProgressBar (
- true, //isEvent
- false, //timeLimited:
activity mode
- tracks
- );
- needUpdateEventProgressBar = true;
- }
+ if(runDC.UseDoubleContacts())
+ {
+ runDC.DoneTF (timestamp);
+ timerLastTf = DateTime.Now;
+ needCheckIfTrackEnded = true;
+ } else
+ {
+ lastTf = timestamp;
+ //trackDone();
+ needCallTrackDone = true;
}
- distanceTotal = Util.GetRunITotalDistance(distanceInterval,
distancesString, tracks);
-
- //update graph
- PrepareEventGraphRunIntervalObject = new
PrepareEventGraphRunInterval(
- distanceIntervalFixed, myRaceTime,
intervalTimesString,
- distanceTotal, distancesString, startIn);
-
- needUpdateGraphType = eventType.RUNINTERVAL;
- needUpdateGraph = true;
-
- //put button_finish as sensitive when first jump is done
(there's something recordable)
- if(tracks == 1)
- needSensitiveButtonFinish = true;
+ runPTL.AddTF(timestamp);
}
}
- else if (platformState == Chronopic.Plataforma.OFF && loggedState ==
States.ON)
+ else if (has_lifted()) //timestamp is TC
{
- /*
- * ------------------it's out has abandoned photocell
----------------------
- */
+ loggedState = States.OFF;
lastTc = 0;
if(runPhase == runPhases.PLATFORM_INI_NO_TIME) {
@@ -884,22 +779,23 @@ public class RunIntervalExecute : RunExecute
lastTc = timestamp / 1000.0;
runEI.ChangePhase(RunExecuteInspector.Phases.OUT,
string.Format("SpeedStartArrival, tc = {0}",
Math.Round(lastTc, 3)));
+ runPTL.AddTC(timestamp);
}
feedbackMessage = "";
needShowFeedbackMessage = true;
} else {
- if(checkDoubleContactMode != Constants.DoubleContact.NONE &&
timestampDCn > 0)
+ runEI.ChangePhase(RunExecuteInspector.Phases.OUT,
+ string.Format("SpeedStartArrival, timestamp =
{0}", timestamp));
+
+ if(runDC.UseDoubleContacts())
{
- timestampDCContactTimes += timestamp;
- runEI.ChangePhase(RunExecuteInspector.Phases.OUT,
- string.Format("RUNNING double contact,
timestampDCContactTimes = {0}", Math.Round(timestampDCContactTimes/1000.0, 3)));
+ runDC.DoneTC(timestamp);
}
else {
lastTc = timestamp / 1000.0;
- runEI.ChangePhase(RunExecuteInspector.Phases.OUT,
- string.Format("RUNNING, tc = {0}",
Math.Round(lastTc, 3)));
}
+ runPTL.AddTC(timestamp);
//RSA
@@ -916,14 +812,30 @@ public class RunIntervalExecute : RunExecute
}
-
runPhase = runPhases.RUNNING;
+ }
+ }
- //change the automata state
- loggedState = States.OFF;
+ exitWaitEventBucle = false;
+ if(success || cancel || finish)
+ {
+ if(runDC.UseDoubleContacts())
+ {
+ LogB.Information(string.Format("success: {0}, cancel: {1}, finish:
{2}", success, cancel, finish));
+ while(needCheckIfTrackEnded)
+ {
+ LogB.Information("WAITING 100 MS TO EXIT BUCLE");
+ //TODO: checks what happens with cancel... in the pulse
thread, will change this boolean? needCheckIfTrackEnded
+ Thread.Sleep(100);
+ }
+
+ exitWaitEventBucle = true;
}
+ else
+ exitWaitEventBucle = true;
}
- } while ( ! success && ! cancel && ! finish );
+
+ } while ( ! exitWaitEventBucle );
runEI.ChangePhase(RunExecuteInspector.Phases.END);
if (finish) {
@@ -940,6 +852,116 @@ public class RunIntervalExecute : RunExecute
}
}
+ //this will be protected and in run simple execute class
+ protected override bool lastTfCheckTimeEnded()
+ {
+ TimeSpan span = DateTime.Now - timerLastTf;
+ if(span.TotalMilliseconds > checkDoubleContactTime * 1.5)
+ {
+ timerLastTf = DateTime.Now;
+ return true;
+ }
+ return false;
+ }
+
+ //this will be protected and in run simple execute class
+ //big change in 1.8.1: this will be called from GTK thread
+ //so don't write to SQL here
+ //and use static variables where needed
+ protected override void trackDone()
+ {
+ double myTrackTime = 0;
+ if(runDC.UseDoubleContacts())
+ myTrackTime = runDC.GetTrackTimeInSecondsAndEmptyLists(); //will come in seconds
+ else {
+ //note in double contacts mode timestamp can have added DCFlightTimes and
DCContactTimes. So contact time is not only on lastTc
+ myTrackTime = lastTc + lastTf/1000.0;
+ }
+
+ //runEI.ChangePhase(RunExecuteInspector.Phases.IN, runEIString +
+ runEI.ChangePhase(RunExecuteInspector.Phases.IN, //runEIString +
+ string.Format("; timestamp: {0}; <b>trackTime: {1}</b>",
+ Math.Round(lastTf/1000.0, 3), Math.Round(myTrackTime, 3)));
+
+ LogB.Information(string.Format("RACE ({0}) TC: {1}; TV: {2}; TOTALTIME: {3}", tracks, lastTc,
lastTf/1000.0, myTrackTime));
+
+ if(intervalTimesString.Length > 0) { equal = "="; }
+ intervalTimesString = intervalTimesString + equal + myTrackTime.ToString();
+ updateTimerCountWithChronopicData(intervalTimesString);
+ tracks ++;
+
+ /*
+ * Attention:
+ * don't do this because we are on GTK thread right now
+ * and here we are touching SQL
+ *
+ //save temp table if needed
+ countForSavingTempTable ++;
+ if(countForSavingTempTable == timesForSavingRepetitive) {
+ writeRunInterval(true); //tempTable
+ countForSavingTempTable = 0;
+ }
+ */
+
+ if(limitAsDouble == -1) {
+ //has arrived, unlimited
+ updateProgressBar= new UpdateProgressBar (
+ true, //isEvent
+ true, //unlimited: activity mode
+ tracks
+ );
+ needUpdateEventProgressBar = true;
+ }
+ else {
+ //has arrived, limited
+ if (tracksLimited) {
+ //has arrived, limited by tracks
+ if(tracks >= limitAsDouble)
+ {
+ runPhase = runPhases.PLATFORM_END;
+
+ //finished
+ writeRunInterval(false); //tempTable = false
+ success = true;
+
+ //as we will be on waitEvent do { ok = cp.Read_event ... }
+ //call this to end Read_cambio called by Read_event
+ Chronopic.FinishDo();
+ }
+ //progressBarEventOrTimePreExecution(
+ updateProgressBar= new UpdateProgressBar (
+ true, //isEvent
+ true, //tracksLimited: percentageMode
+ tracks
+ );
+ needUpdateEventProgressBar = true;
+ } else {
+ //has arrived, limited by time
+ updateProgressBar= new UpdateProgressBar (
+ true, //isEvent
+ false, //timeLimited: activity mode
+ tracks
+ );
+ needUpdateEventProgressBar = true;
+ }
+ }
+
+ distanceTotal = Util.GetRunITotalDistance(distanceInterval, distancesString, tracks);
+
+ //update graph
+ PrepareEventGraphRunIntervalObject = new PrepareEventGraphRunInterval(
+ distanceIntervalFixed, myTrackTime, intervalTimesString,
+ distanceTotal, distancesString, startIn);
+
+ needUpdateGraphType = eventType.RUNINTERVAL;
+ needUpdateGraph = true;
+
+ //put button_finish as sensitive when first jump is done (there's something recordable)
+ if(tracks == 1)
+ needSensitiveButtonFinish = true;
+ }
+
+
protected override string countDownMessage() {
double waitSeconds = Util.GetRunIVariableDistancesThisRowIsRSA(distancesString,
Convert.ToInt32(tracks))
- (timerCount - Util.GetTotalTime(intervalTimesString) - lastTc);
@@ -1119,7 +1141,8 @@ public class RunIntervalExecute : RunExecute
);
//define the created object
- eventDone = new RunInterval(uniqueID, personID, sessionID, type, distanceTotal,
timeTotal, distanceInterval, intervalTimesString, tracksHere, description, limitString,
Util.BoolToNegativeInt(simulated), !startIn);
+ eventDone = new RunInterval(uniqueID, personID, sessionID, type, distanceTotal,
timeTotal, distanceInterval, intervalTimesString,
+ tracksHere, description, limitString,
Util.BoolToNegativeInt(simulated), !startIn);
/*
string tempValuesString;
@@ -1207,69 +1230,3 @@ public class RunIntervalExecute : RunExecute
~RunIntervalExecute() {}
}
-
-public class RunExecuteInspector
-{
- public enum Types { RUN_SIMPLE, RUN_INTERVAL }
- private Types type;
-
- public enum Phases { START, IN, OUT, END }
- private DateTime dtStarted;
- private DateTime dtEnded;
-
- private bool speedStartArrival;
- Constants.DoubleContact checkDoubleContactMode;
- int checkDoubleContactTime;
-
- private List<InOut> listInOut;
-
-
- //constructor
- public RunExecuteInspector(Types type, bool speedStartArrival,
- Constants.DoubleContact checkDoubleContactMode, int checkDoubleContactTime)
- {
- this.type = type;
- this.speedStartArrival = speedStartArrival;
- this.checkDoubleContactMode = checkDoubleContactMode;
- this.checkDoubleContactTime = checkDoubleContactTime;
-
- listInOut = new List<InOut>();
- }
-
- //public methods
-
- public void ChangePhase(Phases phase)
- {
- ChangePhase(phase, "");
- }
- public void ChangePhase(Phases phase, string message)
- {
- DateTime dt = DateTime.Now;
-
- if(phase == Phases.START)
- dtStarted = dt;
- else if(phase == Phases.END)
- dtEnded = dt;
- else // (phase == Phases.IN || phases == Phases.OUT)
- {
- InOut inOut = new InOut(phase == Phases.IN, dt, message);
- listInOut.Add(inOut);
- //listInOut.Add(new InOut(phase == Phases.IN, dt, message));
- }
- }
-
- public override string ToString()
- {
- string report = string.Format("Report of race started at: {0}; ended at: {1}",
dtStarted.ToShortTimeString(), dtEnded.ToShortTimeString());
- report += "\n" + "Type: " + type.ToString();
- report += "\n" + "SpeedStartArrival: " + speedStartArrival;
- report += "\n" + "CheckDoubleContactMode: " + checkDoubleContactMode;
- report += "\n" + "CheckDoubleContactTime: " + checkDoubleContactTime;
- report += "\n" + "Chronopic changes:";
- foreach(InOut inOut in listInOut)
- {
- report += inOut.ToString();
- }
- return report;
- }
-}
diff --git a/src/execute/runObjects.cs b/src/execute/runObjects.cs
new file mode 100644
index 0000000..9919b66
--- /dev/null
+++ b/src/execute/runObjects.cs
@@ -0,0 +1,376 @@
+/*
+ * This file is part of ChronoJump
+ *
+ * ChronoJump is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * ChronoJump is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) 2018 Xavier de Blas <xaviblas gmail com>
+ */
+
+using System;
+using System.Data;
+using System.Collections.Generic; //List
+
+//contains for each phase: isContact? startMSInSequence duration
+public class RunPhaseInfo
+{
+ public enum Types { CONTACT, FLIGHT }
+
+ public Types type;
+ public double startMSInSequence; //unused right now
+ public double duration;
+
+ public RunPhaseInfo (Types type, double startMSInSequence, double duration)
+ {
+ this.type = type;
+ this.startMSInSequence = startMSInSequence;
+ this.duration = duration;
+ }
+
+ public bool IsContact()
+ {
+ return type == Types.CONTACT;
+ }
+
+ public double Duration {
+ get { return duration; }
+ }
+
+ public override string ToString()
+ {
+ return string.Format("type: {0}, startMSInSequence: {1}, duration: {2}",
+ type, startMSInSequence, duration);
+ }
+
+}
+//manage RunPhaseInfo list
+public class RunPhaseInfoManage
+{
+ private List<RunPhaseInfo> list;
+
+ public RunPhaseInfoManage ()
+ {
+ list = new List<RunPhaseInfo>();
+ }
+
+ public void Add (RunPhaseInfo rpi)
+ {
+ list.Add(rpi);
+ }
+
+ public int GetPosOfBiggestTC ()
+ {
+ //if there's no tc, return -1, track duration will be tf duration
+ //if there's one tc, return -1, track duration will be tc+tf duration
+ if(countTCs() < 2)
+ return -1;
+
+ //if there's more than one tc, return the pos of bigger tc,
+ //but first tc cannot be the biggest, because first tc will be always added (and first tf)
+ double max = 0;
+ int pos = 0;
+ int posBiggest = 0;
+ foreach(RunPhaseInfo rpi in list)
+ {
+ if(pos > 0 && rpi.IsContact() && rpi.Duration > max) //pos > 0 to not allow first tc
to be the biggest
+ {
+ max = rpi.Duration;
+ posBiggest = pos;
+ }
+
+ pos ++;
+ }
+ return posBiggest;
+ }
+
+ //if pos == -1 return all
+ public double SumUntilPos(int pos)
+ {
+ double sum = 0;
+
+ if(pos == -1) {
+ foreach(RunPhaseInfo rpi in list)
+ sum += rpi.Duration;
+ } else {
+ int count = 0;
+ foreach(RunPhaseInfo rpi in list)
+ if(count ++ < pos)
+ sum += rpi.Duration;
+ }
+
+ return sum;
+ }
+
+ //if pos == -1 empty all
+ public void EmtpyListUntilPos(int pos)
+ {
+ if(pos == -1)
+ list = new List<RunPhaseInfo>();
+ else {
+ List<RunPhaseInfo> listNew = new List<RunPhaseInfo>();
+ int count = 0;
+ foreach(RunPhaseInfo rpi in list)
+ if(count ++ >= pos)
+ listNew.Add(rpi);
+
+ list = listNew;
+ }
+ }
+
+ public string PrintList()
+ {
+ string str = "\n";
+ foreach(RunPhaseInfo rpi in list)
+ str += "\n" + rpi.ToString();
+
+ return str;
+ }
+
+ private int countTCs()
+ {
+ int count = 0;
+ foreach(RunPhaseInfo rpi in list)
+ if(rpi.IsContact())
+ count ++;
+
+ return count;
+ }
+
+ public int LastPositionOfList {
+ get { return list.Count -1; }
+ }
+}
+
+//manage double contacts in runs
+public class RunDoubleContact
+{
+ private Constants.DoubleContact mode;
+ private int checkTime;
+
+ private RunPhaseInfoManage rpim;
+
+ //these are used also to know track time if there are no double contacts
+ private double lastTc; //important to check lastTc and currentTF to measure if they are above or not
checkTime
+
+ private double timeAcumulated;
+
+ //constructor ------------------------------------------
+ public RunDoubleContact (Constants.DoubleContact mode, int checkTime)
+ {
+ this.mode = mode;
+ this.checkTime = checkTime;
+
+ lastTc = 0;
+ timeAcumulated = 0;
+ rpim = new RunPhaseInfoManage();
+ }
+
+ //public methods ---------------------------------------
+
+ public bool UseDoubleContacts ()
+ {
+ return (mode != Constants.DoubleContact.NONE);
+ }
+
+ public void DoneTC (double timestamp)
+ {
+ lastTc = timestamp;
+ rpim.Add(new RunPhaseInfo(RunPhaseInfo.Types.CONTACT, timeAcumulated, timestamp));
+ timeAcumulated += timestamp;
+ LogB.Information(string.Format("DoneTC -> lastTc: {0}", lastTc));
+ }
+
+ public void DoneTF (double timestamp)
+ {
+ LogB.Information(string.Format(
+ "lastTc + timestamp <= checkTime ?, lastTc: {0}; timestamp: {1};
checkTime: {2}",
+ lastTc, timestamp, checkTime));
+
+ rpim.Add(new RunPhaseInfo(RunPhaseInfo.Types.FLIGHT, timeAcumulated, timestamp));
+ timeAcumulated += timestamp;
+ }
+
+ //this wait will be done by C#
+ public double GetTrackTimeInSecondsAndEmptyLists()
+ {
+ double trackTime = 0;
+ /*
+ if(mode == Constants.FoubleContact.FIRST)
+ timestamp = getDCFirst();
+ else if(mode == Constants.FoubleContact.LAST)
+ timestamp = getDCLast();
+ else if(mode == Constants.FoubleContact.AVERAGE)
+ timestamp = getDCAverage();
+ else // if(mode == Constants.FoubleContact.BIGGEST_TC)
+ */
+ trackTime = getDCBiggestTC(); //superhardcoded
+
+ //in seconds
+ if(trackTime > 0)
+ trackTime /= 1000.0;
+
+ return trackTime;
+ }
+
+ //private methods --------------------------------------
+
+ private double getDCBiggestTC()
+ {
+ int bigTCPosition = rpim.GetPosOfBiggestTC();
+ double sum = rpim.SumUntilPos(bigTCPosition);
+
+ LogB.Information(string.Format("\n----------------\ngetDCBiggestTC, list: {0}, bigTCPosition:
{1}, sum: {2}", rpim.PrintList(), bigTCPosition, sum));
+
+ if(sum < checkTime)
+ {
+ while (sum < checkTime && bigTCPosition +2 <= rpim.LastPositionOfList)
+ {
+ bigTCPosition += 2;
+ sum = rpim.SumUntilPos(bigTCPosition);
+ LogB.Information(string.Format("SUM was < checkTime. New bigTCPosition: {0},
New Sum: {1}", bigTCPosition, sum));
+ }
+ }
+
+ rpim.EmtpyListUntilPos(bigTCPosition);
+
+ return sum;
+ }
+}
+
+//decide if use this or inspector
+public class RunPhaseTimeList
+{
+ private List<PhaseTime> listPhaseTime;
+
+ public RunPhaseTimeList()
+ {
+ listPhaseTime = new List<PhaseTime>();
+ }
+
+ public void AddTC(double timestamp)
+ {
+ listPhaseTime.Add(new PhaseTime(true, timestamp));
+ }
+
+ public void AddTF(double timestamp)
+ {
+ listPhaseTime.Add(new PhaseTime(false, timestamp));
+ }
+
+ public override string ToString()
+ {
+ string str = "";
+ foreach(PhaseTime pt in listPhaseTime)
+ str += pt.ToString();
+
+ return str;
+ }
+
+ public List<string> InListForPainting()
+ {
+ List<string> list_in = new List<string>();
+ int currentMS = 0;
+ int startInMS = -1;
+ foreach(PhaseTime pt in listPhaseTime)
+ {
+ if(pt.IsContact)
+ startInMS = currentMS;
+ else if(startInMS >= 0)
+ list_in.Add(startInMS/1000.0 + ":" + currentMS/1000.0); //in seconds
+
+ currentMS += Convert.ToInt32(pt.Duration);
+ }
+
+ return list_in;
+ }
+
+ //Debug
+ public string InListForPaintingToString()
+ {
+ string str = "Contact in time list:\n";
+ List<string> list_in = InListForPainting();
+ foreach(string s in list_in)
+ str += s + "\n";
+
+ return str;
+ }
+
+}
+
+//currently used for simple runs
+public class RunExecuteInspector
+{
+ public enum Types { RUN_SIMPLE, RUN_INTERVAL }
+ private Types type;
+
+ public enum Phases { START, IN, OUT, END }
+ private DateTime dtStarted;
+ private DateTime dtEnded;
+
+ private bool speedStartArrival;
+ Constants.DoubleContact checkDoubleContactMode;
+ int checkDoubleContactTime;
+
+ private List<InOut> listInOut;
+
+
+ //constructor
+ public RunExecuteInspector(Types type, bool speedStartArrival,
+ Constants.DoubleContact checkDoubleContactMode, int checkDoubleContactTime)
+ {
+ this.type = type;
+ this.speedStartArrival = speedStartArrival;
+ this.checkDoubleContactMode = checkDoubleContactMode;
+ this.checkDoubleContactTime = checkDoubleContactTime;
+
+ listInOut = new List<InOut>();
+ }
+
+ //public methods
+
+ public void ChangePhase(Phases phase)
+ {
+ ChangePhase(phase, "");
+ }
+ public void ChangePhase(Phases phase, string message)
+ {
+ DateTime dt = DateTime.Now;
+
+ if(phase == Phases.START)
+ dtStarted = dt;
+ else if(phase == Phases.END)
+ dtEnded = dt;
+ else // (phase == Phases.IN || phases == Phases.OUT)
+ {
+ InOut inOut = new InOut(phase == Phases.IN, dt, message);
+ listInOut.Add(inOut);
+ //listInOut.Add(new InOut(phase == Phases.IN, dt, message));
+ }
+ }
+
+ public override string ToString()
+ {
+ string report = string.Format("Report of race started at: {0}; ended at: {1}",
dtStarted.ToShortTimeString(), dtEnded.ToShortTimeString());
+ report += "\n" + "Type: " + type.ToString();
+ report += "\n" + "SpeedStartArrival: " + speedStartArrival;
+ report += "\n" + "CheckDoubleContactMode: " + checkDoubleContactMode;
+ report += "\n" + "CheckDoubleContactTime: " + checkDoubleContactTime;
+ report += "\n" + "Chronopic changes:";
+ foreach(InOut inOut in listInOut)
+ {
+ report += inOut.ToString();
+ }
+ return report;
+ }
+}
diff --git a/src/gui/chronojump.cs b/src/gui/chronojump.cs
index ef32f55..e2686e5 100644
--- a/src/gui/chronojump.cs
+++ b/src/gui/chronojump.cs
@@ -5443,7 +5443,9 @@ LogB.Debug("X");
distanceTotal,
runType.DistancesString,
currentRunInterval.StartIn,
- preferences.volumeOn, preferences.gstreamer,
repetitiveConditionsWin);
+ preferences.volumeOn, preferences.gstreamer,
repetitiveConditionsWin,
+ currentEventExecute.RunPTL
+ );
}
break;
case EventType.Types.FORCESENSOR:
diff --git a/src/gui/eventExecute.cs b/src/gui/eventExecute.cs
index b8a3a84..0b70793 100644
--- a/src/gui/eventExecute.cs
+++ b/src/gui/eventExecute.cs
@@ -707,7 +707,7 @@ public partial class ChronoJumpWindow
public void PrepareRunIntervalGraph(double distance, double lastTime, string timesString,
double distanceTotal, string distancesString,
bool startIn, bool volumeOn, Preferences.GstreamerTypes gstreamer,
- RepetitiveConditionsWindow repetitiveConditionsWin)
+ RepetitiveConditionsWindow repetitiveConditionsWin, RunPhaseTimeList runPTL)
{
//check graph properties window is not null (propably user has closed it with the DeleteEvent
//then create it, but not show it
@@ -750,7 +750,7 @@ public partial class ChronoJumpWindow
lastTime, timesString, Util.GetAverage(timesString),
maxValue, minValue, tracks, topMargin, bottomMargin,
Util.GetPosMax(timesString), Util.GetPosMin(timesString), startIn,
- volumeOn, gstreamer, repetitiveConditionsWin);
+ volumeOn, gstreamer, repetitiveConditionsWin, runPTL);
// -- refresh
event_execute_drawingarea.QueueDraw();
@@ -1435,7 +1435,7 @@ public partial class ChronoJumpWindow
double maxValue, double minValue, int tracks, int topMargin, int bottomMargin,
int hightValuePosition, int lowValuePosition, bool startIn,
bool volumeOn, Preferences.GstreamerTypes gstreamer,
- RepetitiveConditionsWindow repetitiveConditionsWin)
+ RepetitiveConditionsWindow repetitiveConditionsWin, RunPhaseTimeList runPTL)
{
//int topMargin = 10;
int ancho=drawingarea.Allocation.Width;
@@ -1478,8 +1478,24 @@ public partial class ChronoJumpWindow
Gdk.GC myPen = pen_rojo; //default value
double myValue = 0;
+ foreach (string inPTL in runPTL.InListForPainting())
+ {
+ string [] inPTLFull = inPTL.Split(new char[] {':'});
+ int xStart = event_execute_rightMargin + Convert.ToInt32((ancho -
2*event_execute_rightMargin) *
+ (Convert.ToDouble(inPTLFull[0]) / timeTotal));
+
+ int xEnd = event_execute_rightMargin + Convert.ToInt32((ancho -
2*event_execute_rightMargin) *
+ (Convert.ToDouble(inPTLFull[1]) / timeTotal));
+
+ //don't plot the TCs after current track
+ if(Convert.ToDouble(inPTLFull[0]) < timeTotal)
+ event_execute_pixmap.DrawRectangle(pen_gris, true,
+ new Rectangle (xStart, alto-bottomMargin-4,
xEnd-xStart, 4));
+ }
+
foreach (string myTime in myTimesStringFull)
{
+ LogB.Information(myTime.ToString());
myTimeDouble = Convert.ToDouble(myTime);
if(myTimeDouble < 0)
myTimeDouble = 0;
@@ -1979,13 +1995,17 @@ public partial class ChronoJumpWindow
volumeOnHere = false;
PrepareRunIntervalGraph(
+ //TODO: pass most of this as (including RunPTL)
+ //new PrepareEventGraphRunIntervalObject(distance,
lastTime, ...)
currentEventExecute.PrepareEventGraphRunIntervalObject.distance,
currentEventExecute.PrepareEventGraphRunIntervalObject.lastTime,
currentEventExecute.PrepareEventGraphRunIntervalObject.timesString,
currentEventExecute.PrepareEventGraphRunIntervalObject.distanceTotal,
currentEventExecute.PrepareEventGraphRunIntervalObject.distancesString,
currentEventExecute.PrepareEventGraphRunIntervalObject.startIn,
- volumeOnHere, preferences.gstreamer,
repetitiveConditionsWin);
+ volumeOnHere, preferences.gstreamer,
repetitiveConditionsWin,
+ currentEventExecute.RunPTL
+ );
}
break;
case EventType.Types.REACTIONTIME:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]