Display batch end time estimate according to a sample batch, ver. 2.32.2022

This commit is contained in:
Milan Hanajik 2023-02-27 12:28:21 +01:00
parent 4b42b5ba7a
commit aaa78d60db
10 changed files with 130 additions and 24 deletions

View File

@ -39,6 +39,7 @@ namespace Results.Entities
public virtual int Counter10 { get; set; } public virtual int Counter10 { get; set; }
public virtual DateTime StartTime { get; set; } public virtual DateTime StartTime { get; set; }
public virtual DateTime EndTime { get; set; } public virtual DateTime EndTime { get; set; }
public virtual DateTime SaveTime { get; set; }
public virtual bool Dirty { get; set; } public virtual bool Dirty { get; set; }
public virtual bool RsltsSent { get; set; } public virtual bool RsltsSent { get; set; }
public virtual bool RsltsPrinted { get; set; } public virtual bool RsltsPrinted { get; set; }
@ -157,6 +158,7 @@ namespace Results.Entities
Counter10 = oriBatch.Counter10; Counter10 = oriBatch.Counter10;
StartTime = oriBatch.StartTime; StartTime = oriBatch.StartTime;
EndTime = oriBatch.EndTime; EndTime = oriBatch.EndTime;
SaveTime = oriBatch.SaveTime;
Dirty = oriBatch.Dirty; Dirty = oriBatch.Dirty;
RsltsSent = oriBatch.RsltsSent; RsltsSent = oriBatch.RsltsSent;
RsltsPrinted = oriBatch.RsltsPrinted; RsltsPrinted = oriBatch.RsltsPrinted;
@ -321,16 +323,19 @@ namespace Results.Entities
public override string ToString() public override string ToString()
{ {
return string.Format("Batch #{0}, Start:{1}, End:{2}, Procedure:{3}", BatchNr, StartTime, EndTime, ProcedureName); return string.Format("Batch {0} ({1}s) Start {2}, End {3}, Proc={4}",
BatchNr, (EndTime - StartTime).TotalSeconds, StartTime, EndTime, ProcedureName);
} }
public virtual string ToString(int i) public virtual string ToString(int i)
{ {
return string.Format("Batch: BatchNr={0} ProgramVersion={1} TestBenchId={2} UserName={3} UserNumber={4} ProcedureName={5}{6} ProcRev={7} ProtocolTitle={8} Remark={9} RealDensity={10} AtTemperature={11} Buoyancy={12} StartTime={13} EndTime={14} Dirty={15} RsltsSent={16} RsltsPrinted={17}", return string.Format("Batch {0} ({1}s) ver={2} TestBenchId={3} User={4}/{5} Proc={6}{7} Rev={8} Remark={9} RealDensity={10} AtTemperature={11} Buoyancy={12} StartTime={13} EndTime={14} SaveTime={15} RsltsSent={16} RsltsPrinted={17}",
BatchNr, ProgramVersion, TestBenchId, UserName, UserNumber, BatchNr,
(EndTime - StartTime).TotalSeconds,
ProgramVersion, TestBenchId, UserName, UserNumber,
ProcedureName, (IsRemoteProcedure ? "(R)" : ""), ProcedureRevision, ProcedureName, (IsRemoteProcedure ? "(R)" : ""), ProcedureRevision,
ProtocolTitle, Remark, RealDensity, AtTemperature, Buoyancy, Remark, RealDensity, AtTemperature, Buoyancy,
StartTime, EndTime, Dirty, RsltsSent, RsltsPrinted); StartTime, EndTime, SaveTime, RsltsSent, RsltsPrinted);
} }
public virtual void WriteBinary(BinaryWriter writer) public virtual void WriteBinary(BinaryWriter writer)
@ -364,6 +369,7 @@ namespace Results.Entities
writer.Write(Counter10); writer.Write(Counter10);
writer.Write(StartTime.ToString()); writer.Write(StartTime.ToString());
writer.Write(EndTime.ToString()); writer.Write(EndTime.ToString());
writer.Write(SaveTime.ToString());
writer.Write(Dirty); writer.Write(Dirty);
writer.Write(RsltsSent); writer.Write(RsltsSent);
writer.Write(RsltsPrinted); writer.Write(RsltsPrinted);
@ -431,6 +437,7 @@ namespace Results.Entities
Counter10 = reader.ReadInt32(); Counter10 = reader.ReadInt32();
StartTime = DateTime.Parse(reader.ReadString()); StartTime = DateTime.Parse(reader.ReadString());
EndTime = DateTime.Parse(reader.ReadString()); EndTime = DateTime.Parse(reader.ReadString());
SaveTime = DateTime.Parse(reader.ReadString());
Dirty = reader.ReadBoolean(); Dirty = reader.ReadBoolean();
RsltsSent = reader.ReadBoolean(); RsltsSent = reader.ReadBoolean();
RsltsPrinted = reader.ReadBoolean(); RsltsPrinted = reader.ReadBoolean();

View File

@ -148,6 +148,7 @@ namespace Results.Entities
/// Wrappers /// Wrappers
public virtual string Name() { return Common.Utils.GetTestName(TestData.Name, TestData.Repeats, RepetitionNr); } public virtual string Name() { return Common.Utils.GetTestName(TestData.Name, TestData.Repeats, RepetitionNr); }
public virtual string Key() { return string.Format("{0}~{1}~{2}~{3}", TestData.Name, Part, TestData.Repeats, RepetitionNr); } /// Unique key
public virtual int Repeats() { return TestData.Repeats; } public virtual int Repeats() { return TestData.Repeats; }
public virtual double Qfrom() { return TestData.Qfrom; } public virtual double Qfrom() { return TestData.Qfrom; }
public virtual double Qto() { return TestData.Qto; } public virtual double Qto() { return TestData.Qto; }

View File

@ -35,6 +35,7 @@ namespace Results.Mappings
Map(x => x.StartTime); Map(x => x.StartTime);
Map(x => x.EndTime); Map(x => x.EndTime);
Map(x => x.SaveTime);
Map(x => x.Dirty); Map(x => x.Dirty);
Map(x => x.RsltsSent); Map(x => x.RsltsSent);
Map(x => x.RsltsPrinted); Map(x => x.RsltsPrinted);

View File

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("2.31.2018.0")] [assembly: AssemblyVersion("2.32.2022.0")]
[assembly: AssemblyFileVersion("2.31.2018.0")] [assembly: AssemblyFileVersion("2.32.2022.0")]

View File

@ -673,10 +673,10 @@
<value>Tiskárna</value> <value>Tiskárna</value>
</data> </data>
<data name="Procedure" xml:space="preserve"> <data name="Procedure" xml:space="preserve">
<value>Postup</value> <value>Prodedura</value>
</data> </data>
<data name="Procedures" xml:space="preserve"> <data name="Procedures" xml:space="preserve">
<value>Postupy</value> <value>Procedury</value>
</data> </data>
<data name="Producer" xml:space="preserve"> <data name="Producer" xml:space="preserve">
<value>Výrobce</value> <value>Výrobce</value>
@ -688,7 +688,7 @@
<value>Restart programu vyžaduje použít některá nastavení</value> <value>Restart programu vyžaduje použít některá nastavení</value>
</data> </data>
<data name="Progress" xml:space="preserve"> <data name="Progress" xml:space="preserve">
<value>V činnosti</value> <value>Postup</value>
</data> </data>
<data name="Properties" xml:space="preserve"> <data name="Properties" xml:space="preserve">
<value>Vlastnosti</value> <value>Vlastnosti</value>

View File

@ -440,6 +440,7 @@ namespace TBF.Rig.Sequences
{ {
/// Clear session data in case this is not an interrupted/restored session /// Clear session data in case this is not an interrupted/restored session
ClearSessionData(); ClearSessionData();
SampleRemainingTimeSec.Clear();
} }
@ -504,6 +505,60 @@ namespace TBF.Rig.Sequences
{ {
/// This is a regular session => initialize BatchRslts /// This is a regular session => initialize BatchRslts
BatchRslts = CreateNewBatchResults(newBatchNr, StateMachine.Procedure); BatchRslts = CreateNewBatchResults(newBatchNr, StateMachine.Procedure);
Batch b = BatchRslts.Batch;
b.EndTime = DateTime.MinValue; /// Disable the batch end time estimate
Batch sampleBatch = null;
using (ISession rsltsDB = Results.DB.CreateSession())
{
var bts = rsltsDB.QueryOver<Batch>()
.OrderBy(x => x.BatchNr).Desc
.Where(x => x.ProcedureName == StateMachine.Procedure.Name)
//.And(x => x.ProcedureRevision == StateMachine.Procedure.Revision)
.List();
///
/// Take the median batch of the last 7, 5, 3 or 1 batches
///
if (bts.Count >= 7)
{
var batches7 = new List<Batch>() { bts[0], bts[1], bts[2], bts[3], bts[4], bts[5], bts[6] };
sampleBatch = batches7.OrderBy(x => (x.EndTime - x.StartTime)).Skip(3).Take(1).Single();
}
else if (bts.Count >= 5)
{
var batches5 = new List<Batch>() { bts[0], bts[1], bts[2], bts[3], bts[4] };
sampleBatch = batches5.OrderBy(x => (x.EndTime - x.StartTime)).Skip(2).Take(1).Single();
}
else if (bts.Count >= 3)
{
var batches3 = new List<Batch>() { bts[0], bts[1], bts[2] };
sampleBatch = batches3.OrderBy(x => (x.EndTime - x.StartTime)).Skip(1).Take(1).Single();
}
else if (bts.Count >= 1)
{
sampleBatch = bts[0];
}
if (sampleBatch != null)
{
/// Update the batch end time estimate according to a sample batch
b.EndTime = b.StartTime + (sampleBatch.EndTime - sampleBatch.StartTime);
/// Prepare the dictionary of remaining times for each completed test according to the sample batch
SampleRemainingTimeSec.Clear();
foreach (TestRslt tr in sampleBatch.TestRslts)
{
if (TBF.Utils.IsHydroTest(tr.TestData.Method))
{
string key = tr.Key();
if (!SampleRemainingTimeSec.ContainsKey(key))
{
SampleRemainingTimeSec.Add(key, sampleBatch.EndTime - tr.EndTime);
}
}
}
}
}
} }
@ -895,14 +950,10 @@ namespace TBF.Rig.Sequences
for (int i = currentTestIx + 1; i < StateMachine.TestInstances.Length - simultWithEvacuationCount; i++) for (int i = currentTestIx + 1; i < StateMachine.TestInstances.Length - simultWithEvacuationCount; i++)
{ {
Test tst = StateMachine.TestInstances[i].Test; Test tst = StateMachine.TestInstances[i].Test;
if (tst != null) if (tst != null && TBF.Utils.IsHydroTest(tst.Method))
{ {
ITestMethod tm = TbfComponents.FindComponent(tst.Method) as ITestMethod;
if (tm != null && tm.DoTransitions())
{
nextHydroTest = tst; nextHydroTest = tst;
break; break;
}
} }
} }
@ -991,7 +1042,6 @@ namespace TBF.Rig.Sequences
Bridge.OnTestProgress(this, new TestProgressEventArgs(testInst.Test, testInst.Repetition, Progress.JustStarted)); Bridge.OnTestProgress(this, new TestProgressEventArgs(testInst.Test, testInst.Repetition, Progress.JustStarted));
bool currentTestFinished = true; bool currentTestFinished = true;
bool doOneMoreRepetition = false;
bool doExecuteTransitionBefore = (currentTestIx == simultWithPurgingCount) || (testInst.Test != StateMachine.TestInstances[currentTestIx - 1].Test) || veryFirstTestInTheRestOfCycle; bool doExecuteTransitionBefore = (currentTestIx == simultWithPurgingCount) || (testInst.Test != StateMachine.TestInstances[currentTestIx - 1].Test) || veryFirstTestInTheRestOfCycle;
bool isLastRepetition = (currentTestIx == StateMachine.TestInstances.Length - simultWithEvacuationCount - 1) || (testInst.Test != StateMachine.TestInstances[currentTestIx + 1].Test); bool isLastRepetition = (currentTestIx == StateMachine.TestInstances.Length - simultWithEvacuationCount - 1) || (testInst.Test != StateMachine.TestInstances[currentTestIx + 1].Test);
@ -1261,7 +1311,18 @@ namespace TBF.Rig.Sequences
/// ///
/// Update batch results, determine whether watermeters passed all required tests /// Update batch results, determine whether watermeters passed all required tests
/// ///
BatchRslts.Batch.EndTime = DateTime.Now; /// Set cycle end time
/// Determine the end of the last test and save it as the batch end time
DateTime lastTestEndTime = DateTime.MinValue;
if (BatchRslts.Batch.TestRslts != null)
{
foreach (var tr in BatchRslts.Batch.TestRslts)
{
if (tr.EndTime > lastTestEndTime) lastTestEndTime = tr.EndTime;
}
}
BatchRslts.Batch.EndTime = lastTestEndTime;
Results.Utils.GetCounterStates(BatchRslts.Batch, Program.LocalSettings.Counters); /// Update counters Results.Utils.GetCounterStates(BatchRslts.Batch, Program.LocalSettings.Counters); /// Update counters
/// Remove results of internal tests /// Remove results of internal tests
for (int i = BatchRslts.Batch.TestRslts.Count - 1; i >= 0; i--) for (int i = BatchRslts.Batch.TestRslts.Count - 1; i >= 0; i--)

View File

@ -47,6 +47,7 @@ namespace TBF.Rig.Sequences
// public static TBF.UI.ProcedureInfo SelectedProcedure; // public static TBF.UI.ProcedureInfo SelectedProcedure;
public static Common.IOrderInfo OrderInfo; public static Common.IOrderInfo OrderInfo;
// public static SharedDatabase.WorkflowSummary WorkflowSummary; /// Selected production tracing workflow // public static SharedDatabase.WorkflowSummary WorkflowSummary; /// Selected production tracing workflow
public static IDictionary<string, TimeSpan> SampleRemainingTimeSec = new Dictionary<string, TimeSpan>();
/// ///
/// State variables to be saved after each completed test /// State variables to be saved after each completed test

View File

@ -401,12 +401,38 @@ namespace TBF.UI
void OnTestProgress(object sender, UiBridge.TestProgressEventArgs args) void OnTestProgress(object sender, UiBridge.TestProgressEventArgs args)
{ {
mainProgressBar.Value = (int)(100.499f * args.OveralProgress); if (TBF.Rig.Sequences.ProcessData.BatchRslts != null)
{
var b = TBF.Rig.Sequences.ProcessData.BatchRslts.Batch;
if (b != null && b.EndTime > b.StartTime)
{
progressGroupBox.Text = string.Format("{0} @ {1}", Strings.End, b.EndTime.ToShortTimeString());
}
else
{
progressGroupBox.Text = Strings.Progress;
}
}
else
{
progressGroupBox.Text = Strings.Progress;
}
mainProgressBar.Value = (int)(100.499f * args.OveralProgress);
} }
void OnProcedureSelected(object sender, UiBridge.ProcedureSelectedEventArgs args) void OnProcedureSelected(object sender, UiBridge.ProcedureSelectedEventArgs args)
{ {
mainProgressBar.Value = 0; mainProgressBar.Value = 0;
if (TBF.Rig.Sequences.ProcessData.BatchRslts != null)
{
var b = TBF.Rig.Sequences.ProcessData.BatchRslts.Batch;
if (b != null && b.EndTime > b.StartTime)
{
progressGroupBox.Text = string.Format("{0} @ {1}", Strings.End, b.EndTime.ToShortTimeString());
}
}
} }
/// <summary> /// <summary>
@ -445,6 +471,8 @@ namespace TBF.UI
procedureComboBox.Enabled = ((args.Flags & ButtonsEtc.ProcedureCmbBoxEn) != 0); procedureComboBox.Enabled = ((args.Flags & ButtonsEtc.ProcedureCmbBoxEn) != 0);
optoHeadsToolStripMenuItem.Enabled = ((args.Flags & ButtonsEtc.ProcedureCmbBoxEn) != 0); optoHeadsToolStripMenuItem.Enabled = ((args.Flags & ButtonsEtc.ProcedureCmbBoxEn) != 0);
if (procedureComboBox.Enabled) progressGroupBox.Text = Strings.Progress;
if (procedureComboBox.Enabled && ProceduresUpdated) if (procedureComboBox.Enabled && ProceduresUpdated)
{ {
ReloadProcedureComboBoxItems(); ReloadProcedureComboBoxItems();

View File

@ -135,6 +135,13 @@ namespace TBF.UiBridge
{ {
TBF.Rig.Sequences.ProcessData.SaveProcessData(); TBF.Rig.Sequences.ProcessData.SaveProcessData();
/// Update the estimated batch end time
TimeSpan remainingTime;
if (data.TestRslt != null && TBF.Rig.Sequences.ProcessData.SampleRemainingTimeSec.TryGetValue(data.TestRslt.Key(), out remainingTime))
{
TBF.Rig.Sequences.ProcessData.BatchRslts.Batch.EndTime = DateTime.Now + remainingTime;
}
if (TestCompletedHandler == null) return; if (TestCompletedHandler == null) return;
try { TestCompletedHandler(sender, data); } try { TestCompletedHandler(sender, data); }
catch (Exception e) { log.Error("TestCompletedHandler(...) failed", e); } catch (Exception e) { log.Error("TestCompletedHandler(...) failed", e); }

View File

@ -1,20 +1,20 @@
/// ///
/// Copyright (c) 2013-2016 Sensus Metering Systems /// Copyright (c) 2013-2023 Sensus Slovensko a.s.
/// ///
using System; using System;
using Config.Entities; using Results.Entities;
namespace TBF.UiBridge namespace TBF.UiBridge
{ {
public class TestCompletedEventArgs : EventArgs public class TestCompletedEventArgs : EventArgs
{ {
public string TestName; public string TestName;
public Results.Entities.TestRslt TestRslt; /// If null => just redraw results public TestRslt TestRslt; /// If null => just redraw results
public TestCompletedEventArgs(string testName, Results.Entities.TestRslt testRslt) public TestCompletedEventArgs(string testName, TestRslt testRslt)
{ {
this.TestName = testName; TestName = testName;
this.TestRslt = testRslt; TestRslt = testRslt;
} }
} }
} }