diff --git a/TBF_V2/Docu/Prüfstationsanalyse Hannover Stara Tura.pdf b/TBF_V2/Docu/Prüfstationsanalyse Hannover Stara Tura.pdf
new file mode 100644
index 00000000..b302744c
Binary files /dev/null and b/TBF_V2/Docu/Prüfstationsanalyse Hannover Stara Tura.pdf differ
diff --git a/TBF_V2/Docu/Prüfstationsanalyse Hannover.pdf b/TBF_V2/Docu/Prüfstationsanalyse Hannover.pdf
new file mode 100644
index 00000000..09ef7830
Binary files /dev/null and b/TBF_V2/Docu/Prüfstationsanalyse Hannover.pdf differ
diff --git a/TBF_V2/Docu/Prüfstationsanalyse Stara Tura.pdf b/TBF_V2/Docu/Prüfstationsanalyse Stara Tura.pdf
new file mode 100644
index 00000000..1b324fc3
Binary files /dev/null and b/TBF_V2/Docu/Prüfstationsanalyse Stara Tura.pdf differ
diff --git a/TBF_V2/Docu/Schulung-TBF-P2022.docx b/TBF_V2/Docu/Schulung-TBF-P2022.docx
new file mode 100644
index 00000000..6c291e4d
Binary files /dev/null and b/TBF_V2/Docu/Schulung-TBF-P2022.docx differ
diff --git a/TBF_V2/Docu/SoftwareDesign/TBF_SDDe.docx b/TBF_V2/Docu/SoftwareDesign/TBF_SDDe.docx
new file mode 100644
index 00000000..84ad5bf6
Binary files /dev/null and b/TBF_V2/Docu/SoftwareDesign/TBF_SDDe.docx differ
diff --git a/TBF_V2/Docu/SoftwareDesign/TBF_SDDe.vsd b/TBF_V2/Docu/SoftwareDesign/TBF_SDDe.vsd
new file mode 100644
index 00000000..1eab01ae
Binary files /dev/null and b/TBF_V2/Docu/SoftwareDesign/TBF_SDDe.vsd differ
diff --git a/TBF_V2/Docu/SoftwareDesign/TBF_SRSe.docx b/TBF_V2/Docu/SoftwareDesign/TBF_SRSe.docx
new file mode 100644
index 00000000..ed8c7ef4
Binary files /dev/null and b/TBF_V2/Docu/SoftwareDesign/TBF_SRSe.docx differ
diff --git a/TBF_V2/Sources/TBF/.gitignore b/TBF_V2/Sources/TBF/.gitignore
new file mode 100644
index 00000000..d08e4307
--- /dev/null
+++ b/TBF_V2/Sources/TBF/.gitignore
@@ -0,0 +1,25 @@
+Config/bin/
+Config/obj/
+DeviceTest/bin/
+DeviceTest/obj/
+Dirichlet.Numerics/bin
+Dirichlet.Numerics/obj
+GraphLib/bin
+GraphLib/obj
+MonitoringDB/bin
+MonitoringDB/obj
+Results/bin/
+Results/obj/
+ResultsBrowser/bin/
+ResultsBrowser/obj/
+TBF/bin/
+TBF/obj/
+TBFSetup/Debug/
+TBFSetup/Release/
+Users/bin/
+Users/obj/
+UserManagement/bin/
+UserManagement/obj/
+Doc/
+*.suo
+*.bak
diff --git a/TBF_V2/Sources/TBF/Config/Config.csproj b/TBF_V2/Sources/TBF/Config/Config.csproj
new file mode 100644
index 00000000..68f4d018
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Config.csproj
@@ -0,0 +1,152 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {743DF7DB-C7B6-42EB-986D-0F485E5588E4}
+ Library
+ Properties
+ Config
+ Config
+ v4.0
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;GENESIS;IPERL;LANG_DE
+ prompt
+ 4
+ false
+ x86
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;GENESIS;IPERL;LANG_DE
+ prompt
+ 4
+
+
+
+ ..\..\..\Debug\ControlComponent3U.dll
+
+
+ ..\packages\FluentNHibernate.2.0.3.0\lib\net40\FluentNHibernate.dll
+
+
+ ..\packages\Iesi.Collections.4.0.0.4000\lib\net40\Iesi.Collections.dll
+
+
+ ..\packages\log4net.2.0.2\lib\net40-full\log4net.dll
+
+
+ ..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll
+
+
+ ..\packages\NHibernate.4.0.4.4000\lib\net40\NHibernate.dll
+
+
+
+
+ ..\packages\System.Data.SQLite.1.0.90.0\lib\net40\System.Data.SQLite.dll
+
+
+ ..\packages\System.Data.SQLite.1.0.90.0\lib\net40\System.Data.SQLite.Linq.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Strings.resx
+
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+ {6E5CB0E9-E1B6-4E5D-AC6E-B1049E180F2B}
+ Users
+
+
+
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Data.cs b/TBF_V2/Sources/TBF/Config/Data.cs
new file mode 100644
index 00000000..997d474e
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Data.cs
@@ -0,0 +1,96 @@
+using System;
+
+namespace Config
+{
+ public class Data : Users.GlobalData
+ {
+ public const string AdminUsername = "admin";
+ public const string AdminPassword = "staratura";
+ public const string SQLiteDbFName = "SQLite.db";
+
+#if MUNICH
+ public const int WMsCount = 3;
+ public const int LineSize = 1;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = 3;
+#elif DN100 || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT || CEVAK_200
+ public const int WMsCount = 3;
+ public const int LineSize = 3;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif FUZHOU300 || FUZHOU150 || PT200IL || PUCHONG_PT200 || GENESIS || SLM_150 || PETERSBURG_200
+ public const int WMsCount = 6;
+ public const int LineSize = 6;
+ public const int CompoundWMsCount = 3;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = 3;
+#elif DUBAJ_50
+ public const int WMsCount = 10;
+ public const int LineSize = 5;
+ public const int CompoundWMsCount = 0;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif FUZHOU100
+ public const int WMsCount = 10;
+ public const int LineSize = 10;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif TORINO50 || BADGER_MALA_TRAT || BERLIN
+ public const int WMsCount = 6;
+ public const int LineSize = 6;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = 1;
+#elif TORUN_PT50_2015 || CEVAK_PT40_272 || MURES_PT40 || FUZHOU_40 || PETERSBURG_50 || KEMPNO_50 || BAHRAIN_50 || KRAKOW_50 || JUZNA_AFRIKA_50 || ZAMBIA
+ public const int WMsCount = 20;
+ public const int LineSize = 10;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif RUM_MOB
+ public const int WMsCount = 8;
+ public const int LineSize = 8;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif TURA_IPERL
+ public const int WMsCount = 40;
+ public const int LineSize = 20;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif TURA_SPECIAL || SENTEC
+ public const int WMsCount = 6;
+ public const int LineSize = 6;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif SLM_50
+ public const int WMsCount = 12;
+ public const int LineSize = 12;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 6;
+ public const int MaxPartNr = WMsCount / LineSize;
+#elif SLM_END || WARSAW_END
+ public const int WMsCount = 10;
+ public const int LineSize = 5;
+ public const int CompoundWMsCount = 1;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = 4;
+#elif MALTA_WSD25
+ public const int WMsCount = 6;
+ public const int LineSize = 6;
+ public const int CompoundWMsCount = 0;
+ public const int HeatMetersCount = 0;
+ public const int MaxPartNr = WMsCount / LineSize;
+#endif
+
+ ///
+ /// Database related: This object reference is set after a successful user login
+ ///
+ public static DatabaseSettings CurrentBench;
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/DatabaseSettings.cs b/TBF_V2/Sources/TBF/Config/DatabaseSettings.cs
new file mode 100644
index 00000000..7671d478
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/DatabaseSettings.cs
@@ -0,0 +1,54 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace Config
+{
+ ///
+ /// Test bench database settings, contains bench name and settings od several databases
+ ///
+ public class DatabaseSettings : ICloneable
+ {
+ // Public fields
+ public string BenchName;
+ public bool IsRealBench;
+ public Users.DBSettings ProceduresDBSettings; /// Config database settings
+ public Users.DBSettings WaterMetersDBSettings; /// Results database settings
+ public Users.DBSettings UsersDBSettings; /// Users database settings
+
+ // Constructor
+ public DatabaseSettings()
+ {
+ BenchName = String.Empty; /// Empty string (avoid null)
+ IsRealBench = false;
+ ProceduresDBSettings = new Users.DBSettings(Users.Entities.DBType.MySql, string.Empty);
+ WaterMetersDBSettings = new Users.DBSettings(Users.Entities.DBType.MySql, string.Empty);
+ UsersDBSettings = new Users.DBSettings(Users.Entities.DBType.MySql, string.Empty);
+ }
+
+ public object Clone()
+ {
+ DatabaseSettings result = new DatabaseSettings();
+
+ result.BenchName = BenchName;
+ result.IsRealBench = IsRealBench;
+ result.ProceduresDBSettings = (Users.DBSettings)ProceduresDBSettings.Clone();
+ result.WaterMetersDBSettings = (Users.DBSettings)WaterMetersDBSettings.Clone();
+ result.UsersDBSettings = (Users.DBSettings)ProceduresDBSettings.Clone();
+
+ return result;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0} config={1} results={2} users={3}",
+ BenchName,
+ ProceduresDBSettings.ConnectionString,
+ WaterMetersDBSettings.ConnectionString,
+ UsersDBSettings.ConnectionString);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/BenchPath.cs b/TBF_V2/Sources/TBF/Config/Entities/BenchPath.cs
new file mode 100644
index 00000000..8572a10d
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/BenchPath.cs
@@ -0,0 +1,61 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class BenchPath : IHasName, IHasItemNr, IHasValves
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OriName { get; set; } /// Not mapped to database
+ public virtual float Qfrom { get; set; } /// Water flow in [m3/h]
+ public virtual float Qto { get; set; } /// Water flow in [m3/h]
+ public virtual string TempMtrUp { get; set; }
+ public virtual string TempMtrDown { get; set; }
+ public virtual string PressMtrUp { get; set; }
+ public virtual string PressMtrDown { get; set; }
+ public virtual string PressMtrDelta { get; set; }
+ public virtual string StopBFValve { get; set; }
+
+ /// Valves
+ public virtual string ValvesOpen { get; set; }
+ public virtual string ValvesClose { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public BenchPath()
+ {
+ ValvesOpen = string.Empty;
+ ValvesClose = string.Empty;
+ }
+
+ public BenchPath(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual BenchPath Clone(string name, int itemNr)
+ {
+ BenchPath result = new BenchPath(name, itemNr);
+
+ result.Qfrom = Qfrom;
+ result.Qto = Qto;
+ result.TempMtrUp = TempMtrUp;
+ result.TempMtrDown = TempMtrDown;
+ result.PressMtrUp = PressMtrUp;
+ result.PressMtrDown = PressMtrDown;
+ result.PressMtrDelta = PressMtrDelta;
+ result.StopBFValve = StopBFValve;
+ result.ValvesOpen = ValvesOpen;
+ result.ValvesClose = ValvesClose;
+
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/Component.cs b/TBF_V2/Sources/TBF/Config/Entities/Component.cs
new file mode 100644
index 00000000..800013e3
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/Component.cs
@@ -0,0 +1,136 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+
+namespace Config.Entities
+{
+ public class Component : IHasName, IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string ClassName { get; set; }
+ public virtual string ParentName { get; set; }
+ public virtual DebugMode Mode { get; set; }
+ public virtual LogLevel Logging { get; set; }
+ public virtual string Parameters { get; set; }
+ public virtual IList Corrections { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public Component()
+ {
+ Name = string.Empty;
+ ClassName = string.Empty;
+ Corrections = new List();
+ }
+
+ public static Component CreateFromCfg(string name, string className, string parentName, int itemNr,
+ DebugMode debugLevel, LogLevel logLevel, string parameters)
+ {
+ Component result = new Component();
+ result.ItemNr = itemNr;
+ result.Name = name;
+ result.ClassName = className;
+ result.ParentName = parentName;
+ result.Mode = debugLevel;
+ result.Logging = logLevel;
+ result.Parameters = parameters;
+ return result;
+ }
+
+ // Makes a new copy of this object (not just a reference)
+ public virtual Component Clone()
+ {
+ Component result = new Component();
+ result.ItemNr = ItemNr;
+ result.Name = Name;
+ result.ClassName = ClassName;
+ result.ParentName = ParentName;
+ result.Mode = Mode;
+ result.Logging = Logging;
+ result.Parameters = Parameters;
+ return result;
+ }
+
+ public virtual void Export(StreamWriter output)
+ {
+ output.WriteLine(Name);
+ output.WriteLine(ClassName);
+ output.WriteLine(ParentName);
+ output.WriteLine(Mode.ToString());
+ output.WriteLine(Logging.ToString());
+ output.Write(Parameters);
+
+ output.Close();
+ }
+
+ public static Component Import(StreamReader input)
+ {
+ Component result = new Component();
+
+ result.Name = input.ReadLine();
+ result.ClassName = input.ReadLine();
+ result.ParentName = input.ReadLine();
+
+ string line = input.ReadLine();
+ if (line.Equals(DebugMode.DetectedOff.ToString())) result.Mode = DebugMode.DetectedOff;
+ else if (line.Equals(DebugMode.DetectedOn.ToString())) result.Mode = DebugMode.DetectedOn;
+ else if (line.Equals(DebugMode.Normal.ToString())) result.Mode = DebugMode.Normal;
+ else if (line.Equals(DebugMode.AutoDetect.ToString())) result.Mode = DebugMode.AutoDetect;
+ else if (line.Equals(DebugMode.FailureDuringOperation.ToString())) result.Mode = DebugMode.FailureDuringOperation;
+ else if (line.Equals(DebugMode.Off.ToString())) result.Mode = DebugMode.Off;
+ else if (line.Equals(DebugMode.Record.ToString())) result.Mode = DebugMode.Record;
+ else if (line.Equals(DebugMode.Reply.ToString())) result.Mode = DebugMode.Reply;
+ else if (line.Equals(DebugMode.Simulate.ToString())) result.Mode = DebugMode.Simulate;
+ else if (line.Equals(DebugMode.Inherit.ToString())) result.Mode = DebugMode.Inherit;
+
+ line = input.ReadLine();
+ if (line.Equals(LogLevel.Off.ToString())) result.Logging = LogLevel.Off;
+ else if (line.Equals(LogLevel.Fatal.ToString())) result.Logging = LogLevel.Fatal;
+ else if (line.Equals(LogLevel.Error.ToString())) result.Logging = LogLevel.Error;
+ else if (line.Equals(LogLevel.Warn.ToString())) result.Logging = LogLevel.Warn;
+ else if (line.Equals(LogLevel.Info.ToString())) result.Logging = LogLevel.Info;
+ else if (line.Equals(LogLevel.Debug.ToString())) result.Logging = LogLevel.Debug;
+ else if (line.Equals(LogLevel.All.ToString())) result.Logging = LogLevel.All;
+
+ result.Parameters = string.Empty;
+ line = input.ReadLine();
+ while (line != null)
+ {
+ result.Parameters += line;
+ result.Parameters += Environment.NewLine;
+ line = input.ReadLine();
+ }
+
+ return result;
+ }
+
+ public virtual string ToString(string indent)
+ {
+ string result = string.Empty;
+
+ result += indent + "ItemNr = " + (ItemNr + 1).ToString() + Environment.NewLine;
+ result += indent + "Name = " + Name + Environment.NewLine;
+ result += indent + "ClassName = " + ClassName + Environment.NewLine;
+ if (ParentName != null)
+ {
+ result += indent + "ParentName = " + ParentName + Environment.NewLine;
+ }
+ result += indent + "DebugLevel = " + Mode.ToString() + Environment.NewLine;
+ result += indent + "LogLevel = " + Logging.ToString() + Environment.NewLine;
+ result += indent + "Parameters = " + Parameters + Environment.NewLine;
+
+ return result;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0} ({1})", Name, ClassName);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/ComponentProcedure.cs b/TBF_V2/Sources/TBF/Config/Entities/ComponentProcedure.cs
new file mode 100644
index 00000000..e0b17982
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/ComponentProcedure.cs
@@ -0,0 +1,61 @@
+///
+/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
+///
+using System;
+using System.IO;
+
+namespace Config.Entities
+{
+ public class ComponentProcedure
+ {
+ public virtual int Id { get; protected set; }
+ public virtual string CmpntName { get; set; } /// Component name
+ public virtual string Parameters { get; set; }
+ public virtual Procedure Procedure { get; set; }
+
+ IParamsProvider paramsProvider;
+ ///
+ public virtual IParamsProvider GetParamsProvider() { return paramsProvider; }
+ public virtual void SetParamsProvider(IParamsProvider paramsProvider) { this.paramsProvider = paramsProvider; }
+
+
+ protected ComponentProcedure() { }
+
+ public ComponentProcedure(string name, string parameters, Procedure procedure)
+ {
+ this.CmpntName = name;
+ this.Parameters = parameters;
+ this.Procedure = procedure;
+ }
+
+
+ public virtual ComponentProcedure Clone(Procedure newProcedure)
+ {
+ return new ComponentProcedure(CmpntName, Parameters, newProcedure);
+ }
+
+ public virtual void Export(StreamWriter output)
+ {
+ output.WriteLine(CmpntName);
+ output.WriteLine(Parameters.Replace(Environment.NewLine, "~"));
+ }
+
+ public static ComponentProcedure Import(StreamReader input, Procedure newProcedure)
+ {
+ string firstLine = input.ReadLine();
+
+ if (string.IsNullOrEmpty(firstLine)) return null;
+
+ try
+ {
+ string cmptnName = firstLine;
+ string parameters = input.ReadLine().Replace("~", Environment.NewLine);
+ return new ComponentProcedure(cmptnName, parameters, newProcedure);
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/ComponentTest.cs b/TBF_V2/Sources/TBF/Config/Entities/ComponentTest.cs
new file mode 100644
index 00000000..ab059928
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/ComponentTest.cs
@@ -0,0 +1,61 @@
+///
+/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
+///
+using System;
+using System.IO;
+
+namespace Config.Entities
+{
+ public class ComponentTest
+ {
+ public virtual int Id { get; protected set; }
+ public virtual string CmpntName { get; set; } /// Component name
+ public virtual string Parameters { get; set; }
+ public virtual Test Test { get; set; }
+
+ IParamsProvider paramsProvider;
+ ///
+ public virtual IParamsProvider GetParamsProvider() { return paramsProvider; }
+ public virtual void SetParamsProvider(IParamsProvider paramsProvider) { this.paramsProvider = paramsProvider; }
+
+
+ protected ComponentTest() { }
+
+ public ComponentTest(string name, string parameters, Test test)
+ {
+ this.CmpntName = name;
+ this.Parameters = parameters;
+ this.Test = test;
+ }
+
+
+ public virtual ComponentTest Clone()
+ {
+ return new ComponentTest(CmpntName, Parameters, Test);
+ }
+
+ public virtual void Export(StreamWriter output)
+ {
+ output.WriteLine(CmpntName);
+ output.WriteLine(Parameters.Replace(Environment.NewLine, "~"));
+ }
+
+ public static ComponentTest Import(StreamReader input, Test newTest)
+ {
+ string firstLine = input.ReadLine();
+
+ if (string.IsNullOrEmpty(firstLine)) return null;
+
+ try
+ {
+ string cmptnName = firstLine;
+ string parameters = input.ReadLine().Replace("~", Environment.NewLine);
+ return new ComponentTest(cmptnName, parameters, newTest);
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/Enums.cs b/TBF_V2/Sources/TBF/Config/Entities/Enums.cs
new file mode 100644
index 00000000..0558d7dc
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/Enums.cs
@@ -0,0 +1,493 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Config.Entities
+{
+ ///
+ /// Helper class to assign descriptions to enum values
+ ///
+ public class Description : Attribute
+ {
+ public string Text;
+ public Description(string t)
+ {
+ Text = t;
+ }
+ }
+
+ public static class GetDescription
+ {
+ /// Extension method for enum-s
+ public static string ToDescription(this Enum en)
+ {
+ Type type = en.GetType();
+ MemberInfo[] memInfo = type.GetMember(en.ToString());
+
+ if (memInfo != null && memInfo.Length > 0)
+ {
+ object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);
+ if (attrs != null && attrs.Length > 0)
+ return ((Description)attrs[0]).Text;
+ }
+
+ return en.ToString(); /// Return ToString() value in case there is no description
+ }
+ }
+
+ ///
+ /// Flags returned by each device configuration control Verify(...) function.
+ ///
+ public enum CfgUpdateFlags
+ {
+ None = 0,
+ Error = 0x1, /// Some settings in the user control are invalid and cannot be set
+ Warning = 0x02, /// Some settings in the user control are suspicious, can be set after user confirmation
+ RestartRqrd = 0x04, /// TBF program restart is required to apply all changed parameters
+ AnyChange = 0x08, /// At least one parameter have changed
+ VolatileChange = 0x10,
+ InvokeCfgChange = 0x20, /// Invoke CfgChange handler of the component
+ }
+
+ public enum RemoteDBUse
+ {
+ [Description("Local DB only")] LocalDBOnly,
+ [Description("Remote DB only")] RemoteDBOnly,
+ [Description("Both DB-s, local 1st")] BothDBsLocalFirst,
+ [Description("Both DB-s, remote 1st")] BothDBsRemoteFirst,
+ Count,
+ }
+
+ ///
+ /// Contains a procedure name and a database specification (local/remote).
+ ///
+ public class ProcedureInfo
+ {
+ public readonly string Name;
+ public readonly Users.Entities.DBKind DBKind;
+
+ public ProcedureInfo(string name, Users.Entities.DBKind dbKind)
+ {
+ Name = name;
+ DBKind = dbKind;
+ }
+ }
+
+ public enum ProcedureState
+ {
+ Active,
+ History,
+ Count,
+ }
+
+ /// Kind of meters for the procedure / test
+ public enum MetersKind
+ {
+#if LANG_DE
+ [Description("Wasserzähler")] Single,
+ [Description("Verbundwasserzähler")] Combined,
+ [Description("Wärmezähler")] HeatMeter,
+#elif LANG_CS
+ [Description("Vodoměry")] Single,
+ [Description("Kombinované vodoměry")] Combined,
+ [Description("Měřiče tepla")] HeatMeter,
+#elif LANG_RU
+ [Description("Счетчик")] Single,
+ [Description("Комбинированный счетчик")] Combined,
+ [Description("Счетчик тепла")] HeatMeter,
+#else
+ [Description("Water meters")] Single,
+ [Description("Compound water meters")] Combined,
+ [Description("Heat meters")] HeatMeter,
+#endif
+ }
+
+ public enum CompoundMeterId : byte
+ {
+ Single,
+ CompoundMain,
+ CompoundAux,
+ Compound,
+ HeatMeterVolume,
+ HeatMeterEnergy,
+ SingleOrCompound, /// Only used when querying results
+ }
+
+ public enum Medium
+ {
+ [Description("")] NotSpecified,
+#if LANG_PL
+ [Description("zimna")] ColdWater,
+ [Description("ciepła")] HotWater,
+#elif LANG_IT
+ [Description("freddo")] ColdWater,
+ [Description("caldo")] HotWater,
+#else
+ [Description("cold")] ColdWater,
+ [Description("hot")] HotWater,
+#endif
+ Count
+ }
+
+ public enum Mounting
+ {
+ [Description("")] NotSpecified,
+#if LANG_DE
+ [Description("H")] H, /// horizontal
+ [Description("V")] V, /// vertical
+ [Description("STR")] S, /// standrohre
+ [Description("F")] F, /// fall
+#else
+ [Description("H")] H, /// horizontal
+ [Description("V")] V, /// vertical
+ [Description("S")] S, /// steig
+ [Description("F")] F, /// fall
+#endif
+ Count
+ }
+
+ public enum TemperatureClass
+ {
+ [Description("")] NotSpecified,
+ [Description("T30")] T30,
+ [Description("T50")] T50,
+ [Description("T70")] T70,
+ [Description("T90")] T90,
+ [Description("T130")] T130,
+ [Description("T180")] T180,
+ [Description("T30/70")] T30_70,
+ [Description("T30/90")] T30_90,
+ [Description("T30/130")] T30_130,
+ [Description("T30/180")] T30_180,
+ [Description("30")] t30,
+ [Description("50")] t50,
+ [Description("70")] t70,
+ [Description("90")] t90,
+ [Description("130")] t130,
+ [Description("180")] t180,
+ Count
+ }
+
+ public enum FlowProfileSensitivityClass
+ {
+ [Description("")] NotSpecified,
+ [Description("U0")] U0, /// ?
+ [Description("D0")] D0, /// ?
+ Count
+ }
+
+ public enum PressureLossClass
+ {
+ [Description("")] NotSpecified,
+ [Description("dp63")] dp63, /// 0.063 MPa = 0.63 bar, TODO: Change to "Δp63"
+ [Description("dp40")] dp40, /// 0.040 MPa = 0.40 bar
+ [Description("dp25")] dp25, /// 0.025 MPa = 0.25 bar
+ [Description("dp16")] dp16, /// 0.016 MPa = 0.16 bar
+ [Description("dp10")] dp10, /// 0.010 MPa = 0.10 bar
+ Count
+ }
+
+ /// Maximum Admissible Pressure
+ public enum MaxAdmissiblePressure
+ {
+ [Description("")] NotSpecified,
+ [Description("MAP6")] MAP6,
+ [Description("MAP10")] MAP10,
+ [Description("MAP16")] MAP16,
+ [Description("MAP25")] MAP25,
+ [Description("MAP40")] MAP40,
+ Count
+ }
+
+ /// Register reader type
+ public enum RegisterReaderType
+ {
+ Unknown,
+ Pulses, /// Sick, optical and similar
+ Camera, /// CLP1611
+ DataStream, /// iPerl
+ Manual, /// Entered by human via form (also from camera images)
+ Count
+ }
+
+ /// Transition step is finished when this condition is fulfilled
+ public enum StepCondition
+ {
+ None,
+ Scale1Empty,
+ Scale2Empty,
+ Scale3Empty,
+ AllScalesEmpty,
+ Count
+ }
+
+ public enum Publish : sbyte
+ {
+#if LANG_DE
+ /// german
+ [Description("nie")] Never = 0,
+ [Description("immer")] Always = 1,
+ [Description("Bildschirm")] OnScreen = 2,
+ [Description("intern")] Internal = 3,
+#elif LANG_CS
+ /// czech
+ [Description("nikdy")] Never = 0,
+ [Description("vždy")] Always = 1,
+ [Description("na obrazovku")] OnScreen = 2,
+ [Description("interně")] Internal = 3,
+#elif LANG_SK
+ /// slovak
+ [Description("nikdy")] Never = 0,
+ [Description("vždy")] Always = 1,
+ [Description("na obrazovku")] OnScreen = 2,
+ [Description("interne")] Internal = 3,
+#elif LANG_PL
+ /// polish
+ [Description("nigdy")] Never = 0,
+ [Description("zawsze")] Always = 1,
+ [Description("na ekranie")] OnScreen = 2,
+ [Description("wewnętrznie")] Internal = 3,
+#elif LANG_RU
+ /// russian
+ [Description("никогда")] Never = 0,
+ [Description("всегда")] Always = 1,
+ [Description("толька экран")] OnScreen = 2,
+ [Description("внутренно")] Internal = 3,
+#else
+ /// english
+ [Description("Never")] Never = 0,
+ [Description("Always")] Always = 1,
+ [Description("On screen")] OnScreen = 2,
+ [Description("Internal")] Internal = 3,
+#endif
+ Count
+ }
+
+ public enum MassMethod : byte
+ {
+#if LANG_DE
+ /// nemecky
+ [Description("Waage")] Scale,
+ [Description("Spanne")] Spread,
+ [Description("Standardabw.")] StdDev,
+#elif LANG_CS
+ /// cesky
+ [Description("váhou")] Scale,
+ [Description("max.rozdíl")] Spread,
+ [Description("std.dev.")] StdDev,
+#else
+ [Description("Scale")] Scale,
+ [Description("Spread")] Spread,
+ [Description("Std.dev.")] StdDev,
+#endif
+ Count
+ }
+
+ public enum TestRedType
+ {
+ Fix,
+ /// etc.
+ Count,
+ }
+
+ public enum FQC1
+ {
+ FQC1,
+ FQP1,
+ Count,
+ }
+
+ public enum Progress
+ {
+ JustStarted,
+ TransitionBefore,
+ SwitchingFlowDetection,
+ FlowSetting,
+ Aborted, /// Use as an argument when a test was aborted
+ Test,
+ TransitionAfter,
+ Completed,
+ Count,
+ }
+
+ public enum Device
+ {
+ Screen,
+ Printer,
+ Disk,
+ }
+
+ public enum PageOrientation
+ {
+ Portrait,
+ Landscape,
+ Count,
+ }
+
+ public enum ItemCategory
+ {
+#if LANG_DE
+ [Description("Allgemein")] Other,
+ [Description("Prüfstanddaten")] BenchData,
+ [Description("Prüfstandergebnisse")] BenchResult,
+ [Description("Prüfpunktdaten")] TestData,
+ [Description("Prüfpunktergebnisse")] TestResult,
+ [Description("Wasserzelledaten")] MeterData,
+ [Description("Wasserzelleergebnisse")] MeterResult,
+#else
+ [Description("Other")] Other,
+ [Description("Bench data")] BenchData,
+ [Description("Bench result")] BenchResult,
+ [Description("Test data")] TestData,
+ [Description("Test result")] TestResult,
+ [Description("Meter data")] MeterData,
+ [Description("Meter result")] MeterResult,
+#endif
+ Count,
+ }
+
+ /// Possible modes of operation of components and devices.
+ public enum DebugMode
+ {
+#if LANG_DE
+ [Description("Erkennen-aus")] DetectedOff = -2,
+ [Description("Erkennen-ein")] DetectedOn = -1,
+ [Description("Normal")] Normal = 0, /// Normal operation
+ [Description("Auto-erkennen")] AutoDetect, /// The component (device) will be auto-detected
+ [Description("Fehler")] FailureDuringOperation, /// Failure during operation -> disabled
+ [Description("Aus")] Off, /// The component is off
+ [Description("Aufzeichnen")] Record,
+ [Description("Reply")] Reply,
+ [Description("Simuliert")] Simulate, /// Test bench simulation, this mode does not require any hardware
+ [Description("Geerbt")] Inherit,
+#else
+ [Description("Detected off")] DetectedOff = -2,
+ [Description("Detected on")] DetectedOn = -1,
+ [Description("Normal")] Normal = 0, /// Normal operation
+ [Description("Auto detect")] AutoDetect, /// The component (device) will be auto-detected
+ [Description("Run-time error")] FailureDuringOperation, /// Failure during operation -> disabled
+ [Description("Off")] Off, /// The component is off
+ [Description("Record")] Record,
+ [Description("Reply")] Reply,
+ [Description("Simulate")] Simulate, /// Test bench simulation, this mode does not require any hardware
+ [Description("Inherit")] Inherit,
+#endif
+ Count,
+ }
+
+ public enum LogLevel
+ {
+#if LANG_DE
+ [Description("Aus")] Off,
+ [Description("Schwerwiegend")] Fatal,
+ [Description("Fehler")] Error,
+ [Description("Warnung")] Warn,
+ [Description("Info")] Info,
+ [Description("Debug")] Debug,
+ [Description("Alles")] All,
+#else
+ [Description("Off")] Off,
+ [Description("Fatal")] Fatal,
+ [Description("Error")] Error,
+ [Description("Warn")] Warn,
+ [Description("Info")] Info,
+ [Description("Debug")] Debug,
+ [Description("All")] All,
+#endif
+ Count,
+ }
+
+
+ /// Arrangement of tests
+ public enum TestsArrangement
+ {
+ Rows,
+ Columns,
+ }
+
+ /// Arrangement of meters
+ public enum MetersArrangement
+ {
+ Vertically,
+ Horizontally,
+ }
+
+ public enum Alignment
+ {
+#if LANG_DE
+ [Description("links")] Left,
+ [Description("zentriert")] Center,
+ [Description("rechts")] Right,
+ [Description("angepasst")] Justified,
+#else
+ [Description("Left")] Left,
+ [Description("Center")] Center,
+ [Description("Right")] Right,
+ [Description("Justified")] Justified,
+#endif
+ Count
+ }
+
+ public enum VertAlignment
+ {
+ [Description("Top")] Top,
+ [Description("Middle")] Middle,
+ [Description("Bottom")] Bottom,
+ }
+
+ public enum TableForm
+ {
+ None,
+ Rows,
+ Columns,
+ ColumnsPL,
+ Count,
+ }
+
+ public enum ImageRotation
+ {
+ [Description("0 deg")] None,
+ [Description("90 deg")] Deg90,
+ [Description("180 deg")] Deg180,
+ [Description("270 deg")] Deg270,
+ Count
+ }
+
+ public enum CameraDisplayResolution
+ {
+ Small,
+ Medium,
+ Large,
+ // FullScreen,
+ Count,
+ }
+
+ public enum ErrorFlagsMode : sbyte
+ {
+#if LANG_DE
+ [Description("aus")] Off,
+ [Description("info")] Info,
+ [Description("ein")] On,
+#elif LANG_CS
+ [Description("vypnuto")] Off,
+ [Description("info")] Info,
+ [Description("zapnuto")] On,
+#elif LANG_RU
+ [Description("выкл")] Off,
+ [Description("инфо")] Info,
+ [Description("вкл")] On,
+#elif LANG_PL
+ [Description("nie")] Off,
+ [Description("info")] Info,
+ [Description("tak")] On,
+#else // LANG_EN
+ [Description("off")] Off,
+ [Description("info")] Info,
+ [Description("on")] On,
+#endif
+ Count
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/FeedingPath.cs b/TBF_V2/Sources/TBF/Config/Entities/FeedingPath.cs
new file mode 100644
index 00000000..dac4a6d5
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/FeedingPath.cs
@@ -0,0 +1,53 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class FeedingPath : IHasName, IHasItemNr, IHasValves
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OriName { get; set; } /// Not mapped to database
+ public virtual float Qfrom { get; set; } /// Water flow in [m3/h]
+ public virtual float Qto { get; set; } /// Water flow in [m3/h]
+ public virtual string Pump { get; set; }
+ public virtual string RegulValvesPct { get; set; } /// Positions of regulation valves in % separated by ';'
+
+ /// Valves
+ public virtual string ValvesOpen { get; set; }
+ public virtual string ValvesClose { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public FeedingPath()
+ {
+ ValvesOpen = string.Empty;
+ ValvesClose = string.Empty;
+ }
+
+ public FeedingPath(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual FeedingPath Clone(string name, int itemNr)
+ {
+ FeedingPath result = new FeedingPath(name, itemNr);
+
+ result.Qfrom = Qfrom;
+ result.Qto = Qto;
+ result.Pump = Pump;
+ result.RegulValvesPct = RegulValvesPct;
+ result.ValvesOpen = ValvesOpen;
+ result.ValvesClose = ValvesClose;
+
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/Group.cs b/TBF_V2/Sources/TBF/Config/Entities/Group.cs
new file mode 100644
index 00000000..208840ee
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/Group.cs
@@ -0,0 +1,24 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+
+namespace Config.Entities
+{
+ public class Group
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int Gid { get; set; }
+ public virtual string Name { get; set; }
+
+ public Group()
+ {
+ }
+
+ public Group(int gid, string name)
+ {
+ Gid = gid;
+ Name = name;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/HeatMetersPath.cs b/TBF_V2/Sources/TBF/Config/Entities/HeatMetersPath.cs
new file mode 100644
index 00000000..95e7c006
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/HeatMetersPath.cs
@@ -0,0 +1,65 @@
+///
+/// Copyright (c) 2016-2017 Sensus Metering Systems
+///
+using System;
+
+namespace Config.Entities
+{
+ public class HeatMetersPath : IHasName, IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OriName { get; set; } /// Not mapped to database
+
+ public virtual float TempWarmFrom { get; set; } /// Warm temperature range from [°C]
+ public virtual float TempWarmTo { get; set; } /// Warm temperature range to [°C]
+ public virtual float TempColdFrom { get; set; } /// Cold temperature range from [°C]
+ public virtual float TempColdTo { get; set; } /// Cold temperature renge to [°C]
+
+ public virtual string TMeterRefWarm1 { get; set; }
+ public virtual string TMeterRefWarm2 { get; set; }
+ public virtual string TMeterRefCold1 { get; set; }
+ public virtual string TMeterRefCold2 { get; set; }
+
+ public virtual string TMeterWorkWarm1 { get; set; }
+ public virtual string TMeterWorkWarm2 { get; set; }
+ public virtual string TMeterWorkCold1 { get; set; }
+ public virtual string TMeterWorkCold2 { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public HeatMetersPath()
+ {
+ }
+
+ public HeatMetersPath(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual HeatMetersPath Clone(string name, int itemNr)
+ {
+ HeatMetersPath result = new HeatMetersPath(name, itemNr);
+
+ result.TempWarmFrom = TempWarmFrom;
+ result.TempWarmTo = TempWarmTo;
+ result.TempColdFrom = TempColdFrom;
+ result.TempColdTo = TempColdTo;
+
+ result.TMeterRefWarm1 = TMeterRefWarm1;
+ result.TMeterRefWarm2 = TMeterRefWarm2;
+ result.TMeterRefCold1 = TMeterRefCold1;
+ result.TMeterRefCold2 = TMeterRefCold2;
+
+ result.TMeterWorkWarm1 = TMeterWorkWarm1;
+ result.TMeterWorkWarm2 = TMeterWorkWarm2;
+ result.TMeterWorkCold1 = TMeterWorkCold1;
+ result.TMeterWorkCold2 = TMeterWorkCold2;
+
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/IHasItemNr.cs b/TBF_V2/Sources/TBF/Config/Entities/IHasItemNr.cs
new file mode 100644
index 00000000..504f3f63
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/IHasItemNr.cs
@@ -0,0 +1,11 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+namespace Config.Entities
+{
+ public interface IHasItemNr
+ {
+ int Id { get; }
+ int ItemNr { get; set; }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/IHasName.cs b/TBF_V2/Sources/TBF/Config/Entities/IHasName.cs
new file mode 100644
index 00000000..44bd1137
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/IHasName.cs
@@ -0,0 +1,11 @@
+///
+/// Copyright (c) 2017 Sensus Metering Systems
+///
+namespace Config.Entities
+{
+ public interface IHasName
+ {
+ int Id { get; }
+ string Name { get; set; }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/IHasValves.cs b/TBF_V2/Sources/TBF/Config/Entities/IHasValves.cs
new file mode 100644
index 00000000..d2e7232c
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/IHasValves.cs
@@ -0,0 +1,11 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+namespace Config.Entities
+{
+ public interface IHasValves
+ {
+ string ValvesOpen { get; set; } /// List of valves to be opened
+ string ValvesClose { get; set; } /// List of valves to be closed
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/IParamsProvider.cs b/TBF_V2/Sources/TBF/Config/Entities/IParamsProvider.cs
new file mode 100644
index 00000000..d2bbc541
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/IParamsProvider.cs
@@ -0,0 +1,71 @@
+///
+/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
+///
+using System;
+using System.Collections.Generic;
+using System.Xml.Serialization;
+
+namespace Config.Entities
+{
+ public interface IParamsProvider
+ {
+ ///
+ /// Get XML Serializer
+ ///
+ XmlSerializer GetSerializer();
+
+ string ComponentName { get; }
+
+ ///
+ /// Number of parameters
+ ///
+ int ParamsCount();
+
+ ///
+ /// Returns a parameter name
+ ///
+ /// Zero based index of the parameter
+ string ParamName(int ix);
+
+ ///
+ /// Returns a list of possible values of one parameter (ComboBox when editing) or null (Textbox when editing).
+ ///
+ /// Zero based index of the parameter
+ IList ParamValues(int ix);
+
+ ///
+ /// Returns a parameter value in the string form
+ ///
+ /// Zero based index of the parameter
+ string ToString(int ix);
+
+ ///
+ /// Initialize values of all parameters
+ ///
+ void InitializeAll();
+
+ ///
+ /// Validates the string representation of a parameter
+ ///
+ /// Zero based index of the parameter
+ /// String representation of the parameter
+ /// Warning message in case the string is wrong or null
+ /// true = string is OK, false = string is wrong (see 'message')
+ bool ValidateParam(int ix, string strValue, out string message);
+
+ ///
+ /// Update the parameter from a string
+ ///
+ /// Zero based index of the parameter
+ /// String representation of the parameter
+ CfgUpdateFlags UpdateParam(int ix, string strValue);
+
+ void UpdateEmbeddedDbEntity();
+
+ ///
+ /// Creates an object copy
+ ///
+ ///
+ IParamsProvider Clone();
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/MeasurementCorrection.cs b/TBF_V2/Sources/TBF/Config/Entities/MeasurementCorrection.cs
new file mode 100644
index 00000000..6d3bea7d
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/MeasurementCorrection.cs
@@ -0,0 +1,22 @@
+///
+/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
+///
+using System;
+
+namespace Config.Entities
+{
+ public class MeasurementCorrection
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int RangeIx { get; set; } /// 0..5
+ public virtual float Measurement { get; set; }
+ public virtual float Correction { get; set; }
+
+ public MeasurementCorrection() { }
+
+ public MeasurementCorrection(int rangeIx)
+ {
+ RangeIx = rangeIx;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/MetersPath.cs b/TBF_V2/Sources/TBF/Config/Entities/MetersPath.cs
new file mode 100644
index 00000000..6c105a89
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/MetersPath.cs
@@ -0,0 +1,209 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class MetersPath : IHasName, IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OriName { get; set; } /// Not mapped to database
+
+ /// Sensors
+ public virtual string Sensor1 { get; set; }
+ public virtual string Sensor2 { get; set; }
+ public virtual string Sensor3 { get; set; }
+ public virtual string Sensor4 { get; set; }
+ public virtual string Sensor5 { get; set; }
+ public virtual string Sensor6 { get; set; }
+ public virtual string Sensor7 { get; set; }
+ public virtual string Sensor8 { get; set; }
+ public virtual string Sensor9 { get; set; }
+ public virtual string Sensor10 { get; set; }
+ public virtual string Sensor11 { get; set; }
+ public virtual string Sensor12 { get; set; }
+ public virtual string Sensor13 { get; set; }
+ public virtual string Sensor14 { get; set; }
+ public virtual string Sensor15 { get; set; }
+ public virtual string Sensor16 { get; set; }
+ public virtual string Sensor17 { get; set; }
+ public virtual string Sensor18 { get; set; }
+ public virtual string Sensor19 { get; set; }
+ public virtual string Sensor20 { get; set; }
+ public virtual string Sensor21 { get; set; }
+ public virtual string Sensor22 { get; set; }
+ public virtual string Sensor23 { get; set; }
+ public virtual string Sensor24 { get; set; }
+ public virtual string Sensor25 { get; set; }
+ public virtual string Sensor26 { get; set; }
+ public virtual string Sensor27 { get; set; }
+ public virtual string Sensor28 { get; set; }
+ public virtual string Sensor29 { get; set; }
+ public virtual string Sensor30 { get; set; }
+ public virtual string Sensor31 { get; set; }
+ public virtual string Sensor32 { get; set; }
+ public virtual string Sensor33 { get; set; }
+ public virtual string Sensor34 { get; set; }
+ public virtual string Sensor35 { get; set; }
+ public virtual string Sensor36 { get; set; }
+ public virtual string Sensor37 { get; set; }
+ public virtual string Sensor38 { get; set; }
+ public virtual string Sensor39 { get; set; }
+ public virtual string Sensor40 { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public MetersPath()
+ {
+ }
+
+ public MetersPath(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual MetersPath Clone(string name, int itemNr)
+ {
+ MetersPath result = new MetersPath(name, itemNr);
+ result.Sensor1 = Sensor1;
+ result.Sensor2 = Sensor2;
+ result.Sensor3 = Sensor3;
+ result.Sensor4 = Sensor4;
+ result.Sensor5 = Sensor5;
+ result.Sensor6 = Sensor6;
+ result.Sensor7 = Sensor7;
+ result.Sensor8 = Sensor8;
+ result.Sensor9 = Sensor9;
+ result.Sensor10 = Sensor10;
+ result.Sensor11 = Sensor11;
+ result.Sensor12 = Sensor12;
+ result.Sensor13 = Sensor13;
+ result.Sensor14 = Sensor14;
+ result.Sensor15 = Sensor15;
+ result.Sensor16 = Sensor16;
+ result.Sensor17 = Sensor17;
+ result.Sensor18 = Sensor18;
+ result.Sensor19 = Sensor19;
+ result.Sensor20 = Sensor20;
+ result.Sensor21 = Sensor21;
+ result.Sensor22 = Sensor22;
+ result.Sensor23 = Sensor23;
+ result.Sensor24 = Sensor24;
+ result.Sensor25 = Sensor25;
+ result.Sensor26 = Sensor26;
+ result.Sensor27 = Sensor27;
+ result.Sensor28 = Sensor28;
+ result.Sensor29 = Sensor29;
+ result.Sensor30 = Sensor30;
+ result.Sensor31 = Sensor31;
+ result.Sensor32 = Sensor32;
+ result.Sensor33 = Sensor33;
+ result.Sensor34 = Sensor34;
+ result.Sensor35 = Sensor35;
+ result.Sensor36 = Sensor36;
+ result.Sensor37 = Sensor37;
+ result.Sensor38 = Sensor38;
+ result.Sensor39 = Sensor39;
+ result.Sensor40 = Sensor40;
+
+ return result;
+ }
+
+ /// Returns the component name
+ public virtual string GetSensor(int i)
+ {
+ if (i == 0) return Sensor1;
+ else if (i == 1) return Sensor2;
+ else if (i == 2) return Sensor3;
+ else if (i == 3) return Sensor4;
+ else if (i == 4) return Sensor5;
+ else if (i == 5) return Sensor6;
+ else if (i == 6) return Sensor7;
+ else if (i == 7) return Sensor8;
+ else if (i == 8) return Sensor9;
+ else if (i == 9) return Sensor10;
+ else if (i == 10) return Sensor11;
+ else if (i == 11) return Sensor12;
+ else if (i == 12) return Sensor13;
+ else if (i == 13) return Sensor14;
+ else if (i == 14) return Sensor15;
+ else if (i == 15) return Sensor16;
+ else if (i == 16) return Sensor17;
+ else if (i == 17) return Sensor18;
+ else if (i == 18) return Sensor19;
+ else if (i == 19) return Sensor20;
+ else if (i == 20) return Sensor21;
+ else if (i == 21) return Sensor22;
+ else if (i == 22) return Sensor23;
+ else if (i == 23) return Sensor24;
+ else if (i == 24) return Sensor25;
+ else if (i == 25) return Sensor26;
+ else if (i == 26) return Sensor27;
+ else if (i == 27) return Sensor28;
+ else if (i == 28) return Sensor29;
+ else if (i == 29) return Sensor30;
+ else if (i == 30) return Sensor31;
+ else if (i == 31) return Sensor32;
+ else if (i == 32) return Sensor33;
+ else if (i == 33) return Sensor34;
+ else if (i == 34) return Sensor35;
+ else if (i == 35) return Sensor36;
+ else if (i == 36) return Sensor37;
+ else if (i == 37) return Sensor38;
+ else if (i == 38) return Sensor39;
+ else if (i == 39) return Sensor40;
+ else return null;
+ }
+
+ /// Sets the component name
+ public virtual void SetSensor(int i, string cmpntName)
+ {
+ if (i == 0) Sensor1 = cmpntName;
+ else if (i == 1) Sensor2 = cmpntName;
+ else if (i == 2) Sensor3 = cmpntName;
+ else if (i == 3) Sensor4 = cmpntName;
+ else if (i == 4) Sensor5 = cmpntName;
+ else if (i == 5) Sensor6 = cmpntName;
+ else if (i == 6) Sensor7 = cmpntName;
+ else if (i == 7) Sensor8 = cmpntName;
+ else if (i == 8) Sensor9 = cmpntName;
+ else if (i == 9) Sensor10 = cmpntName;
+ else if (i == 10) Sensor11 = cmpntName;
+ else if (i == 11) Sensor12 = cmpntName;
+ else if (i == 12) Sensor13 = cmpntName;
+ else if (i == 13) Sensor14 = cmpntName;
+ else if (i == 14) Sensor15 = cmpntName;
+ else if (i == 15) Sensor16 = cmpntName;
+ else if (i == 16) Sensor17 = cmpntName;
+ else if (i == 17) Sensor18 = cmpntName;
+ else if (i == 18) Sensor19 = cmpntName;
+ else if (i == 19) Sensor20 = cmpntName;
+ else if (i == 20) Sensor21 = cmpntName;
+ else if (i == 21) Sensor22 = cmpntName;
+ else if (i == 22) Sensor23 = cmpntName;
+ else if (i == 23) Sensor24 = cmpntName;
+ else if (i == 24) Sensor25 = cmpntName;
+ else if (i == 25) Sensor26 = cmpntName;
+ else if (i == 26) Sensor27 = cmpntName;
+ else if (i == 27) Sensor28 = cmpntName;
+ else if (i == 28) Sensor29 = cmpntName;
+ else if (i == 29) Sensor30 = cmpntName;
+ else if (i == 30) Sensor31 = cmpntName;
+ else if (i == 31) Sensor32 = cmpntName;
+ else if (i == 32) Sensor33 = cmpntName;
+ else if (i == 33) Sensor34 = cmpntName;
+ else if (i == 34) Sensor35 = cmpntName;
+ else if (i == 35) Sensor36 = cmpntName;
+ else if (i == 36) Sensor37 = cmpntName;
+ else if (i == 37) Sensor38 = cmpntName;
+ else if (i == 38) Sensor39 = cmpntName;
+ else if (i == 39) Sensor40 = cmpntName;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/OutputPath.cs b/TBF_V2/Sources/TBF/Config/Entities/OutputPath.cs
new file mode 100644
index 00000000..8b375f3b
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/OutputPath.cs
@@ -0,0 +1,66 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class OutputPath : IHasName, IHasItemNr, IHasValves
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OriName { get; set; } /// Not mapped to database
+ public virtual float Qfrom { get; set; } /// Water flow in [m3/h]
+ public virtual float Qto { get; set; } /// Water flow in [m3/h]
+ public virtual string RegulValve { get; set; }
+ public virtual string FlowMeter { get; set; }
+ public virtual float PidCoef { get; set; } /// PID coefficient for the regulation path
+ public virtual string StartValve { get; set; }
+ public virtual string Diverter { get; set; }
+ public virtual string TempDiv { get; set; }
+ public virtual string Scale { get; set; }
+ public virtual string EmptyTankValve { get; set; } /// Not used anywhere
+
+ /// Valves
+ public virtual string ValvesOpen { get; set; }
+ public virtual string ValvesClose { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public OutputPath()
+ {
+ ValvesOpen = string.Empty;
+ ValvesClose = string.Empty;
+ }
+
+ public OutputPath(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual OutputPath Clone(string name, int itemNr)
+ {
+ OutputPath result = new OutputPath(name, itemNr);
+
+ result.Name = Name;
+ result.Qfrom = Qfrom;
+ result.Qto = Qto;
+ result.RegulValve = RegulValve;
+ result.FlowMeter = FlowMeter;
+ result.PidCoef = PidCoef;
+ result.StartValve = StartValve;
+ result.Diverter = Diverter;
+ result.TempDiv = TempDiv;
+ result.Scale = Scale;
+ result.EmptyTankValve = EmptyTankValve;
+ result.ValvesOpen = ValvesOpen;
+ result.ValvesClose = ValvesClose;
+
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/Procedure.cs b/TBF_V2/Sources/TBF/Config/Entities/Procedure.cs
new file mode 100644
index 00000000..64504c10
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/Procedure.cs
@@ -0,0 +1,242 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+
+namespace Config.Entities
+{
+ ///
+ /// Stores one test procedure, supports revisions and history log
+ ///
+ public class Procedure : IHasName, IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+
+ public virtual string Description { get; set; } /// Short description
+ public virtual string CreationUser { get; set; } /// Name of the user who has created or changed this procedure
+ public virtual DateTime CreationTime { get; set; } /// Date and time of the creation or change
+ public virtual string LastChgUser { get; set; } /// Name of the user who has created or changed this procedure
+ public virtual DateTime LastChgTime { get; set; } /// Date and time of the creation or change
+ public virtual string LongDescription { get; set; } /// Long description (notes)
+
+ public virtual ProcedureState ProcedureState { get; set; }
+ public virtual int Revision { get; set; }
+ public virtual int PredecessorId { get; set; }
+ public virtual bool ObtainedByCopy { get; set; } /// Initial version of this procedure was a copy of another procedure
+ ///
+ public virtual MetersKind MetersKind { get; set; } /// single / compound / heat meters
+ public virtual string Watermeters { get; set; } /// Water meter name or Id
+ public virtual bool Protected { get; set; } /// true = procedure cannot be changed by a testing specialist
+ public virtual bool MustBeComplete { get; set; } /// true = procedure can be finished just when all tests were finished
+ public virtual bool ManualCtrlDisabled { get; set; } /// true = manual control of valves, etc. is disabled
+
+ public virtual string DataEntry { get; set; } /// Component to use for data entry
+ public virtual string ResultsPrinter { get; set; } /// Component to use for printing the results
+ public virtual string ResultsWriter { get; set; } /// Component to use for saving the results into the file
+ public virtual string TransitionStart { get; set; }
+ public virtual string TransitionEnd { get; set; }
+
+ public virtual string AltProcName { get; set; } /// Alternative procedure name (null or string.Empty = no alt. procedure)
+ public virtual int AltProcPeriod { get; set; } /// Period of alternative procedures (0 = no alt. procedure)
+
+ public virtual IList MoreParams { get; set; }
+ public virtual IList Tests { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public Procedure()
+ {
+ MoreParams = new List();
+ Tests = new List();
+
+ ///
+ /// Default values
+ ///
+ CreationUser = (Users.GlobalData.CurrentUser != null) ? Users.GlobalData.CurrentUser.UserName : null;
+ CreationTime = DateTime.Now;
+ LastChgUser = CreationUser;
+ LastChgTime = CreationTime;
+ MetersKind = Entities.MetersKind.Single;
+ Watermeters = string.Empty;
+ Description = string.Empty;
+ LongDescription = string.Empty;
+ }
+
+ public Procedure(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual Procedure Clone()
+ {
+ Procedure result = new Procedure();
+
+ result.ItemNr = ItemNr;
+ result.Name = Name;
+ result.Description = Description;
+ result.CreationUser = CreationUser;
+ result.CreationTime = CreationTime;
+ result.LastChgUser = LastChgUser;
+ result.LastChgTime = LastChgTime;
+ result.LongDescription = LongDescription;
+
+ result.ProcedureState = ProcedureState;
+ result.Revision = Revision;
+ result.PredecessorId = Id;
+ result.ObtainedByCopy = ObtainedByCopy;
+
+ result.MetersKind = MetersKind;
+ result.Watermeters = Watermeters;
+ result.Protected = Protected;
+ result.MustBeComplete = MustBeComplete;
+ result.ManualCtrlDisabled = ManualCtrlDisabled;
+ result.DataEntry = DataEntry;
+ result.ResultsPrinter = ResultsPrinter;
+ result.ResultsWriter = ResultsWriter;
+ result.TransitionStart = TransitionStart;
+ result.TransitionEnd = TransitionEnd;
+
+ foreach (var prms in MoreParams) { result.MoreParams.Add(prms.Clone(result)); }
+ foreach (var test in Tests) { result.Tests.Add(test.Clone()); }
+
+ return result;
+ }
+
+ public virtual void Export(StreamWriter output)
+ {
+ output.WriteLine(ItemNr.ToString(CultureInfo.InvariantCulture));
+ output.WriteLine(Name);
+ output.WriteLine(Description);
+ output.WriteLine(CreationUser);
+ output.WriteLine(CreationTime.ToString(CultureInfo.InvariantCulture));
+ output.WriteLine(LastChgUser);
+ output.WriteLine(LastChgTime.ToString(CultureInfo.InvariantCulture));
+ output.WriteLine(MetersKind.ToString());
+ output.WriteLine(Watermeters);
+ output.WriteLine(Protected.ToString());
+ output.WriteLine(MustBeComplete.ToString());
+ output.WriteLine(ManualCtrlDisabled.ToString());
+ output.WriteLine(DataEntry);
+ output.WriteLine(ResultsPrinter);
+ output.WriteLine(ResultsWriter);
+ output.WriteLine(TransitionStart);
+ output.WriteLine(TransitionEnd);
+
+ foreach (var prms in MoreParams) { prms.Export(output); }
+ output.WriteLine();
+
+ foreach (var test in Tests) { test.Export(output); }
+ output.WriteLine();
+
+ output.Close();
+ }
+
+ public static Procedure Import(StreamReader input)
+ {
+ Procedure result = new Procedure();
+
+ result.ItemNr = int.Parse(input.ReadLine(), CultureInfo.InvariantCulture);
+ result.Name = input.ReadLine();
+ result.Description = input.ReadLine();
+ result.CreationUser = input.ReadLine();
+ result.CreationTime = DateTime.Parse(input.ReadLine(), CultureInfo.InvariantCulture);
+ result.LastChgUser = input.ReadLine();
+ result.LastChgTime = DateTime.Parse(input.ReadLine(), CultureInfo.InvariantCulture);
+ string line = input.ReadLine();
+ result.MetersKind = line.Equals(MetersKind.Single.ToString()) ? MetersKind.Single : (line.Equals(MetersKind.Combined.ToString()) ? MetersKind.Combined : MetersKind.HeatMeter);
+ result.Watermeters = input.ReadLine();
+ result.Protected = bool.Parse(input.ReadLine());
+ result.MustBeComplete = bool.Parse(input.ReadLine());
+ result.ManualCtrlDisabled = bool.Parse(input.ReadLine());
+ result.DataEntry = input.ReadLine();
+ result.ResultsPrinter = input.ReadLine();
+ result.ResultsWriter = input.ReadLine();
+ result.TransitionStart = input.ReadLine();
+ result.TransitionEnd = input.ReadLine();
+
+ while(true)
+ {
+ ComponentProcedure prms = ComponentProcedure.Import(input, result);
+ if (prms == null)
+ break;
+ else
+ result.MoreParams.Add(prms);
+ }
+
+ while (true)
+ {
+ Test tst = Test.Import(input, result);
+ if (tst == null)
+ break;
+ else
+ result.Tests.Add(tst);
+ }
+
+ return result;
+ }
+
+ public virtual string Compare(StreamReader inp)
+ {
+ System.Text.StringBuilder diff = new System.Text.StringBuilder();
+ const string fmt = "{0} = {1}\r\n (in the file {2})\r\n";
+ string ln;
+
+ ln = inp.ReadLine(); /// skip ItemNr
+ ln = inp.ReadLine(); if (ln != Name) { diff.AppendFormat(fmt, "Name", Name, ln); };
+ ln = inp.ReadLine(); if (ln != Description) { diff.AppendFormat(fmt, "Description", Description, ln); };
+ ln = inp.ReadLine(); /// skip CreationUser
+ ln = inp.ReadLine(); /// skip CreationTime
+ ln = inp.ReadLine(); /// skip LastChgUser
+ ln = inp.ReadLine(); /// skip LastChgTime
+ ln = inp.ReadLine(); if (ln != MetersKind.ToString()) { diff.AppendFormat(fmt, "MetersKind", MetersKind, ln); };
+ ln = inp.ReadLine(); if (ln != Watermeters) { diff.AppendFormat(fmt, "Watermeters", Watermeters, ln); };
+
+ ln = inp.ReadLine(); if (ln != Protected.ToString()) { diff.AppendFormat(fmt, "Protected", Protected, ln); };
+ ln = inp.ReadLine(); if (ln != MustBeComplete.ToString()) { diff.AppendFormat(fmt, "MustBeComplete", MustBeComplete, ln); };
+ ln = inp.ReadLine(); if (ln != ManualCtrlDisabled.ToString()) { diff.AppendFormat(fmt, "ManualCtrlDisabled", ManualCtrlDisabled, ln); };
+ ln = inp.ReadLine(); if (ln != DataEntry) { diff.AppendFormat(fmt, "DataEntry", DataEntry, ln); };
+ ln = inp.ReadLine(); if (ln != ResultsPrinter) { diff.AppendFormat(fmt, "ResultsPrinter", ResultsPrinter, ln); };
+ ln = inp.ReadLine(); if (ln != ResultsWriter) { diff.AppendFormat(fmt, "ResultsWriter", ResultsWriter, ln); };
+ ln = inp.ReadLine(); if (ln != TransitionStart) { diff.AppendFormat(fmt, "TransitionStart", TransitionStart, ln); };
+ ln = inp.ReadLine(); if (ln != TransitionEnd) { diff.AppendFormat(fmt, "TransitionEnd", TransitionEnd, ln); };
+
+ /// TODO Compare componentprocedure-s
+ while (ComponentProcedure.Import(inp, null) != null)
+ {
+ }
+
+
+ //foreach (var test in Tests)
+ //{
+ // string testDiff = test.Compare(inp);
+ // if (testDiff.Contains(
+ //}
+
+ //bool extraTestsInFile = true;
+ //while (Test.Import(inp, null) != null) { extraTestsInFile = true; }
+
+ return diff.ToString();
+ }
+
+ public virtual ComponentProcedure GetProcedureParamsEntity(string cmpntName)
+ {
+ foreach (var procPrms in MoreParams)
+ {
+ if (procPrms.CmpntName == cmpntName) return procPrms;
+ }
+ return null;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}, rev.{1}", Name, Revision);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/ProcedureHistory.cs b/TBF_V2/Sources/TBF/Config/Entities/ProcedureHistory.cs
new file mode 100644
index 00000000..8c9a98ca
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/ProcedureHistory.cs
@@ -0,0 +1,31 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class ProcedureHistory
+ {
+ public virtual int Id { get; protected set; }
+ public virtual Procedure Current { get; set; }
+ public virtual IList OldProcedures { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public ProcedureHistory()
+ {
+ Current = new Procedure();
+ OldProcedures = new List();
+ }
+
+ public virtual ProcedureHistory Clone()
+ {
+ ProcedureHistory result = new ProcedureHistory();
+ result.Current = Current.Clone();
+ foreach (Procedure p in OldProcedures) result.OldProcedures.Add(p.Clone());
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/Test.cs b/TBF_V2/Sources/TBF/Config/Entities/Test.cs
new file mode 100644
index 00000000..9047f035
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/Test.cs
@@ -0,0 +1,369 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+
+namespace Config.Entities
+{
+ ///
+ /// Test, consisting of one or more repetitions of the test 'SingleTest'.
+ ///
+ public class Test : IHasName, IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual int Part { get; set; } /// Part=0 ... test of all WM-s
+ /// Part>0 ... part of a set of tests with the same Name: subset of WM-s is given by MetersPath
+ public virtual sbyte Publish { get; set; } /// 0=no, 1=in all protocols, 2=on screen, 3=internal
+ public virtual bool DoEvaluate { get; set; }
+ public virtual float Qfrom { get; set; } /// Water flow low limit in [m3/h]
+ public virtual float Qto { get; set; } /// Water flow high limit in [m3/h]
+ public virtual float Volume { get; set; } /// Test volume (target) in [l]
+ public virtual float TstTime { get; set; } /// Test time (estimate) in [s]
+ public virtual string Method { get; set; }
+ public virtual float ErrLimLo { get; set; } /// in [%] (usually < 0) or 1=class1, 2=class2, 3=class3
+ public virtual float ErrLimHi { get; set; } /// in [%] (usually > 0) or -Qn in m3/h
+ public virtual float Uncertainty { get; set; } /// int [%] makes error limits tighter: 0 <= Uncertainty <= abs(ErrLimXx)
+ public virtual int Repeats { get; set; }
+ public virtual bool DoDraining { get; set; }
+ public virtual bool DoZeroing { get; set; }
+ public virtual bool DoControlWaterTemp { get; set; }
+ public virtual float TempLimLo { get; set; } /// Lower limit for the controlled temperature
+ public virtual float TempLimHi { get; set; } /// Upper limit for the controlled temperature
+ public virtual float PumpPower { get; set; } /// Power of the pump in [%] in the range 0 .. 100.0f, use values 0% and 100% for non-FM pumps
+ public virtual int MassRepeats { get; set; } /// Number of mass. measurements at the beginning/end of test, 0 = default (=5)
+ public virtual float MassSpread { get; set; } /// Max spread of mass. measurements at the beginning/end of test, 0 = default
+ public virtual MassMethod MassMethod { get; set; } /// method of mass. measurement at the beginning/end of test: false=slow (precise), true=using immediate mass measurement and evaluation
+ public virtual int TimeBeforeFlow { get; set; } /// Delay time before the start of flow control in [s]
+ public virtual int TimeFlow2Mass { get; set; } /// Delay time from the flow stable to the 1st mass measurement in [s]
+ public virtual int TimePump2StartV { get; set; } /// Delay time from the start of the pump to opening the start valve in [s]
+ public virtual int TimeStop2Mass { get; set; } /// Delay time from the test end (diverted) to the 2nd mass measuremen in [s]
+ public virtual double TolerRed { get; set; } /// = Filter
+ public virtual TestRedType RedType { get; set; }
+ public virtual string FeedingPath { get; set; }
+ public virtual string BenchPath { get; set; }
+ public virtual string OutputPath { get; set; }
+ public virtual string MetersPath { get; set; }
+#if HEAT_METERS
+ public virtual string HeatMetersPath { get; set; }
+#endif
+ public virtual string RelTransBefore { get; set; }
+ public virtual string RelTransBetween { get; set; }
+ public virtual string RelTransAfter { get; set; }
+ public virtual string TransitionAfter { get; set; }
+
+ public virtual IList MoreParams { get; set; }
+
+ public virtual Procedure Procedure { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public Test()
+ {
+ MoreParams = new List();
+
+ ///
+ /// Default values
+ ///
+ Publish = (sbyte)Config.Entities.Publish.Always;
+ DoEvaluate = true;
+ Repeats = 1;
+ DoDraining = false;
+ DoZeroing = false;
+ DoControlWaterTemp = false;
+ TempLimLo = 15.0f;
+ TempLimHi = 25.0f;
+ ErrLimLo = -2.0f; /// [%] lower error limit
+ ErrLimHi = 2.0f; /// [%] upper error limit
+ Uncertainty = 0;
+ PumpPower = 60.0f; /// [%]
+ MassRepeats = 0; /// default
+ MassSpread = 0; /// default
+ MassMethod = MassMethod.Scale; /// default
+ TimeBeforeFlow = 10; /// [s] time before the start of flow control in [s]
+ TimeFlow2Mass = 5; /// [s] time from the flow stable to the 1st mass measurement in [s]
+ TimePump2StartV = 1; /// [s] time from the 1st mass measurement to the test start in [s]
+ TimeStop2Mass = 5; /// [s] between the test end and the final mass measurement
+ TolerRed = 0; /// = Filter parameter
+ RelTransBefore = string.Empty;
+ RelTransBetween = string.Empty;
+ RelTransAfter = string.Empty;
+ TransitionAfter = string.Empty;
+ }
+
+ public Test(string name, int itemNr, Procedure procedure)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ Procedure = procedure;
+ }
+
+ // Makes a new copy of this object (not just a reference)
+ public virtual Test Clone()
+ {
+ Test result = new Test(Name, ItemNr, Procedure);
+
+ result.Part = Part;
+ result.Publish = Publish;
+ result.DoEvaluate = DoEvaluate;
+ result.Qfrom = Qfrom;
+ result.Qto = Qto;
+ result.Volume = Volume;
+ result.TstTime = TstTime;
+ result.Method = Method;
+ result.ErrLimLo = ErrLimLo;
+ result.ErrLimHi = ErrLimHi;
+ result.Uncertainty = Uncertainty;
+ result.Repeats = Repeats;
+ result.DoDraining = DoDraining;
+ result.DoZeroing = DoZeroing;
+ result.DoControlWaterTemp = DoControlWaterTemp;
+ result.TempLimLo = TempLimLo;
+ result.TempLimHi = TempLimHi;
+ result.PumpPower = PumpPower;
+ result.MassRepeats = MassRepeats;
+ result.MassSpread = MassSpread;
+ result.MassMethod = MassMethod;
+ result.TimeBeforeFlow = TimeBeforeFlow;
+ result.TimeFlow2Mass = TimeFlow2Mass;
+ result.TimePump2StartV = TimePump2StartV;
+ result.TimeStop2Mass = TimeStop2Mass;
+ result.TolerRed = TolerRed;
+ result.RedType = RedType;
+ result.FeedingPath = FeedingPath;
+ result.BenchPath = BenchPath;
+ result.OutputPath = OutputPath;
+ result.MetersPath = MetersPath;
+#if HEAT_METERS
+ result.HeatMetersPath = HeatMetersPath;
+#endif
+ result.RelTransBefore = RelTransBefore;
+ result.RelTransBetween = RelTransBetween;
+ result.RelTransAfter = RelTransAfter;
+ result.TransitionAfter = TransitionAfter;
+ foreach (var prms in MoreParams) { result.MoreParams.Add(prms.Clone()); }
+
+ return result;
+ }
+
+ public virtual void Export(StreamWriter output)
+ {
+ CultureInfo ci = CultureInfo.InvariantCulture;
+
+ output.WriteLine(Name);
+ output.WriteLine(Part.ToString(ci));
+ output.WriteLine(Publish.ToString(ci));
+ output.WriteLine(DoEvaluate.ToString());
+ output.WriteLine(Qfrom.ToString(ci));
+ output.WriteLine(Qto.ToString(ci));
+ output.WriteLine(Volume.ToString(ci));
+ output.WriteLine(TstTime.ToString(ci));
+ output.WriteLine(Method);
+ output.WriteLine(ErrLimLo.ToString(ci));
+ output.WriteLine(ErrLimHi.ToString(ci));
+ output.WriteLine(Uncertainty.ToString(ci));
+ output.WriteLine(Repeats.ToString(ci));
+ output.WriteLine(DoDraining.ToString());
+ output.WriteLine(DoZeroing.ToString());
+ output.WriteLine(DoControlWaterTemp.ToString());
+ output.WriteLine(TempLimLo.ToString(ci));
+ output.WriteLine(TempLimHi.ToString(ci));
+ output.WriteLine(PumpPower.ToString(ci));
+ output.WriteLine(MassRepeats.ToString(ci));
+ output.WriteLine(MassSpread.ToString(ci));
+ output.WriteLine(((byte)MassMethod).ToString(ci));
+ output.WriteLine(TimeBeforeFlow.ToString(ci));
+ output.WriteLine(TimeFlow2Mass.ToString(ci));
+ output.WriteLine(TimePump2StartV.ToString(ci));
+ output.WriteLine(TimeStop2Mass.ToString(ci));
+ output.WriteLine(FeedingPath);
+ output.WriteLine(BenchPath);
+ output.WriteLine(OutputPath);
+ output.WriteLine(MetersPath);
+ output.WriteLine(RelTransBefore);
+ output.WriteLine(RelTransBetween);
+ output.WriteLine(RelTransAfter);
+ output.WriteLine(TransitionAfter);
+
+ foreach (var prms in MoreParams) { prms.Export(output); }
+ output.WriteLine();
+ }
+
+ public static Test Import(StreamReader input, Procedure newProcedure)
+ {
+ string firstLine = input.ReadLine();
+ if (string.IsNullOrEmpty(firstLine))
+ {
+ return null;
+ }
+
+ CultureInfo ci = CultureInfo.InvariantCulture;
+ Test tst = new Test();
+
+ tst.Name = firstLine;
+ tst.Part = int.Parse(input.ReadLine(), ci);
+ tst.Publish = sbyte.Parse(input.ReadLine(), ci);
+ tst.DoEvaluate = bool.Parse(input.ReadLine());
+ tst.Qfrom = float.Parse(input.ReadLine(), ci);
+ tst.Qto = float.Parse(input.ReadLine(), ci);
+ tst.Volume = float.Parse(input.ReadLine(), ci);
+ tst.TstTime = float.Parse(input.ReadLine(), ci);
+ tst.Method = input.ReadLine();
+ tst.ErrLimLo = float.Parse(input.ReadLine(), ci);
+ tst.ErrLimHi = float.Parse(input.ReadLine(), ci);
+ tst.Uncertainty = float.Parse(input.ReadLine(), ci);
+ tst.Repeats = int.Parse(input.ReadLine(), ci);
+ tst.DoDraining = bool.Parse(input.ReadLine());
+ tst.DoZeroing = bool.Parse(input.ReadLine());
+ tst.DoControlWaterTemp = bool.Parse(input.ReadLine());
+ tst.TempLimLo = float.Parse(input.ReadLine(), ci);
+ tst.TempLimHi = float.Parse(input.ReadLine(), ci);
+ tst.PumpPower = float.Parse(input.ReadLine(), ci);
+ tst.MassRepeats = int.Parse(input.ReadLine(), ci);
+ tst.MassSpread = float.Parse(input.ReadLine(), ci);
+ tst.MassMethod = (MassMethod)byte.Parse(input.ReadLine(), ci);
+ tst.TimeBeforeFlow = int.Parse(input.ReadLine(), ci);
+ tst.TimeFlow2Mass = int.Parse(input.ReadLine(), ci);
+ tst.TimePump2StartV = int.Parse(input.ReadLine(), ci);
+ tst.TimeStop2Mass = int.Parse(input.ReadLine(), ci);
+ tst.FeedingPath = input.ReadLine();
+ tst.BenchPath = input.ReadLine();
+ tst.OutputPath = input.ReadLine();
+ tst.MetersPath = input.ReadLine();
+ tst.RelTransBefore = input.ReadLine();
+ tst.RelTransBetween = input.ReadLine();
+ tst.RelTransAfter = input.ReadLine();
+ tst.TransitionAfter = input.ReadLine();
+
+ while (true)
+ {
+ ComponentTest prms = ComponentTest.Import(input, tst);
+ if (prms == null)
+ break;
+ else
+ tst.MoreParams.Add(prms);
+ }
+
+ tst.Procedure = newProcedure;
+ return tst;
+ }
+
+ public virtual string Compare(StreamReader inp)
+ {
+ System.Text.StringBuilder diff = new System.Text.StringBuilder();
+ string fmt = string.Format("Test {0} : ", Name) + "{0} = {1}\r\n (in the file {2})\r\n";
+ string ln;
+ CultureInfo ci = CultureInfo.InvariantCulture;
+
+ string firstLine = inp.ReadLine();
+ if (string.IsNullOrEmpty(firstLine)) return string.Format("Test {0} is missing in the file\r\n", Name);
+
+ if (Name != firstLine) { diff.AppendFormat(fmt, "Name", Name, firstLine); };
+ ln = inp.ReadLine(); if (ln != Part.ToString(ci)) { diff.AppendFormat(fmt, "Part", Part.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != Publish.ToString(ci)) { diff.AppendFormat(fmt, "Publish", Publish.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != DoEvaluate.ToString(ci)) { diff.AppendFormat(fmt, "Evaluate", DoEvaluate.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != Qfrom.ToString(ci)) { diff.AppendFormat(fmt, "Qfrom", Qfrom.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != Qto.ToString(ci)) { diff.AppendFormat(fmt, "Qto", Qto.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != Volume.ToString(ci)) { diff.AppendFormat(fmt, "Volume", Volume.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != TstTime.ToString(ci)) { diff.AppendFormat(fmt, "TstTime", TstTime.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != Method) { diff.AppendFormat(fmt, "Method", Method, ln); };
+ ln = inp.ReadLine(); if (ln != ErrLimLo.ToString(ci)) { diff.AppendFormat(fmt, "ErrLimLo", ErrLimLo.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != ErrLimHi.ToString(ci)) { diff.AppendFormat(fmt, "ErrLimHi", ErrLimHi.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != Uncertainty.ToString(ci)) { diff.AppendFormat(fmt, "Uncertainty", Uncertainty.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != Repeats.ToString(ci)) { diff.AppendFormat(fmt, "Repeats", Repeats.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != DoDraining.ToString(ci)) { diff.AppendFormat(fmt, "Draining", DoDraining.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != DoZeroing.ToString(ci)) { diff.AppendFormat(fmt, "Zeroing", DoZeroing.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != DoControlWaterTemp.ToString()) { diff.AppendFormat(fmt, "DoControlWaterTemp", DoControlWaterTemp.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != TempLimLo.ToString(ci)) { diff.AppendFormat(fmt, "TempLimLo", TempLimLo.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != TempLimHi.ToString(ci)) { diff.AppendFormat(fmt, "TempLimHi", TempLimHi.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != PumpPower.ToString(ci)) { diff.AppendFormat(fmt, "PumpPower", PumpPower.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != MassRepeats.ToString(ci)) { diff.AppendFormat(fmt, "MassRepeats", MassRepeats.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != MassSpread.ToString(ci)) { diff.AppendFormat(fmt, "MassSpread", MassSpread.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != ((byte)MassMethod).ToString(ci)) { diff.AppendFormat(fmt, "MassMethod", ((byte)MassMethod).ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != TimeBeforeFlow.ToString(ci)) { diff.AppendFormat(fmt, "TimeBeforeFlow", TimeBeforeFlow.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != TimeFlow2Mass.ToString(ci)) { diff.AppendFormat(fmt, "TimeFlow2Mass", TimeFlow2Mass.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != TimePump2StartV.ToString(ci)) { diff.AppendFormat(fmt, "TimePump2StartV", TimePump2StartV.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != TimeStop2Mass.ToString(ci)) { diff.AppendFormat(fmt, "TimeStop2Mass", TimeStop2Mass.ToString(ci), ln); };
+ ln = inp.ReadLine(); if (ln != FeedingPath) { diff.AppendFormat(fmt, "FeedingPath", FeedingPath, ln); };
+ ln = inp.ReadLine(); if (ln != BenchPath) { diff.AppendFormat(fmt, "BenchPath", BenchPath, ln); };
+ ln = inp.ReadLine(); if (ln != OutputPath) { diff.AppendFormat(fmt, "OutputPath", OutputPath, ln); };
+ ln = inp.ReadLine(); if (ln != MetersPath) { diff.AppendFormat(fmt, "MetersPath", MetersPath, ln); };
+ ln = inp.ReadLine(); if (ln != RelTransBefore) { diff.AppendFormat(fmt, "RelTransBefore", RelTransBefore, ln); };
+ ln = inp.ReadLine(); if (ln != RelTransBetween) { diff.AppendFormat(fmt, "RelTransBetween", RelTransBetween, ln); };
+ ln = inp.ReadLine(); if (ln != RelTransAfter) { diff.AppendFormat(fmt, "RelTransAfter", RelTransAfter, ln); };
+ ln = inp.ReadLine(); if (ln != TransitionAfter) { diff.AppendFormat(fmt, "TransitionAfter", TransitionAfter, ln); };
+
+ return diff.ToString();
+ }
+
+ public virtual ComponentTest GetTestParamsEntity(string cmpntName)
+ {
+ foreach (var tstPrms in MoreParams)
+ {
+ if (tstPrms.CmpntName == cmpntName) return tstPrms;
+ }
+ return null;
+ }
+
+ public virtual float GetErrLimLo(float flow)
+ {
+ if (ErrLimLo <= ErrLimHi)
+ {
+ return ErrLimLo; /// Error limit of a water meter
+ }
+ else
+ {
+ /// Metrological class and nominal flow of a heat meter
+ int metrClass = (int)Math.Round(ErrLimLo);
+ float Qp = Math.Abs(ErrLimHi);
+ float Q = Math.Max(flow, 0.00001f); /// to avoid division by zero
+
+ /// Calculate the error limit of a heat meter
+ switch (metrClass)
+ {
+ default:
+ case 1: return -Math.Min(3.5f, 1.0f + 0.01f * Qp / Q);
+ case 2: return -Math.Min(5.0f, 2.0f + 0.02f * Qp / Q);
+ case 3: return -Math.Min(5.0f, 3.0f + 0.05f * Qp / Q);
+ }
+ }
+ }
+
+ public virtual float GetErrLimHi(float flow)
+ {
+ if (ErrLimLo <= ErrLimHi)
+ {
+ return ErrLimHi; /// Error limit of a water meter
+ }
+ else
+ {
+ /// Metrological class and nominal flow of a heat meter
+ int metrClass = (int)Math.Round(ErrLimLo);
+ float Qp = Math.Abs(ErrLimHi);
+ float Q = Math.Max(flow, 0.00001f); /// to avoid division by zero
+
+ /// Calculate the error limit of a heat meter
+ switch (metrClass)
+ {
+ default:
+ case 1: return +Math.Min(3.5f, 1.0f + 0.01f * Qp / Q);
+ case 2: return +Math.Min(5.0f, 2.0f + 0.02f * Qp / Q);
+ case 3: return +Math.Min(5.0f, 3.0f + 0.05f * Qp / Q);
+ }
+ }
+ }
+
+
+ public override string ToString()
+ {
+ string partStr = (Part > 0) ? string.Format(", part {0}", Part) : string.Empty;
+
+ return string.Format("{0}(P.{1},{2}){3}", Name, ((Publish)Publish).ToString(), DoEvaluate ? "E" : "-", partStr);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/TransitionSequence.cs b/TBF_V2/Sources/TBF/Config/Entities/TransitionSequence.cs
new file mode 100644
index 00000000..d17ef434
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/TransitionSequence.cs
@@ -0,0 +1,41 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ ///
+ /// Stores one transition sequence containing a list of transition steps
+ ///
+ public class TransitionSequence : IHasName, IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OriName { get; set; } /// Not mapped to database
+ public virtual string Description { get; set; } /// Short description
+ public virtual IList TransitionSteps { get; set; }
+
+ public TransitionSequence()
+ {
+ TransitionSteps = new List();
+ }
+
+ public TransitionSequence(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual TransitionSequence Clone()
+ {
+ TransitionSequence result = new TransitionSequence();
+ result.Name = Name;
+ result.Description = Description;
+ foreach (var step in TransitionSteps) { result.TransitionSteps.Add(step.Clone()); }
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/TransitionStep.cs b/TBF_V2/Sources/TBF/Config/Entities/TransitionStep.cs
new file mode 100644
index 00000000..143b525e
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/TransitionStep.cs
@@ -0,0 +1,65 @@
+///
+/// Copyright (c) 2013-2015, 2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class TransitionStep : IHasItemNr, IHasValves
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; } /// Order of the preparation step
+ public virtual int Duration { get; set; } /// Duration in seconds
+ public virtual string Message { get; set; } /// Message
+ public virtual string EndCondition { get; set; } /// Condition when transition step is finished (next to the duration)
+ public virtual string ValvesOpen { get; set; } /// List of valves to be opened
+ public virtual string ValvesClose { get; set; } /// List of valves to be closed
+ public virtual string RegulValvesPct { get; set; } /// Positions of regulation valves in % separated by ';'
+ public virtual string PumpWithFMPcts { get; set; } /// Power of FM controlled pumps in % separated by ';'
+
+ public virtual TransitionSequence TransitionSequence { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public TransitionStep()
+ {
+ Duration = 5; /// sec.
+ EndCondition = "None";
+ }
+
+ public TransitionStep(int itemNr, TransitionSequence sequence)
+ : this()
+ {
+ ItemNr = itemNr;
+ TransitionSequence = sequence;
+ }
+
+ public virtual TransitionStep Clone()
+ {
+ TransitionStep result = new TransitionStep(ItemNr, TransitionSequence);
+ result.Duration = Duration;
+ result.Message = Message;
+ result.EndCondition = EndCondition;
+ result.ValvesOpen = ValvesOpen;
+ result.ValvesClose = ValvesClose;
+ result.RegulValvesPct = RegulValvesPct;
+ result.PumpWithFMPcts = PumpWithFMPcts;
+ return result;
+ }
+
+ public virtual string ToString(string indent)
+ {
+ string result = "";
+ result += indent + "ItemNr = " + ItemNr.ToString() + ", ";
+ result += indent + "Duration = " + Duration.ToString() + ", ";
+ result += indent + "Message = " + Message + ", ";
+ result += indent + "EndCondition = " + EndCondition + ", ";
+ result += indent + "ValvesOpen = " + ValvesOpen + ", ";
+ result += indent + "ValvesClose = " + ValvesClose + ", ";
+ result += indent + "RegulValvesPct = " + RegulValvesPct + ", ";
+ result += indent + "PumpsWithFMPct = " + PumpWithFMPcts + Environment.NewLine;
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/User.cs b/TBF_V2/Sources/TBF/Config/Entities/User.cs
new file mode 100644
index 00000000..f969c950
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/User.cs
@@ -0,0 +1,43 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class User
+ {
+ public virtual int Id { get; protected set; }
+ public virtual string UserName { get; set; } /// = name, alias, abbreviation
+ public virtual string FullName { get; set; } /// = description
+ public virtual int Number { get; set; }
+ public virtual string Password { get; set; }
+ public virtual DateTime LastPwChange { get; set; }
+ public virtual IList Groups { get; set; } //User can be a member of a list of groups
+
+ public User()
+ {
+ Groups = new List();
+ }
+
+ ///
+ /// Adds a group to the user.
+ ///
+ /// Group to be added
+ public virtual void AddGroup(Group group)
+ {
+ Groups.Add(group);
+ }
+
+ ///
+ /// Encrypts and sets users password.
+ ///
+ /// Unencrypted password
+ public virtual void SetPassword(string password)
+ {
+ Password = Users.Entities.User.getHash(password);
+ LastPwChange = DateTime.Now;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/VirtualBenchSequence.cs b/TBF_V2/Sources/TBF/Config/Entities/VirtualBenchSequence.cs
new file mode 100644
index 00000000..151d8c20
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/VirtualBenchSequence.cs
@@ -0,0 +1,39 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class VirtualBenchSequence : IHasName, IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OriName { get; set; } /// Not mapped to database
+ public virtual string Description { get; set; } /// Short description
+ public virtual IList VirtualBenchSteps { get; set; }
+
+ public VirtualBenchSequence()
+ {
+ VirtualBenchSteps = new List();
+ }
+
+ public VirtualBenchSequence(string name, int itemNr)
+ : this()
+ {
+ Name = name;
+ ItemNr = itemNr;
+ }
+
+ public virtual VirtualBenchSequence Clone()
+ {
+ VirtualBenchSequence result = new VirtualBenchSequence();
+ result.Name = Name;
+ result.Description = Description;
+ foreach (var step in VirtualBenchSteps) { result.VirtualBenchSteps.Add(step.Clone()); }
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/VirtualBenchStep.cs b/TBF_V2/Sources/TBF/Config/Entities/VirtualBenchStep.cs
new file mode 100644
index 00000000..8e850eda
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/VirtualBenchStep.cs
@@ -0,0 +1,39 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+
+namespace Config.Entities
+{
+ public class VirtualBenchStep : IHasItemNr
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; } /// Order of the preparation step
+ public virtual int Duration { get; set; } /// Duration in seconds
+ ///
+
+ public virtual VirtualBenchSequence VirtualBenchSequence { get; set; }
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public VirtualBenchStep()
+ {
+ Duration = 5; /// sec.
+ }
+
+ public VirtualBenchStep(int itemNr, VirtualBenchSequence sequence)
+ : this()
+ {
+ ItemNr = itemNr;
+ VirtualBenchSequence = sequence;
+ }
+
+ public virtual VirtualBenchStep Clone()
+ {
+ VirtualBenchStep result = new VirtualBenchStep(ItemNr, VirtualBenchSequence);
+
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Entities/WMType.cs b/TBF_V2/Sources/TBF/Config/Entities/WMType.cs
new file mode 100644
index 00000000..ab60d298
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/WMType.cs
@@ -0,0 +1,78 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+/// This class holds the watermeter type specific data
+/// that have all watermaters of the same type in common
+
+namespace Config.Entities
+{
+ public class WMType
+ {
+ // mapped
+ public virtual int Id { get; protected set; } /// primary key
+ public virtual DateTime CreateTime { get; set; } /// Date and time of the creation or change
+ public virtual string CreateUserName { get; set; } /// Name of the user who has created or changed this procedure
+ public virtual string CreateDescription { get; set; } /// Description\
+
+ public virtual string Name { get; set; } /// type name
+ public virtual float PulseRate { get; set; } /// Pulses per Liter
+
+ // not yet mapped
+ public virtual int IdentNr { get; protected set; } /// identification number of watermeter tzpe
+ public virtual int Diameter { get; set; } /// nominal diameter
+ public virtual int Pressure { get; set; } /// nominal pressure
+ public virtual int Length { get; set; } /// construction length
+ public virtual int Temperatur { get; set; } /// nominal temperature in C
+ public virtual float NominalFlow { get; set; } /// nominal flow Qn
+
+ /// ------------- Additional stuff not mapped into the database -------------
+
+ public WMType()
+ {
+ }
+
+ public static WMType DefaultWMType()
+ {
+ WMType procedure = new WMType()
+ {
+ CreateTime = DateTime.Now,
+ CreateUserName = Users.GlobalData.CurrentUser.UserName,
+ CreateDescription = "A default water meter created.",
+ Name = "Watermeter",
+ PulseRate = 1000,
+ };
+ return procedure;
+ }
+
+ public virtual WMType Clone()
+ {
+ WMType result = new WMType();
+
+ result.CreateTime = CreateTime;
+ result.CreateUserName = CreateUserName;
+ result.CreateDescription = CreateDescription;
+ result.Name = Name;
+ result.PulseRate = PulseRate;
+
+ return result;
+ }
+
+ public override string ToString()
+ {
+ string result = "";
+ result += "WMTpe: " + Environment.NewLine;
+ result += " Name = " + Name + Environment.NewLine;
+ result += " Created by = " + CreateUserName + Environment.NewLine;
+ result += " Created on = " + CreateTime.ToString() + Environment.NewLine;
+ result += " Description = " + CreateDescription + Environment.NewLine;
+ result += " Pulse rate = " + PulseRate.ToString() + Environment.NewLine;
+ return result;
+ }
+ }
+}
+
diff --git a/TBF_V2/Sources/TBF/Config/Entities/Watermeter.cs b/TBF_V2/Sources/TBF/Config/Entities/Watermeter.cs
new file mode 100644
index 00000000..ff1f058f
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Entities/Watermeter.cs
@@ -0,0 +1,40 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using NHibernate;
+using FluentNHibernate;
+
+namespace Config.Entities
+{
+ public class Watermeter
+ {
+ public virtual int Id { get; protected set; } /// primary key
+
+ public virtual DateTime CreateTime { get; set; } /// Date and time of the creation or change
+ public virtual string CreateUserName { get; set; } /// Name of the user who has created or changed this procedure
+ public virtual string CreateDescription { get; set; } /// Description
+
+ /// mapped
+ public virtual string Serial { get; set; } /// serial number
+ public virtual WMType WMType { get; set; } /// type of watermeter
+ ///
+
+ ///
+ /// Load a watermeter from the database
+ ///
+ public static Watermeter LoadBySerialnr(string SerialNr)
+ {
+ IList ListOfWatermeters = FluentCommon.CreateSession(Users.Entities.DBKind.Results)
+ .CreateQuery("FROM Watermeter WHERE Serial = :SerialNrParameter")
+ .SetParameter("SerialNrParameter", SerialNr)
+ .List();
+ if (ListOfWatermeters.Count > 0) return ListOfWatermeters.ElementAt(0);
+ return null;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/FluentCommon.cs b/TBF_V2/Sources/TBF/Config/FluentCommon.cs
new file mode 100644
index 00000000..ca8b42f6
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/FluentCommon.cs
@@ -0,0 +1,247 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using System;
+using System.Windows.Forms;
+using FluentNHibernate.Cfg;
+using FluentNHibernate.Cfg.Db;
+using NHibernate;
+using NHibernate.Cfg;
+using NHibernate.Tool.hbm2ddl;
+using Config.Resources;
+
+namespace Config
+{
+ public static class FluentCommon
+ {
+ ///
+ /// Session factories for regular sessions.
+ ///
+ public static ISessionFactory[] SessionFactories = new ISessionFactory[(int)Users.Entities.DBKind.Count];
+
+ ///
+ /// NHibernate session factory (to create the database session 'SessionFactory')
+ ///
+ /// A database session
+ static ISessionFactory CreateSessionFactory(Users.Entities.DBKind database)
+ {
+ Users.Entities.DBType dbType;
+ string connectionString;
+
+ switch (database)
+ {
+ default:
+ case Users.Entities.DBKind.Config:
+ dbType = Data.CurrentBench.ProceduresDBSettings.DbType;
+ connectionString = Data.CurrentBench.ProceduresDBSettings.ConnectionString;
+ break;
+ case Users.Entities.DBKind.Results:
+ dbType = Data.CurrentBench.WaterMetersDBSettings.DbType;
+ connectionString = Data.CurrentBench.WaterMetersDBSettings.ConnectionString;
+ break;
+ case Users.Entities.DBKind.RemoteConfig:
+ dbType = Data.CurrentBench.UsersDBSettings.DbType;
+ connectionString = Data.CurrentBench.UsersDBSettings.ConnectionString;
+ break;
+ }
+
+ return CreateSessionFactory(database, dbType, connectionString, false);
+ }
+
+ ///
+ /// NHibernate session factory (to create the database session 'SessionFactory')
+ ///
+ /// A database session
+ public static ISessionFactory CreateSessionFactory(Users.Entities.DBKind database, Users.Entities.DBType dbType, string connectionString, bool createDB)
+ {
+ try
+ {
+ FluentConfiguration cfg = Fluently.Configure();
+
+ switch (dbType)
+ {
+ default:
+ case Users.Entities.DBType.SQLite:
+ cfg = cfg.Database(SQLiteConfiguration.Standard.UsingFile(connectionString));
+ break;
+ case Users.Entities.DBType.MySql:
+ cfg = cfg.Database(MySQLConfiguration.Standard.ConnectionString(connectionString));
+ break;
+ }
+
+ switch (database)
+ {
+ default:
+ case Users.Entities.DBKind.Config:
+ case Users.Entities.DBKind.RemoteConfig:
+ cfg = cfg.Mappings(m => m.FluentMappings.AddFromAssemblyOf());
+ break;
+ case Users.Entities.DBKind.Results:
+ cfg = cfg.Mappings(m => m.FluentMappings.AddFromAssemblyOf());
+ break;
+ }
+
+ if (createDB)
+ {
+ return cfg.ExposeConfiguration(BuildSchemaCreate).BuildSessionFactory();
+ }
+ else
+ {
+ return cfg.ExposeConfiguration(BuildSchema).BuildSessionFactory();
+ }
+ }
+ catch (Exception exc)
+ {
+ MessageBox.Show(string.Format(Strings.Cannot_open_DB_Cause_0, exc.Message),
+ Strings.Error,
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ return null;
+ }
+ }
+
+ public delegate void BuildSchemaDlgt(Configuration config);
+
+ static void BuildSchema(Configuration config)
+ {
+ /// This NHibernate tool takes a configuration (with mapping info in)
+ /// and exports a database schema from it
+ new SchemaExport(config).SetOutputFile("db_schema");
+ }
+
+ static void BuildSchemaCreate(Configuration config)
+ {
+ /// This NHibernate tool takes a configuration (with mapping info in)
+ /// and exports a database schema from it
+ new SchemaExport(config).Create(true, true);
+ }
+
+ /// Create a NHibernate session for the given database
+ public static ISession CreateSession(Users.Entities.DBKind database)
+ {
+ int ix = (int)database;
+ if (ix < 0 || ix >= (int)Users.Entities.DBKind.Count) return null;
+
+ if (SessionFactories[ix] == null) SessionFactories[ix] = CreateSessionFactory(database);
+
+ return SessionFactories[ix].OpenSession();
+ }
+
+ public static void SaveToDb(Users.Entities.DBKind database, object obj)
+ {
+ SaveToDb(CreateSession(database), obj);
+ }
+
+ public static void SaveToDb(ISession session, object obj)
+ {
+ using (var transaction = session.BeginTransaction())
+ {
+ try
+ {
+ session.SaveOrUpdate(obj);
+ transaction.Commit();
+ }
+ catch
+ {
+ transaction.Rollback();
+ }
+ }
+ }
+
+ public static void DeleteFromDb(Users.Entities.DBKind database, object obj)
+ {
+ DeleteFromDb(CreateSession(database), obj);
+ }
+
+ public static void DeleteFromDb(ISession session, object obj)
+ {
+ using (var transaction = session.BeginTransaction())
+ {
+ session.Delete(obj);
+ transaction.Commit();
+ }
+ }
+
+ ///
+ /// Create an empty users database.
+ /// Database contains only the user 'admin' and the control board component 'CB'.
+ ///
+ /// DBType.SQLite or DBType.MySql
+ /// Connection string
+ /// true=success, false=error
+ public static bool CreateEmptyConfigDB(Users.Entities.DBType dbType, string connectionString)
+ {
+ ISessionFactory sessionFactory = CreateSessionFactory(Users.Entities.DBKind.Config, dbType, connectionString, true);
+ if (sessionFactory == null) return false;
+
+ /// Populate the database
+ using (var session = sessionFactory.OpenSession())
+ {
+ using (var transaction = session.BeginTransaction())
+ {
+ ///
+ /// Prepare all groups
+ ///
+ var testers = new Config.Entities.Group((int)Users.Grp.GID.Testers, Strings.Tester);
+ var testingSpecialists = new Config.Entities.Group((int)Users.Grp.GID.TestingSpecialists, Strings.Testing_Specialist);
+ var headOfLab = new Config.Entities.Group((int)Users.Grp.GID.HeadOfLab, Strings.Head_of_Lab);
+ var maintenanceSpecialists = new Config.Entities.Group((int)Users.Grp.GID.MaintenanceSpecialists, Strings.Maintenance_Specialist);
+ var metrologists = new Config.Entities.Group((int)Users.Grp.GID.Metrologists, Strings.Metrologist);
+ var calibrationSpecialists = new Config.Entities.Group((int)Users.Grp.GID.CalibrationSpecialists, Strings.Calibration_Specialist);
+ var administrators = new Config.Entities.Group((int)Users.Grp.GID.Administrators, Strings.Administrator);
+
+ /// Create the user 'admin' add his groups
+ var admin = new Config.Entities.User
+ {
+ UserName = Data.AdminUsername,
+ FullName = Strings.Administrator,
+ LastPwChange = DateTime.Now
+ };
+ admin.SetPassword(Data.AdminPassword);
+ admin.AddGroup(testers);
+ admin.AddGroup(testingSpecialists);
+ admin.AddGroup(headOfLab);
+ admin.AddGroup(maintenanceSpecialists);
+ admin.AddGroup(metrologists);
+ admin.AddGroup(calibrationSpecialists);
+ admin.AddGroup(administrators);
+
+ session.SaveOrUpdate(admin);
+
+ ///// Create the control board component
+ //var cmpnt = (new BenchControl.Elde.ControlBoardCfg(new BenchControl.Elde.ControlBoardFactory())).CreateDbEntity();
+ //session.SaveOrUpdate(cmpnt);
+
+ transaction.Commit();
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Create an empty water meters database
+ ///
+ /// DBType.SQLite or DBType.MySql
+ /// Connection string
+ /// true=success, false=error
+ public static bool CreateEmptyResultsDB(Users.Entities.DBType dbType, string connectionString)
+ {
+ ISessionFactory sessionFactory = CreateSessionFactory(Users.Entities.DBKind.Results, dbType, connectionString, true);
+ if (sessionFactory == null) return false;
+
+ /// Populate the database
+ //using (var session = sessionFactory.OpenSession())
+ //{
+ // using (var transaction = session.BeginTransaction())
+ // {
+ // /// Create one component
+ // var cmpnt = (new BenchControl.Elde.ControlBoardCfg("CB", 1)).CreateDbEntity();
+ // session.SaveOrUpdate(cmpnt);
+ // transaction.Commit();
+ // }
+ //}
+ return true;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Formulas.cs b/TBF_V2/Sources/TBF/Config/Formulas.cs
new file mode 100644
index 00000000..85a5d873
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Formulas.cs
@@ -0,0 +1,399 @@
+///
+/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
+///
+using System;
+using System.Collections.Generic;
+using log4net;
+
+namespace Config
+{
+ public static class Formulas
+ {
+ private static readonly ILog log = LogManager.GetLogger(typeof(Formulas));
+ private static readonly ILog logrefError = LogManager.GetLogger("RefErrorLog");
+ ///
+ /// Tables to calculate specific enthalpy
+ ///
+ private static readonly int[] Ii;
+ private static readonly int[] Ji;
+ private static readonly double[] ni;
+
+ private static readonly double[] Di;
+
+ ///
+ /// Constructor
+ ///
+ static Formulas()
+ {
+ ///
+ /// Initialize tables to calculate specific enthalpies
+ ///
+ Ii = new int[34] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 8, 8, 21, 23, 29, 30, 31, 32 };
+ Ji = new int[34] { -2, -1, 0, 1, 2, 3, 4, 5, -9, -7, -1, 0, 1, 3, -3, 0, 1, 3, 17, -4, 0, 6, -5, -2, 10, -8, -11, -6, -29, -31, -38, -39, -40, -41 };
+ ni = new double[34] {
+ 0.14632971213167, /// 1
+ -0.84548187169114, /// 2
+ -0.37563603672040E1, /// 3
+ 0.33855169168385E1, /// 4
+ -0.95791963387872, /// 5
+ 0.15772038513228, /// 6
+ -0.16616417199501E-1, /// 7
+ 0.81214629983568E-3, /// 8
+ 0.28319080123804E-3, /// 9
+ -0.60706301565874E-3, /// 10
+ -0.18990068218419E-1, /// 11
+ -0.32529748770505E-1, /// 12
+ -0.21841717175414E-1, /// 13
+ -0.52838357969930E-4, /// 14
+ -0.47184321073267E-3, /// 15
+ -0.30001780793026E-3, /// 16
+ 0.47661393906987E-4, /// 17
+ -0.44141845330846E-5, /// 18
+ -0.72694996297594E-15, /// 19
+ -0.31679644845054E-4, /// 20
+ -0.28270797985312E-5, /// 21
+ -0.85205128120103E-9, /// 22
+ -0.22425281908000E-5, /// 23
+ -0.65171222895601E-6, /// 24
+ -0.14341729937924E-12, /// 25
+ -0.40516996860117E-6, /// 26
+ -0.12734301741641E-8, /// 27
+ -0.17424871230634E-9, /// 28
+ -0.68762131295531E-18, /// 29
+ 0.14478307828521E-19, /// 30
+ 0.26335781662795E-22, /// 31
+ -0.11947622640071E-22, /// 32
+ 0.18228094581404E-23, /// 33
+ -0.93537087292458E-25, /// 34
+ };
+
+ ///
+ /// Initialize a table to calculate temperature of a platinum thermometer from resistance
+ ///
+ Di = new double[]
+ {
+ 439.932854,
+ 472.418020,
+ 37.684494,
+ 7.472018,
+ 2.920828,
+ 0.005184,
+ -0.963864,
+ -0.188732,
+ 0.191203,
+ 0.049025,
+ };
+ }
+
+ ///
+ /// Calculate density of distilled water from temperature
+ ///
+ /// ITS-90 temperature in [°C]
+ /// Density in [kg/m3]
+ public static double DistilledWaterDensityFromTemp(double t)
+ {
+ if (t <= 40)
+ {
+ const double c0 = 999.839564;
+ const double c1 = 0.067998613;
+ const double c2 = -0.0091101468;
+ const double c3 = 0.00010058299;
+ const double c4 = -0.0000011275659;
+ const double c5 = 6.5985371e-09;
+
+ return ((((c5 * t + c4) * t + c3) * t + c2) * t + c1) * t + c0;
+ }
+ else
+ {
+ const double a0 = 9.9983952E2;
+ const double a1 = 1.6952577E1;
+ const double a2 = -7.9905127E-3;
+ const double a3 = -4.6241757E-5;
+ const double a4 = 1.0584601E-7;
+ const double a5 = -2.8103006E-10;
+ const double b = 1.6887236E-2;
+
+ return (((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t + a0) / (1.0 + b * t);
+ }
+ }
+
+ ///
+ /// Calculate density of distilled water from temperature (obsolete)
+ ///
+ /// IPTS-68 temperature in [°C]
+ /// Density in [kg/m3]
+ public static double DistilledWaterDensityFromTempIPTS68(double t)
+ {
+ const double a0 = 999.842594;
+ const double a1 = 0.06793952;
+ const double a2 = -0.009095290;
+ const double a3 = 0.0001001685;
+ const double a4 = -0.000001120083;
+ const double a5 = 6.536332e-09;
+
+ return ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t + a0;
+ }
+
+ ///
+ /// Calculate density by comparing calculated data and data from a certificate
+ ///
+ /// Density from a certificate in [kg/m3]
+ /// Temperature from a certificate in [°C]
+ /// Density correction in [kg/m3]
+ public static double DensityCorrection(double realDensity, double atTemperature)
+ {
+ /// Calculated data
+ double calculatedDensity = DistilledWaterDensityFromTemp(atTemperature);
+
+ return realDensity - calculatedDensity;
+ }
+
+ ///
+ /// Calculate corrected (real) water density from temperature
+ ///
+ /// Temperature in [°C]
+ /// Density in [kg/m3]
+ public static double WaterDensityFromTemp(double t, double realDensity, double atTemperature)
+ {
+ return DistilledWaterDensityFromTemp(t) + DensityCorrection(realDensity, atTemperature);
+ }
+
+ ///
+ /// Calculate corrected (real) water density from temperature
+ ///
+ /// Temperature in [°C]
+ /// Density in [kg/m3]
+ public static double WaterDensityFromTempPress(double temp, double pressure, double realDensity, double atTemperature)
+ {
+ double x0 = 5.08821E-10;
+ double x1 = 1.2639418;
+ double x2 = 0.2660269;
+ double x3 = 0.3734838;
+ double x4 = 2.0205242;
+ double theta = temp / 100.0;
+ double B = x0 * (((x3 * theta + x2) * theta + x1) * theta + 1) / (1 + x4 * theta);
+
+ return WaterDensityFromTemp(temp, realDensity, atTemperature) * (1 + B * Config.Units.ConvertTo(Config.Unit.Pa, pressure));
+ }
+
+
+ public static float AirDensityFromAmbientVales(float tempC, float pressureBar, float humiPct)
+ {
+ double pressurePa = 100000.0 * (double)pressureBar; /// [Pa]
+ double tempKelvin = 273.15 + (double)tempC;
+ double coef1 = 1.2811805 / 10000.0 * tempKelvin * tempKelvin
+ - 1.950987 / 100.0 * tempKelvin
+ + 34.04926034
+ - 6.353631 * 1000.0 / tempKelvin;
+ double coef3 = humiPct / 100.0 * System.Math.Exp(coef1) / pressurePa;
+ double airDensityKgm3 = 0.00348353 * pressurePa * (1.0 - 0.378 * coef3) / tempKelvin; /// kg/m3
+ return (float)airDensityKgm3;
+ }
+
+ ///
+ /// Convert 'pulses' to 'volume', prevent division by zero
+ ///
+ public static double VolumeFromPulses(int pulses, double pulsesPerLiter)
+ {
+ if (pulsesPerLiter <= double.Epsilon) return 0;
+ return Convert.ToDouble(pulses) / pulsesPerLiter;
+ }
+
+ ///
+ /// Calculate the error in % from 'measured' and 'true' volume, prevent division by zero
+ ///
+ public static double ErrorFromVolumes(double measuredVolume, double trueVolume)
+ {
+ if (trueVolume <= float.Epsilon)
+ {
+ if (measuredVolume <= float.Epsilon)
+ {
+ log.WarnFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, -100.0);
+ return -100.0;
+ }
+
+ log.WarnFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, 99.0);
+ return 99.0;
+ }
+
+ double error = 100.0 * (measuredVolume - trueVolume) / trueVolume;
+ log.InfoFormat("ErrorFromVolumes({0},{1}) returns {2}", measuredVolume, trueVolume, error);
+ return error;
+ }
+
+ ///
+ /// Calculates corrected value form a list of corrections by interpolation.
+ /// It is assumed that values in the list 'corrections' are sorted.
+ ///
+ /// Raw uncorrected value
+ /// Sorted (value, correction) pairs
+ /// Corrected value
+ public static double CorrectedValue(double rawValue, IList corrections)
+ {
+ logrefError.InfoFormat("call CorrectedValue({0},{1}.Count)", rawValue, corrections.Count);
+ if (corrections == null || corrections.Count == 0)
+ {
+ logrefError.InfoFormat("CorrectedValue({0},{1}.Count) return rawValue... no correction found", rawValue, corrections.Count);
+ return rawValue;
+ }
+
+ if (rawValue < corrections[0].Measurement)
+ {
+ logrefError.InfoFormat("CorrectedValue({0},{1}.Count) return {2}... rawValue < corrections[0].Measurement", rawValue, corrections.Count, rawValue + corrections[0].Correction);
+ return rawValue + corrections[0].Correction;
+ }
+
+ int count = corrections.Count;
+ for (int i = 1; i < count; i++)
+ {
+ if (rawValue < corrections[i].Measurement)
+ {
+ double d1 = rawValue - corrections[i-1].Measurement;
+ double d2 = corrections[i].Measurement - rawValue;
+
+ double corr;
+ if (d1 + d2 <= float.Epsilon)
+ {
+ corr = (corrections[i - 1].Correction + corrections[i].Correction) / 2.0;
+ logrefError.InfoFormat("CorrectedValue({0},{1}.Count) return {2}... (corrections[i - 1].Correction + corrections[i].Correction) / 2.0", rawValue, corrections.Count, rawValue + corr);
+
+ }
+ else
+ {
+ corr = (corrections[i - 1].Correction * d2 + corrections[i].Correction * d1) / (d1 + d2);
+ logrefError.InfoFormat("CorrectedValue({0},{1}.Count) return {2}... (corrections[i - 1].Correction * d2 + corrections[i].Correction * d1) / (d1 + d2)", rawValue, corrections.Count, rawValue + corr);
+ }
+ return rawValue + corr;
+ }
+ }
+ logrefError.InfoFormat("CorrectedValue({0},{1}.Count) return {2}... rawValue < corrections[0].Measurement", rawValue, corrections.Count, rawValue + corrections[count - 1].Correction);
+
+ return rawValue + corrections[count - 1].Correction;
+ }
+
+
+ ///
+ /// Converts a measurement error to a correction (used when preparing correction tables).
+ ///
+ /// Measured value (in arbitrary units)
+ /// Measurement error in %
+ /// Correction in the same units as the measured value
+ public static double CorrectionFromError(double measuredValue, double error)
+ {
+ double trueValue = measuredValue / (1 + error/100);
+ double correction = trueValue - measuredValue;
+ return correction;
+ }
+
+
+ ///
+ /// Calculates the heat coefficient for water
+ ///
+ /// Pressure [bar]
+ /// Inlet temperature [°C]
+ /// Outlet temperature [°C]
+ /// true = flow measured @inlet, false = flow measured @outlet
+ /// Heat coefficient for water [J/(m3 K)]
+ public static double HeatCoefficientWater(double pressure, double T_in, double T_out, bool flowMeasuredAtInlet)
+ {
+ if (T_in == T_out) return 0;
+
+ const double R = 461.526; /// [J kg^-1 K^-1]
+ const double p_star_Pa = 16.53E6; /// [Pa] (=16.53 MPa)
+ const double T_star = 1386.0; /// [K]
+
+ double T_in_K = Config.Units.ConvertTo(Config.Unit.K, T_in);
+ double T_out_K = Config.Units.ConvertTo(Config.Unit.K, T_out);
+ double tau_in = T_star / T_in_K;
+ double tau_out = T_star / T_out_K;
+ double pi = Config.Units.ConvertTo(Config.Unit.Pa, pressure) / p_star_Pa;
+
+ double h_in = tau_in * GammaTau(pi, tau_in) * R * T_in_K;
+ double h_out = tau_out * GammaTau(pi, tau_out) * R * T_out_K;
+
+ double ni = flowMeasuredAtInlet ? GammaPi(pi, tau_in) * R * T_in_K / p_star_Pa
+ : GammaPi(pi, tau_out) * R * T_out_K / p_star_Pa;
+
+ return (h_in - h_out) / (ni * (T_in - T_out));
+ }
+
+ ///
+ /// gamma(pi) see also STN EN 1434-1 Annex A (A.4)
+ ///
+ /// pi = p / p* where p* = 16.53 MPa
+ /// tau = T* / T where T* = 1386 K
+ /// gamma(pi)
+ static double GammaPi(double pi, double tau)
+ {
+ double result = 0;
+ for (int i = 0; i < 34; i++)
+ {
+ result -= ni[i] * Ii[i] * Math.Pow(7.1 - pi, Ii[i] - 1) * Math.Pow(tau - 1.222, Ji[i]);
+ }
+ return result;
+ }
+
+ ///
+ /// gamma(tau) see also STN EN 1434-1 Annex A (A.7)
+ ///
+ /// pi = p / p* where p* = 16.53 MPa
+ /// tau = T* / T where T* = 1386 K
+ /// gamma(tau)
+ static double GammaTau(double pi, double tau)
+ {
+ double result = 0;
+ for (int i = 0; i < 34; i++)
+ {
+ result += ni[i] * Math.Pow(7.1 - pi, Ii[i]) * Ji[i] * Math.Pow(tau - 1.222, Ji[i] - 1);
+ }
+ return result;
+ }
+
+ ///
+ /// Conversion of measured resistance of a platinum thermometer to temperature according to ITS-90
+ ///
+ /// Measured resistance in [°C]
+ /// Calibrated resistance in Ohm at 0.01°C
+ /// Calibrated ITS-90 coefficient a7
+ /// Calibrated ITS-90 coefficient b7
+ /// Calibrated ITS-90 coefficient c7
+ /// Temperature in [°C]
+ public static double PlatinumResistanceTM_ITS90_R2T(double R, double R001C, double a7, double b7, double c7)
+ {
+ double w = R / R001C; /// ratio
+ double r1 = w - 1.0;
+ double dw = r1 * (a7 + r1 * (b7 + r1 * c7)); /// = a7*r1 + b7*r1^2 + c7*r1^3
+ double wr = w - dw;
+ double x = (wr - 2.64) / 1.64;
+
+ double sum = 0;
+ for (int i = Di.Length - 1; i >= 0; i--)
+ {
+ sum = sum * x + Di[i];
+ }
+
+ return sum;
+ }
+
+ ///
+ /// Conversion of measured resistance of a platinum thermometer to temperature using Callendar-Van Dusen equations
+ ///
+ /// Measured resistance in [°C]
+ /// Calibrated resistance in Ohm at 0°C
+ /// Calibration coefficient a
+ /// Calibration coefficient b
+ /// Temperature in [°C]
+ public static double PlatinumResistanceTM_ITS27_R2T(double R, double R0, double A, double B)
+ {
+ if (R0 * R0 * A * A - 4 * R0 * B * (R0 - R) <= 0) return 0; /// Out of range
+
+ return (-(R0 * A) + Math.Sqrt(R0 * R0 * A * A - 4 * R0 * B * (R0 - R))) / (2 * R0 * B);
+ }
+
+
+ public static double Buoyancy()
+ {
+ return 1.00103;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/BenchPathMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/BenchPathMap.cs
new file mode 100644
index 00000000..8865bdd6
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/BenchPathMap.cs
@@ -0,0 +1,32 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class BenchPathMap : ClassMap
+ {
+ public BenchPathMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+ Map(x => x.Qfrom);
+ Map(x => x.Qto);
+ Map(x => x.TempMtrUp).Column("TempIn");
+ Map(x => x.TempMtrDown).Column("TempOut");
+ Map(x => x.PressMtrUp).Column("PressIn");
+ Map(x => x.PressMtrDown).Column("PressOut");
+ Map(x => x.PressMtrDelta);
+ Map(x => x.StopBFValve);
+ Map(x => x.ValvesOpen)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ Map(x => x.ValvesClose)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/ComponentMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/ComponentMap.cs
new file mode 100644
index 00000000..5a7170dc
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/ComponentMap.cs
@@ -0,0 +1,28 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class ComponentMap : ClassMap
+ {
+ public ComponentMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.Name);
+ Map(x => x.ClassName);
+ Map(x => x.ParentName);
+ Map(x => x.ItemNr);
+ Map(x => x.Mode);
+ Map(x => x.Logging);
+ Map(x => x.Parameters)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ HasMany(x => x.Corrections)
+ .OrderBy("Measurement")
+ .Cascade.All();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/ComponentProcedureMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/ComponentProcedureMap.cs
new file mode 100644
index 00000000..107d8a28
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/ComponentProcedureMap.cs
@@ -0,0 +1,22 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class ComponentProcedureMap : ClassMap
+ {
+ public ComponentProcedureMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.CmpntName);
+ Map(x => x.Parameters)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+
+ References(x => x.Procedure);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/ComponentTestMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/ComponentTestMap.cs
new file mode 100644
index 00000000..00c4ab36
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/ComponentTestMap.cs
@@ -0,0 +1,22 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class ComponentTestMap : ClassMap
+ {
+ public ComponentTestMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.CmpntName);
+ Map(x => x.Parameters)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+
+ References(x => x.Test);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/FeedingPathMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/FeedingPathMap.cs
new file mode 100644
index 00000000..41ed03e6
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/FeedingPathMap.cs
@@ -0,0 +1,28 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class FeedingPathMap : ClassMap
+ {
+ public FeedingPathMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+ Map(x => x.Qfrom);
+ Map(x => x.Qto);
+ Map(x => x.Pump);
+ Map(x => x.RegulValvesPct);
+ Map(x => x.ValvesOpen)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ Map(x => x.ValvesClose)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/GroupMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/GroupMap.cs
new file mode 100644
index 00000000..2e0ada87
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/GroupMap.cs
@@ -0,0 +1,17 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+
+namespace Config.Mappings
+{
+ class GroupMap : ClassMap
+ {
+ public GroupMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.Gid);
+ Map(x => x.Name);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/HeatMetersPathMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/HeatMetersPathMap.cs
new file mode 100644
index 00000000..7c03888a
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/HeatMetersPathMap.cs
@@ -0,0 +1,35 @@
+///
+/// Copyright (c) 2016 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+#if HEAT_METERS
+ class HeatMetersPathMap : ClassMap
+ {
+ public HeatMetersPathMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+
+ Map(x => x.TempWarmFrom);
+ Map(x => x.TempWarmTo);
+ Map(x => x.TempColdFrom);
+ Map(x => x.TempColdTo);
+
+ Map(x => x.TMeterRefWarm1);
+ Map(x => x.TMeterRefWarm2);
+ Map(x => x.TMeterRefCold1);
+ Map(x => x.TMeterRefCold2);
+
+ Map(x => x.TMeterWorkWarm1);
+ Map(x => x.TMeterWorkWarm2);
+ Map(x => x.TMeterWorkCold1);
+ Map(x => x.TMeterWorkCold2);
+ }
+ }
+#endif
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/MeasurementCorrectionMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/MeasurementCorrectionMap.cs
new file mode 100644
index 00000000..806efeb5
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/MeasurementCorrectionMap.cs
@@ -0,0 +1,19 @@
+///
+/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class MeasurementCorrectionMap : ClassMap
+ {
+ public MeasurementCorrectionMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.RangeIx);
+ Map(x => x.Measurement);
+ Map(x => x.Correction);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/MetersPathMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/MetersPathMap.cs
new file mode 100644
index 00000000..0e95448e
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/MetersPathMap.cs
@@ -0,0 +1,61 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class MetersPathMap : ClassMap
+ {
+ public MetersPathMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+
+#pragma warning disable
+ if (Config.Data.WMsCount >= 1) Map(x => x.Sensor1);
+ if (Config.Data.WMsCount >= 2) Map(x => x.Sensor2);
+ if (Config.Data.WMsCount >= 3) Map(x => x.Sensor3);
+ if (Config.Data.WMsCount >= 4) Map(x => x.Sensor4);
+ if (Config.Data.WMsCount >= 5) Map(x => x.Sensor5);
+ if (Config.Data.WMsCount >= 6) Map(x => x.Sensor6);
+ if (Config.Data.WMsCount >= 7) Map(x => x.Sensor7);
+ if (Config.Data.WMsCount >= 8) Map(x => x.Sensor8);
+ if (Config.Data.WMsCount >= 9) Map(x => x.Sensor9);
+ if (Config.Data.WMsCount >= 10) Map(x => x.Sensor10);
+ if (Config.Data.WMsCount >= 11) Map(x => x.Sensor11);
+ if (Config.Data.WMsCount >= 12) Map(x => x.Sensor12);
+ if (Config.Data.WMsCount >= 13) Map(x => x.Sensor13);
+ if (Config.Data.WMsCount >= 14) Map(x => x.Sensor14);
+ if (Config.Data.WMsCount >= 15) Map(x => x.Sensor15);
+ if (Config.Data.WMsCount >= 16) Map(x => x.Sensor16);
+ if (Config.Data.WMsCount >= 17) Map(x => x.Sensor17);
+ if (Config.Data.WMsCount >= 18) Map(x => x.Sensor18);
+ if (Config.Data.WMsCount >= 19) Map(x => x.Sensor19);
+ if (Config.Data.WMsCount >= 20) Map(x => x.Sensor20);
+ if (Config.Data.WMsCount >= 21) Map(x => x.Sensor21);
+ if (Config.Data.WMsCount >= 22) Map(x => x.Sensor22);
+ if (Config.Data.WMsCount >= 23) Map(x => x.Sensor23);
+ if (Config.Data.WMsCount >= 24) Map(x => x.Sensor24);
+ if (Config.Data.WMsCount >= 25) Map(x => x.Sensor25);
+ if (Config.Data.WMsCount >= 26) Map(x => x.Sensor26);
+ if (Config.Data.WMsCount >= 27) Map(x => x.Sensor27);
+ if (Config.Data.WMsCount >= 28) Map(x => x.Sensor28);
+ if (Config.Data.WMsCount >= 29) Map(x => x.Sensor29);
+ if (Config.Data.WMsCount >= 30) Map(x => x.Sensor30);
+ if (Config.Data.WMsCount >= 31) Map(x => x.Sensor31);
+ if (Config.Data.WMsCount >= 32) Map(x => x.Sensor32);
+ if (Config.Data.WMsCount >= 33) Map(x => x.Sensor33);
+ if (Config.Data.WMsCount >= 34) Map(x => x.Sensor34);
+ if (Config.Data.WMsCount >= 35) Map(x => x.Sensor35);
+ if (Config.Data.WMsCount >= 36) Map(x => x.Sensor36);
+ if (Config.Data.WMsCount >= 37) Map(x => x.Sensor37);
+ if (Config.Data.WMsCount >= 38) Map(x => x.Sensor38);
+ if (Config.Data.WMsCount >= 39) Map(x => x.Sensor39);
+ if (Config.Data.WMsCount >= 40) Map(x => x.Sensor40);
+#pragma warning restore
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/OutputPathMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/OutputPathMap.cs
new file mode 100644
index 00000000..1e7ebbe1
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/OutputPathMap.cs
@@ -0,0 +1,35 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class OutputPathMap : ClassMap
+ {
+ public OutputPathMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+ Map(x => x.Qfrom);
+ Map(x => x.Qto);
+ Map(x => x.RegulValve);
+ Map(x => x.FlowMeter);
+ Map(x => x.PidCoef);
+ Map(x => x.StartValve);
+ Map(x => x.Diverter);
+ Map(x => x.TempDiv);
+ Map(x => x.Scale)
+ .Column("Balance");
+ Map(x => x.EmptyTankValve);
+ Map(x => x.ValvesOpen)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ Map(x => x.ValvesClose)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/ProcedureMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/ProcedureMap.cs
new file mode 100644
index 00000000..977d34c9
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/ProcedureMap.cs
@@ -0,0 +1,53 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class ProcedureMap : ClassMap
+ {
+ public ProcedureMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+
+ Map(x => x.Description);
+ Map(x => x.CreationUser);
+ Map(x => x.CreationTime);
+ Map(x => x.LastChgUser);
+ Map(x => x.LastChgTime);
+ Map(x => x.LongDescription);
+
+ Map(x => x.ProcedureState);
+ Map(x => x.Revision);
+ Map(x => x.PredecessorId);
+ Map(x => x.ObtainedByCopy);
+
+ Map(x => x.MetersKind);
+ Map(x => x.Watermeters);
+ Map(x => x.Protected);
+ Map(x => x.MustBeComplete);
+ Map(x => x.ManualCtrlDisabled);
+
+ Map(x => x.DataEntry);
+ Map(x => x.ResultsPrinter);
+ Map(x => x.ResultsWriter);
+ Map(x => x.TransitionStart);
+ Map(x => x.TransitionEnd);
+
+ Map(x => x.AltProcName);
+ Map(x => x.AltProcPeriod);
+
+ ////Map(x => x.MetrologicalClass);
+ ////HasOne(x => x.WMType);
+ HasMany(x => x.MoreParams)
+ .Cascade.All();
+ HasMany(x => x.Tests)
+ .OrderBy("ItemNr")
+ .Cascade.All();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/TestMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/TestMap.cs
new file mode 100644
index 00000000..52c9cb27
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/TestMap.cs
@@ -0,0 +1,65 @@
+///
+/// Copyright (c) 2013-2017 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class TestMap : ClassMap
+ {
+ public TestMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+ Map(x => x.Part);
+ Map(x => x.Publish);
+ Map(x => x.DoEvaluate)
+ .Column("Evaluate");
+ Map(x => x.Qfrom);
+ Map(x => x.Qto);
+ Map(x => x.Volume);
+ Map(x => x.TstTime);
+ Map(x => x.Repeats);
+ Map(x => x.DoDraining)
+ .Column("Emptying");
+ Map(x => x.DoZeroing)
+ .Column("Zeroing");
+ Map(x => x.DoControlWaterTemp);
+ Map(x => x.TempLimLo);
+ Map(x => x.TempLimHi);
+ Map(x => x.PumpPower);
+ Map(x => x.MassRepeats);
+ Map(x => x.MassSpread);
+ Map(x => x.MassMethod)
+ .CustomType();
+ Map(x => x.TimeBeforeFlow);
+ Map(x => x.TimeFlow2Mass);
+ Map(x => x.TimePump2StartV)
+ .Column("TimeMass2Start");
+ Map(x => x.TimeStop2Mass);
+ Map(x => x.Method);
+ Map(x => x.ErrLimLo);
+ Map(x => x.ErrLimHi);
+ Map(x => x.Uncertainty);
+ Map(x => x.TolerRed)
+ .Column("TolerRed"); /// ???
+ Map(x => x.RedType); /// ???
+ Map(x => x.FeedingPath);
+ Map(x => x.BenchPath);
+ Map(x => x.OutputPath);
+ Map(x => x.MetersPath);
+#if HEAT_METERS
+ Map(x => x.HeatMetersPath);
+#endif
+ Map(x => x.RelTransBefore);
+ Map(x => x.RelTransBetween);
+ Map(x => x.RelTransAfter);
+ Map(x => x.TransitionAfter);
+ HasMany(x => x.MoreParams)
+ .Cascade.All();
+ References(x => x.Procedure);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/TransitionSequenceMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/TransitionSequenceMap.cs
new file mode 100644
index 00000000..f270209d
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/TransitionSequenceMap.cs
@@ -0,0 +1,22 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class TransitionSequenceMap : ClassMap
+ {
+ public TransitionSequenceMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+ Map(x => x.Description);
+ HasMany(x => x.TransitionSteps)
+ .OrderBy("ItemNr")
+ .Cascade.All();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/TransitionStepMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/TransitionStepMap.cs
new file mode 100644
index 00000000..08196e71
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/TransitionStepMap.cs
@@ -0,0 +1,30 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class TransitionStepMap : ClassMap
+ {
+ public TransitionStepMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Duration);
+ Map(x => x.Message);
+ Map(x => x.EndCondition);
+ Map(x => x.ValvesOpen)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ Map(x => x.ValvesClose)
+ .CustomType("StringClob")
+ .CustomSqlType("varchar(8000)");
+ Map(x => x.RegulValvesPct);
+ Map(x => x.PumpWithFMPcts);
+
+ References(x => x.TransitionSequence);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/UserMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/UserMap.cs
new file mode 100644
index 00000000..ccb02838
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/UserMap.cs
@@ -0,0 +1,22 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+
+namespace Config.Mappings
+{
+ class UserMap : ClassMap
+ {
+ public UserMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.UserName).Column("Name");
+ Map(x => x.Number);
+ Map(x => x.Password);
+ Map(x => x.FullName).Column("Description");
+ Map(x => x.LastPwChange);
+ HasMany(x => x.Groups)
+ .Cascade.All();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/VirtualBenchSequenceMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/VirtualBenchSequenceMap.cs
new file mode 100644
index 00000000..2a002250
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/VirtualBenchSequenceMap.cs
@@ -0,0 +1,22 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class VirtualBenchSequenceMap : ClassMap
+ {
+ public VirtualBenchSequenceMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Name);
+ Map(x => x.Description);
+ HasMany(x => x.VirtualBenchSteps)
+ .OrderBy("ItemNr")
+ .Cascade.All();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/VirtualBenchStepMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/VirtualBenchStepMap.cs
new file mode 100644
index 00000000..bf4e7d65
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/VirtualBenchStepMap.cs
@@ -0,0 +1,20 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+using Config.Entities;
+
+namespace Config.Mappings
+{
+ class VirtualBenchStepMap : ClassMap
+ {
+ public VirtualBenchStepMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.ItemNr);
+ Map(x => x.Duration);
+
+ References(x => x.VirtualBenchSequence);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/WMTypeMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/WMTypeMap.cs
new file mode 100644
index 00000000..58173a51
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/WMTypeMap.cs
@@ -0,0 +1,20 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+
+namespace Config.Mappings
+{
+ class WMTypeMap : ClassMap
+ {
+ public WMTypeMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.CreateTime);
+ Map(x => x.CreateUserName);
+ Map(x => x.CreateDescription);
+ Map(x => x.Name);
+ Map(x => x.PulseRate);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Mappings/WatermeterMap.cs b/TBF_V2/Sources/TBF/Config/Mappings/WatermeterMap.cs
new file mode 100644
index 00000000..03553373
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Mappings/WatermeterMap.cs
@@ -0,0 +1,19 @@
+///
+/// Copyright (c) 2013-2015 Sensus Metering Systems
+///
+using FluentNHibernate.Mapping;
+
+namespace Config.Mappings
+{
+ class WatermeterMap : ClassMap
+ {
+ public WatermeterMap()
+ {
+ Id(x => x.Id);
+ Map(x => x.Serial);
+ // HasOne(x => x.WMType)
+ // .Cascade.All();
+ References(x => x.WMType);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Properties/AssemblyInfo.cs b/TBF_V2/Sources/TBF/Config/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..9a8e0d1f
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Config")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Sensus")]
+[assembly: AssemblyProduct("Config")]
+[assembly: AssemblyCopyright("Copyright © 2013 - 2018 Sensus Slovensko a.s.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3fc3ff67-7386-4aff-9855-bef33d5fa0d3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.18.928.0")]
+[assembly: AssemblyFileVersion("2.18.928.0")]
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.Designer.cs b/TBF_V2/Sources/TBF/Config/Resources/Strings.Designer.cs
new file mode 100644
index 00000000..313079c2
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.Designer.cs
@@ -0,0 +1,164 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Config.Resources {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Strings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Strings() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Config.Resources.Strings", typeof(Strings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Administrator.
+ ///
+ internal static string Administrator {
+ get {
+ return ResourceManager.GetString("Administrator", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Calibration Specialist.
+ ///
+ internal static string Calibration_Specialist {
+ get {
+ return ResourceManager.GetString("Calibration_Specialist", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Cannot open DB Cause 0.
+ ///
+ internal static string Cannot_open_DB_Cause_0 {
+ get {
+ return ResourceManager.GetString("Cannot_open_DB_Cause_0", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Error.
+ ///
+ internal static string Error
+ {
+ get
+ {
+ return ResourceManager.GetString("Error", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Failed.
+ ///
+ internal static string Failed {
+ get {
+ return ResourceManager.GetString("Failed", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Head of Lab.
+ ///
+ internal static string Head_of_Lab {
+ get {
+ return ResourceManager.GetString("Head_of_Lab", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Maintenance Specialist.
+ ///
+ internal static string Maintenance_Specialist {
+ get {
+ return ResourceManager.GetString("Maintenance_Specialist", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Metrologist.
+ ///
+ internal static string Metrologist {
+ get {
+ return ResourceManager.GetString("Metrologist", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Passed.
+ ///
+ internal static string Passed {
+ get {
+ return ResourceManager.GetString("Passed", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Tester.
+ ///
+ internal static string Tester {
+ get {
+ return ResourceManager.GetString("Tester", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Testing Specialist.
+ ///
+ internal static string Testing_Specialist {
+ get {
+ return ResourceManager.GetString("Testing_Specialist", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.cs.resx b/TBF_V2/Sources/TBF/Config/Resources/Strings.cs.resx
new file mode 100644
index 00000000..fde77890
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.cs.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Chyba
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.de.resx b/TBF_V2/Sources/TBF/Config/Resources/Strings.de.resx
new file mode 100644
index 00000000..e9a6e00e
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.de.resx
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Administrator
+
+
+ Kalibriertechniker
+
+
+ Laborleiter
+
+
+ Wartungstechniker
+
+
+ Messtechniker
+
+
+ Prüfer
+
+
+ Prüftechniker
+
+
+ NiO
+
+
+ iO
+
+
+ Fehler
+
+
+ Datenbank kann nicht geöffnet.\\r\\nUrsache:\\r\\n{0}
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.it.resx b/TBF_V2/Sources/TBF/Config/Resources/Strings.it.resx
new file mode 100644
index 00000000..457cc0e9
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.it.resx
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Amministratore
+
+
+ esperto in calibrazione
+
+
+ capo di laboratorio
+
+
+ esperto di manutenzione
+
+
+ metrologo
+
+
+ tester
+
+
+ esperto di prove
+
+
+ NOK
+
+
+ ok
+
+
+ Impossibile aprire il database\\r\\nCause:\\r\\n{0}
+
+
+ Errore
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.pl.resx b/TBF_V2/Sources/TBF/Config/Resources/Strings.pl.resx
new file mode 100644
index 00000000..def032d3
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.pl.resx
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Administrator
+
+
+ Specjalista ds. kalibracji
+
+
+ Kierownik Laboratorium
+
+
+ Konserwator
+
+
+ Metrolog
+
+
+ Pracownik przeprowadzający testy
+
+
+ Specjalista ds. testów
+
+
+ Niepowodzenie
+
+
+ OK
+
+
+ Nie można otworzyć \\r\\nCause:\\r\\n{0}
+
+
+ Błąd
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.resx b/TBF_V2/Sources/TBF/Config/Resources/Strings.resx
new file mode 100644
index 00000000..25ef4532
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.resx
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Administrator
+
+
+ Calibration Specialist
+
+
+ Head of Lab
+
+
+ Maintenance Specialist
+
+
+ Metrologist
+
+
+ Tester
+
+
+ Testing Specialist
+
+
+ NOK
+
+
+ OK
+
+
+ Cannot open database.\\r\\nCause:\\r\\n{0}
+
+
+ Error
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.ru.resx b/TBF_V2/Sources/TBF/Config/Resources/Strings.ru.resx
new file mode 100644
index 00000000..00b613b0
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.ru.resx
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Администратор
+
+
+ Специалист по калибровке
+
+
+ Руководитель лаборатории
+
+
+ Специалист по техобслуживанию
+
+
+ Метролог
+
+
+ Контролер
+
+
+ Специалист по тестированию
+
+
+ NOK
+
+
+ OK
+
+
+ Не удается открыть БД.\\r\\nCause:\\r\\n{0}
+
+
+ Ошибка
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Resources/Strings.zh-CN.resx b/TBF_V2/Sources/TBF/Config/Resources/Strings.zh-CN.resx
new file mode 100644
index 00000000..a95f116c
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Resources/Strings.zh-CN.resx
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 管理员
+
+
+ 校准专员
+
+
+ NOK
+
+
+ 实验室负责人
+
+
+ 维护专员
+
+
+ 计量者
+
+
+ 好
+
+
+ 测试仪
+
+
+ 测试专员
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/Config/Units.cs b/TBF_V2/Sources/TBF/Config/Units.cs
new file mode 100644
index 00000000..bf286e39
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Units.cs
@@ -0,0 +1,478 @@
+///
+/// Copyright (c) 2016-2018 Sensus Slovensko a.s.
+///
+using System;
+using System.Reflection;
+using Config.Entities;
+
+namespace Config
+{
+ public enum Unit
+ {
+ [Description("---")] None,
+
+ [Description("imp.")] pulse,
+#if LANG_PL
+ [Description("stopień")] degree,
+#else
+ [Description("degree")] degree,
+#endif
+ [Description("l")] l, /// * 1 liter
+ [Description("dm3")] dm3, /// 1 dm3 = 1 liter
+ [Description("m3")] m3, /// 1000 l
+ [Description("gal(UK)")] gal_UK, /// 1 gal(UK) = 4.54609 l
+ [Description("gal(US)")] gal_US, /// 1 gal(US) = 3.78541178 l
+
+ [Description("l/h")] lph, /// 1 liter/h
+ [Description("m3/h")] m3ph, /// * 1 m3/h = 1000 l/h
+
+ [Description("g")] g, /// 0.001 kg
+ [Description("kg")] kg, /// * 1 kilogram
+ [Description("t")] t, /// 1000 kg
+ [Description("lb")] lb, /// 0.45359237 kg
+
+ [Description("s")] s, /// * 1 second
+ [Description("min")] min, /// 1 min = 60 s
+ [Description("hr")] hour, /// 1 hour = 60 min = 3600 s
+ [Description("ms")] ms, /// 1 ms = 0.001 s
+
+ [Description("°C")] C, /// * degree Celsius (°C)
+ [Description("°F")] F, /// degree Fahrenheit
+ [Description("K")] K, /// degree Kelvin
+
+ [Description("Pa")] Pa, /// 1 Pa = 0.01 hPa
+ [Description("hPa")] hPa, /// 1 hPa = 100 Pa
+ [Description("kPa")] kPa, /// 1 kPa = 10 HPa
+ [Description("MPa")] MPa, /// 1 MPa = 10000 hPa
+ [Description("mbar")] mbar, /// 1 mbar = 1 hPa = 100 Pa
+ [Description("bar")] bar, /// * 1 Bar = 1000 mbar = 0.1 MPa = 100000 Pa
+ [Description("inHg")] inHg, /// 1 inHg = 33.864 hPa
+
+ [Description("R%")] RPct, /// * 1 R%
+
+ [Description("%")] Pct, /// * 1 %
+ [Description("promile")] Promile, /// 1 promile = 0.1 %
+
+ [Description("mm")] mm, /// * 1 millimeter
+ [Description("cm")] cm, /// 1 cm = 10 mm
+ [Description("m")] m, /// 1 m = 1000 mm
+ [Description("in")] inch, /// 1 inch = 25.4 mm
+
+ [Description("kg/m3")] kgpm3, /// * 1 kg/m3 = 0.001 kg/l
+ [Description("kg/l")] kgpl, /// 1 kg/l = 1000 kg/m3
+
+ [Description("J")] J, /// * 1 Joul
+ [Description("kJ")] kJ, /// 1 kJ = 1000 J
+ [Description("MJ")] MJ, /// 1 MJ = 1000000 J
+ [Description("Wh")] Wh, /// 1 Wh = 3600 J
+ [Description("kWh")] kWh, /// 1 kWh = 3600000 J
+ [Description("MWh")] MWh, /// 1 MWh = 3600000000 J
+
+#if LANG_PL
+ [Description("imp/l")] ppl, /// * 1 pulse/l
+ [Description("imp/dm3")] ppdm3, /// * 1 pulse/dm3
+ [Description("stopień/l")] degpl, /// * 1 degree/l
+ [Description("stopień/dm3")] degpdm3, /// * 1 degree/dm3
+ [Description("l/imp")] lpp, /// * 1 l/pulse
+ [Description("dm3/imp")] dm3pp, /// * 1 dm3/pulse
+ [Description("l/stopień")] lpdeg, /// * 1 l/degree
+ [Description("dm3/stopień")] dm3pdeg, /// * 1 dm3/degree
+#else
+ [Description("pulse/l")] ppl, /// * 1 pulse/l
+ [Description("pulse/dm3")] ppdm3, /// * 1 pulse/dm3
+ [Description("degree/l")] degpl, /// * 1 degree/l
+ [Description("degree/dm3")] degpdm3, /// * 1 degree/dm3
+ [Description("l/pulse")] lpp, /// * 1 l/pulse
+ [Description("dm3/pulse")] dm3pp, /// * 1 dm3/pulse
+ [Description("l/degree")] lpdeg, /// * 1 l/degree
+ [Description("dm3/degree")] dm3pdeg, /// * 1 dm3/degree
+#endif
+ ///
+ [Description("pulse/kWh")] ppkWh, /// * 1 pulse/kWh
+ [Description("kWh/pulse")] kWhpp, /// * 1 kWh/pulse
+
+ Count
+ }
+
+ public enum Quantity
+ {
+ /// Quantities with units and conversions (double -> double)
+#if LANG_DE
+ [Description("Volumen")] Volume,
+ [Description("Durchfluss")] Flow,
+ [Description("Masse")] Mass,
+ [Description("Zeit")] Time,
+ [Description("Temperatur")] Temperature,
+ [Description("Druck")] Pressure,
+ [Description("Feuchtigkeit")] Humidity,
+ [Description("Fehler")] Error,
+ [Description("Länge")] Length,
+ [Description("Dichte")] Density,
+ [Description("Energie")] Energy,
+ [Description("Impulse")] Pulses,
+ [Description("Impulse/l")] PulsePerLtr,
+ [Description("Impulse/kWh")] PulsePerKWh,
+
+ /// Quantities without units and conversions
+ [Description("Nummer")] Number,
+ [Description("Text")] String,
+ [Description("Boolean")] Boolean,
+ [Description("Datum und Uhrzeit")] DateTime,
+#elif LANG_PL
+ [Description("Objętość")] Volume,
+ [Description("Przepływ")] Flow,
+ [Description("Masa")] Mass,
+ [Description("Czas")] Time,
+ [Description("Temperatura")] Temperature,
+ [Description("Ciśnienie")] Pressure,
+ [Description("Wilgotność")] Humidity,
+ [Description("Błąd")] Error,
+ [Description("Długość")] Length,
+ [Description("Gęstość")] Density,
+ [Description("Energia")] Energy,
+ [Description("Impulsy")] Pulses,
+ [Description("Impulsy/litr")] PulsePerLtr,
+ [Description("Impulsy/kWh")] PulsePerKWh,
+
+ /// Quantities without units and conversions
+ [Description("Numer")] Number,
+ [Description("Tekst")] String,
+ [Description("Boolean")] Boolean,
+ [Description("Data i czas")] DateTime,
+#elif LANG_CS
+ [Description("Objem")] Volume,
+ [Description("Průtok")] Flow,
+ [Description("Hmotnost")] Mass,
+ [Description("Čas")] Time,
+ [Description("Teplota")] Temperature,
+ [Description("Tlak")] Pressure,
+ [Description("Vlhkost")] Humidity,
+ [Description("Chyba")] Error,
+ [Description("Délka")] Length,
+ [Description("Hustota")] Density,
+ [Description("Energie")] Energy,
+ [Description("Pulzy")] Pulses,
+ [Description("Pulzy/litr")] PulsePerLtr,
+ [Description("Pulzy/kWh")] PulsePerKWh,
+
+ /// Quantities without units and conversions
+ [Description("Počet")] Number,
+ [Description("Text")] String,
+ [Description("Boolean")] Boolean,
+ [Description("Datum a čas")] DateTime,
+#elif LANG_IT
+ [Description("Volume")] Volume,
+ [Description("Flusso")] Flow,
+ [Description("Massa")] Mass,
+ [Description("Tempo")] Time,
+ [Description("Temperatura")] Temperature,
+ [Description("Pressione")] Pressure,
+ [Description("Umidità")] Humidity,
+ [Description("Errore")] Error,
+ [Description("Lungezza")] Length,
+ [Description("Densità")] Density,
+ [Description("Energia")] Energy,
+ [Description("Impulso")] Pulses,
+ [Description("Impulso/litro")] PulsePerLtr,
+ [Description("Impulso/kWh")] PulsePerKWh,
+
+ /// Quantities without units and conversions
+ [Description("Numero")] Number,
+ [Description("Stringa")] String,
+ [Description("Boolean")] Boolean,
+ [Description("Data e ora")] DateTime,
+#else
+ [Description("Volume")] Volume,
+ [Description("Flow")] Flow,
+ [Description("Mass")] Mass,
+ [Description("Time")] Time,
+ [Description("Temperature")] Temperature,
+ [Description("Pressure")] Pressure,
+ [Description("Humidity")] Humidity,
+ [Description("Error")] Error,
+ [Description("Length")] Length,
+ [Description("Density")] Density,
+ [Description("Energy")] Energy,
+ [Description("Pulses")] Pulses,
+ [Description("Pulses/liter")] PulsePerLtr,
+ [Description("Pulses/kWh")] PulsePerKWh,
+
+ /// Quantities without units and conversions
+ [Description("Number")] Number,
+ [Description("String")] String,
+ [Description("Boolean")] Boolean,
+ [Description("Date and time")] DateTime,
+#endif
+ Count,
+ }
+
+ public static class Units
+ {
+ public static bool IsUnitless(Quantity quantity)
+ {
+ return quantity >= Quantity.Number;
+ }
+
+ public static bool IsDefaultUnit(Unit unit)
+ {
+ return unit == Unit.l || unit == Unit.m3ph || unit == Unit.kg || unit == Unit.s || unit == Unit.C || unit == Unit.bar || unit == Unit.RPct ||
+ unit == Unit.Pct || unit == Unit.mm || unit == Unit.kgpm3 || unit == Unit.J || unit == Unit.ppl || unit == Unit.ppkWh;
+ }
+
+ public static bool IsQuantity(Unit units, Quantity quantity)
+ {
+ return (quantity == GetQuantity(units));
+ }
+
+ public static Quantity GetQuantity(Unit units)
+ {
+ switch (units)
+ {
+ case Unit.pulse:
+ case Unit.degree:
+ return Config.Quantity.Pulses;
+
+ case Unit.l:
+ case Unit.dm3:
+ case Unit.m3:
+ case Unit.gal_UK:
+ case Unit.gal_US:
+ return Config.Quantity.Volume;
+
+ case Unit.lph:
+ case Unit.m3ph:
+ return Config.Quantity.Flow;
+
+ case Unit.g:
+ case Unit.kg:
+ case Unit.t:
+ case Unit.lb:
+ return Config.Quantity.Mass;
+
+ case Unit.s:
+ case Unit.min:
+ case Unit.hour:
+ case Unit.ms:
+ return Config.Quantity.Time;
+
+ case Unit.C:
+ case Unit.F:
+ case Unit.K:
+ return Config.Quantity.Temperature;
+
+ case Unit.Pa:
+ case Unit.hPa:
+ case Unit.mbar:
+ case Unit.kPa:
+ case Unit.bar:
+ case Unit.MPa:
+ case Unit.inHg:
+ return Config.Quantity.Pressure;
+
+ case Unit.RPct:
+ return Config.Quantity.Humidity;
+
+ case Unit.Pct:
+ case Unit.Promile:
+ return Config.Quantity.Error;
+
+ case Unit.mm:
+ case Unit.cm:
+ case Unit.m:
+ case Unit.inch:
+ return Config.Quantity.Length;
+
+ case Unit.kgpm3:
+ case Unit.kgpl:
+ return Config.Quantity.Density;
+
+ case Unit.J:
+ case Unit.kJ:
+ case Unit.MJ:
+ case Unit.Wh:
+ case Unit.kWh:
+ case Unit.MWh:
+ return Config.Quantity.Energy;
+
+ case Unit.ppl:
+ case Unit.ppdm3:
+ case Unit.degpl:
+ case Unit.degpdm3:
+ case Unit.lpp:
+ case Unit.dm3pp:
+ case Unit.lpdeg:
+ case Unit.dm3pdeg:
+ return Config.Quantity.PulsePerLtr;
+
+ case Unit.ppkWh:
+ case Unit.kWhpp:
+ return Config.Quantity.PulsePerKWh;
+
+ default:
+ return Config.Quantity.Number;
+ }
+ }
+
+ public static bool IsVolume(Unit units) { return IsQuantity(units, Config.Quantity.Volume); }
+ public static bool IsFlow(Unit units) { return IsQuantity(units, Config.Quantity.Flow); }
+ public static bool IsMass(Unit units) { return IsQuantity(units, Config.Quantity.Mass); }
+ public static bool IsTime(Unit units) { return IsQuantity(units, Config.Quantity.Time); }
+ public static bool IsTemperature(Unit units) { return IsQuantity(units, Config.Quantity.Temperature); }
+ public static bool IsPressure(Unit units) { return IsQuantity(units, Config.Quantity.Pressure); }
+ public static bool IsHumidity(Unit units) { return IsQuantity(units, Config.Quantity.Humidity); }
+ public static bool IsError(Unit units) { return IsQuantity(units, Config.Quantity.Error); }
+ public static bool IsLength(Unit units) { return IsQuantity(units, Config.Quantity.Length); }
+ public static bool IsDensity(Unit units) { return IsQuantity(units, Config.Quantity.Density); }
+ public static bool IsEnergy(Unit units) { return IsQuantity(units, Config.Quantity.Energy); }
+ public static bool IsPulses(Unit units) { return IsQuantity(units, Config.Quantity.Pulses); }
+ public static bool IsPulsePerLtr(Unit units) { return IsQuantity(units, Config.Quantity.PulsePerLtr); }
+ public static bool IsPulsePerKWh(Unit units) { return IsQuantity(units, Config.Quantity.PulsePerKWh); }
+
+
+ public static double ConvertTo(Unit units, double v)
+ {
+ switch (units)
+ {
+ /// Volume: internal representation in l
+ case Unit.dm3:
+ case Unit.l: return v; /// 1 liter
+ case Unit.m3: return 0.001 * v; /// 1 m3 = 1000 l
+ case Unit.gal_UK: return 0.21996925 * v; /// 1 gal(UK) = 4.54609 l
+ case Unit.gal_US: return 0.26417205 * v; /// 1 gal(US) = 3.78541178 l
+
+ /// Flow: internal representation in m3/h
+ case Unit.lph: return 1000 * v; /// 1 liter/h
+ case Unit.m3ph: return v; /// 1 m3/h = 1000 l/h
+
+ /// Mass: internal representation in kg
+ case Unit.g: return 1000 * v; /// 1 g = 0.001 kg
+ case Unit.kg: return v; /// 1 kilogram
+ case Unit.t: return 0.001 * v; /// 1 t = 1000 kg
+ case Unit.lb: return 2.2046226 * v; /// 1 lb = 0.45359237 kg
+
+ /// Time or duration: internal representation in seconds [s]
+ case Unit.s: return v;
+ case Unit.min: return v / 60;
+ case Unit.hour: return v / 3600;
+ case Unit.ms: return 1000 * v;
+
+ /// Temperature: internal representation in °C
+ case Unit.C: return v; /// degree Celsius (°C)
+ case Unit.F: return 1.8 * v + 32; /// degree Fahrenheit
+ case Unit.K: return v + 273.15; /// degree Kelvin
+
+ /// Pressure: internal representation in bar = 0.1 MPa
+ case Unit.Pa: return 100000 * v; /// 1 hPa = 100 Pa
+ case Unit.hPa: return 1000 * v; /// 1 hPa = 100 Pa
+ case Unit.mbar: return 1000 * v; /// 1 mbar = 1 hPa = 100 Pa
+ case Unit.kPa: return 100 * v; /// 1 kPa = 10 HPa
+ case Unit.bar: return v; /// 1 bar = 1000 mbar = 100000 Pa
+ case Unit.MPa: return 0.1 * v; /// 1 MPa = 10000 hPa
+ case Unit.inHg: return 29.53 * v; /// 1 inHg = 33.864 hPa
+
+ /// Error: internal representation in %
+ case Unit.Pct: return v; /// 1 %
+ case Unit.Promile: return 10 * v; /// 1 promile = 0.1 %
+
+ /// Diameter, length: internal representation in mm
+ case Unit.mm: return v; /// 1 mm
+ case Unit.cm: return 0.1 * v; /// 1 cm = 10 mm
+ case Unit.m: return 0.001 * v; /// 1 m = 1000 mm
+ case Unit.inch: return v / 25.4; /// 1 inch = 25.4 mm
+
+ /// Density: internal representation in kg/m3
+ case Unit.kgpm3: return v;
+ case Unit.kgpl: return 0.001 * v;
+
+ /// Energy, internal representation in Joul
+ case Unit.J: return v; /// 1 Joul
+ case Unit.kJ: return 0.001 * v; /// 1 kJ = 1000 J
+ case Unit.MJ: return 0.000001 * v; /// 1 kJ = 1000000 J
+ case Unit.Wh: return v / 3600.0; /// 1 Wh = 3600 J
+ case Unit.kWh: return v / 3600000.0; /// 1 kWh = 3600000 J
+ case Unit.MWh: return v / 3600000000.0;/// 1 MWh = 3600000000 J
+
+ case Unit.kWhpp:
+ case Unit.lpp:
+ case Unit.dm3pp:
+ case Unit.lpdeg:
+ case Unit.dm3pdeg: return ((v <= float.Epsilon) ? 0 : 1 / v);
+
+ default: return v;
+ }
+ }
+
+ public static double ConvertFrom(Unit units, double v)
+ {
+ switch (units)
+ {
+ /// Volume: internal representation in l
+ case Unit.dm3:
+ case Unit.l: return v; /// 1 liter
+ case Unit.m3: return 1000 * v; /// 1000 l
+ case Unit.gal_UK: return 4.54609 * v; /// 1 gal(UK) = 4.54609 l
+ case Unit.gal_US: return 3.78541178 * v; /// 1 gal(US) = 3.78541178 l
+
+ /// Flow: internal representation in m3/h
+ case Unit.lph: return 0.001 * v; /// 1 liter/h
+ case Unit.m3ph: return v; /// 1 m3/h = 1000 l/h
+
+ /// Mass: internal representation in kg
+ case Unit.g: return 0.001 * v; /// 1 g = 0.001 kg
+ case Unit.kg: return v; /// 1 kilogram
+ case Unit.t: return 1000 * v; /// 1 t = 1000 kg
+ case Unit.lb: return 0.45359237 * v; /// 1 lb = 0.45359237 kg
+
+ /// Time or duration: internal representation in seconds [s]
+ case Unit.s: return v;
+ case Unit.min: return 60 * v;
+ case Unit.hour: return 3600 * v;
+ case Unit.ms: return v / 1000;
+
+ /// Temperature: internal representation in °C
+ case Unit.C: return v; /// degree Celsius (°C)
+ case Unit.F: return 5 * (v-32) / 9; /// degree Fahrenheit
+ case Unit.K: return v - 273.15; /// degree Kelvin
+
+ /// Pressure: internal representation in bar = 0.1 MPa
+ case Unit.Pa: return 0.00001 * v; /// 1 hPa = 100 Pa
+ case Unit.hPa: return 0.001 * v; /// 1 hPa = 100 Pa
+ case Unit.mbar: return 0.001 * v; /// 1 mbar = 1 hPa = 100 Pa
+ case Unit.kPa: return 0.01 * v; /// 1 kPa = 10 HPa
+ case Unit.bar: return v; /// 1 bar = 1000 mbar = 100000 Pa
+ case Unit.MPa: return 10 * v; /// 1 MPa = 10000 hPa
+ case Unit.inHg: return 0.033864 * v; /// 1 inHg = 33.864 hPa
+
+ /// Error: internal representation in %
+ case Unit.Pct: return v; /// 1 %
+ case Unit.Promile: return 0.1 * v; /// 1 promile = 0.1 %
+
+ /// Diameter, length: internal representation in mm
+ case Unit.mm: return v; /// 1 mm
+ case Unit.cm: return 10 * v; /// 1 cm = 10 mm
+ case Unit.m: return 1000 * v; /// 1 m = 1000 mm
+ case Unit.inch: return 25.4 * v; /// 1 inch = 25.4 mm
+
+ /// Density: internal representation in kg/m3
+ case Unit.kgpm3: return v;
+ case Unit.kgpl: return 1000 * v;
+
+ /// Energy, internal representation in Joul
+ case Unit.J: return v; /// 1 Joul
+ case Unit.kJ: return 1000 * v; /// 1 kJ = 1000 J
+ case Unit.MJ: return 1000000 * v; /// 1 kJ = 1000000 J
+ case Unit.Wh: return 3600 * v; /// 1 Wh = 3600 J
+ case Unit.kWh: return 3600000 * v; /// 1 kWh = 3600000 J
+ case Unit.MWh: return 3600000000 * v; /// 1 kWh = 3600000000 J
+
+ case Unit.kWhpp:
+ case Unit.lpp:
+ case Unit.dm3pp:
+ case Unit.lpdeg:
+ case Unit.dm3pdeg: return ((v == 0) ? 0 : 1 / v);
+
+ default: return v;
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Config/Utils.cs b/TBF_V2/Sources/TBF/Config/Utils.cs
new file mode 100644
index 00000000..f93c6f75
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Config/Utils.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Config
+{
+ public static class Utils
+ {
+ public static string SignificantDigitsToFmt(double value, int sigDigits)
+ {
+ if (sigDigits == 5)
+ {
+ if (value >= 9999.5 || value < -9999.5) return "F0";
+ else if (value >= 999.95 || value < -999.95) return "F1";
+ else if (value >= 99.995 || value < -99.995) return "F2";
+ else if (value >= 9.9995 || value < -9.9995) return "F3";
+ else if (value >= 0.99995 || value < -0.99995) return "F4";
+ else if (value >= 0.099995 || value < -0.099995) return "F5";
+ else if (value >= 0.0099995 || value < -0.0099995) return "F6";
+ else if (value >= 0.00099995 || value < -0.00099995) return "F7";
+ else if (value >= 0.000099995 || value < -0.000099995) return "F8";
+ else return "F9";
+ }
+ else if (sigDigits == 4)
+ {
+ if (value >= 999.5 || value < -999.5) return "F0";
+ else if (value >= 99.95 || value < -99.95) return "F1";
+ else if (value >= 9.995 || value < -9.995) return "F2";
+ else if (value >= 0.9995 || value < -0.9995) return "F3";
+ else if (value >= 0.09995 || value < -0.09995) return "F4";
+ else if (value >= 0.009995 || value < -0.009995) return "F5";
+ else if (value >= 0.0009995 || value < -0.0009995) return "F6";
+ else if (value >= 0.00009995 || value < -0.00009995) return "F7";
+ else return "F8";
+ }
+ else if (sigDigits == 3)
+ {
+ if (value >= 99.5 || value < -99.5) return "F0";
+ else if (value >= 9.95 || value < -9.95) return "F1";
+ else if (value >= 0.995 || value < -0.995) return "F2";
+ else if (value >= 0.0995 || value < -0.0995) return "F3";
+ else if (value >= 0.00995 || value < -0.00995) return "F4";
+ else if (value >= 0.000995 || value < -0.000995) return "F5";
+ else if (value >= 0.0000995 || value < -0.0000995) return "F6";
+ else return "F7";
+ }
+ else if (sigDigits == 2)
+ {
+ if (value >= 9.5 || value < -9.5) return "F0";
+ else if (value >= 0.95 || value < -0.95) return "F1";
+ else if (value >= 0.095 || value < -0.095) return "F2";
+ else if (value >= 0.0095 || value < -0.0095) return "F3";
+ else if (value >= 0.00095 || value < -0.00095) return "F4";
+ else if (value >= 0.000095 || value < -0.000095) return "F5";
+ else return "F6";
+ }
+ else /// if (sigDigits == 1)
+ {
+ if (value >= 0.95 || value < -0.95) return "F0";
+ else if (value >= 0.095 || value < -0.095) return "F1";
+ else if (value >= 0.0095 || value < -0.0095) return "F2";
+ else if (value >= 0.00095 || value < -0.00095) return "F3";
+ else if (value >= 0.000095 || value < -0.000095) return "F4";
+ else return "F5";
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/DeviceTest/DeviceTest.csproj b/TBF_V2/Sources/TBF/DeviceTest/DeviceTest.csproj
new file mode 100644
index 00000000..98047db2
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/DeviceTest.csproj
@@ -0,0 +1,108 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {6D3384DC-4638-4A92-91A8-F39D900377C6}
+ WinExe
+ Properties
+ DeviceTest
+ DeviceTest
+ v4.0
+
+
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ DeviceTest.Program
+
+
+
+ False
+ ..\packages\log4net.2.0.2\lib\net40-full\log4net.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ DeviceTestDlg.cs
+
+
+
+
+
+ DeviceTestDlg.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+ {743DF7DB-C7B6-42EB-986D-0F485E5588E4}
+ Config
+
+
+ {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}
+ TBF
+
+
+
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.Designer.cs b/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.Designer.cs
new file mode 100644
index 00000000..3077a04c
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.Designer.cs
@@ -0,0 +1,584 @@
+namespace DeviceTest
+{
+ partial class DeviceTestDlg
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.parentClassNameComboBox = new System.Windows.Forms.ComboBox();
+ this.classLabel = new System.Windows.Forms.Label();
+ this.nameLabel = new System.Windows.Forms.Label();
+ this.parentNameTextBox = new System.Windows.Forms.TextBox();
+ this.configureParentButton = new System.Windows.Forms.Button();
+ this.startButton = new System.Windows.Forms.Button();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.configureComponent1Button = new System.Windows.Forms.Button();
+ this.componentNameTextBox = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.component1ClassNameComboBox = new System.Windows.Forms.ComboBox();
+ this.radioButton4 = new System.Windows.Forms.RadioButton();
+ this.radioButton3 = new System.Windows.Forms.RadioButton();
+ this.radioButton2 = new System.Windows.Forms.RadioButton();
+ this.radioButton1 = new System.Windows.Forms.RadioButton();
+ this.radioButton0 = new System.Windows.Forms.RadioButton();
+ this.stopButton = new System.Windows.Forms.Button();
+ this.groupBox3 = new System.Windows.Forms.GroupBox();
+ this.configureComponent2Button = new System.Windows.Forms.Button();
+ this.component2NameTextBox = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.component2ClassNameComboBox = new System.Windows.Forms.ComboBox();
+ this.radioButton24 = new System.Windows.Forms.RadioButton();
+ this.radioButton23 = new System.Windows.Forms.RadioButton();
+ this.radioButton22 = new System.Windows.Forms.RadioButton();
+ this.radioButton21 = new System.Windows.Forms.RadioButton();
+ this.groupBox4 = new System.Windows.Forms.GroupBox();
+ this.radioButton34 = new System.Windows.Forms.RadioButton();
+ this.radioButton33 = new System.Windows.Forms.RadioButton();
+ this.radioButton32 = new System.Windows.Forms.RadioButton();
+ this.radioButton31 = new System.Windows.Forms.RadioButton();
+ this.groupBox5 = new System.Windows.Forms.GroupBox();
+ this.configureComponent3Button = new System.Windows.Forms.Button();
+ this.component3NameTextBox = new System.Windows.Forms.TextBox();
+ this.label5 = new System.Windows.Forms.Label();
+ this.label6 = new System.Windows.Forms.Label();
+ this.component3ClassNameComboBox = new System.Windows.Forms.ComboBox();
+ this.groupBox1.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.groupBox3.SuspendLayout();
+ this.groupBox4.SuspendLayout();
+ this.groupBox5.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // parentClassNameComboBox
+ //
+ this.parentClassNameComboBox.FormattingEnabled = true;
+ this.parentClassNameComboBox.Location = new System.Drawing.Point(77, 19);
+ this.parentClassNameComboBox.Name = "parentClassNameComboBox";
+ this.parentClassNameComboBox.Size = new System.Drawing.Size(299, 21);
+ this.parentClassNameComboBox.TabIndex = 0;
+ //
+ // classLabel
+ //
+ this.classLabel.AutoSize = true;
+ this.classLabel.Location = new System.Drawing.Point(11, 22);
+ this.classLabel.Name = "classLabel";
+ this.classLabel.Size = new System.Drawing.Size(32, 13);
+ this.classLabel.TabIndex = 1;
+ this.classLabel.Text = "Class";
+ //
+ // nameLabel
+ //
+ this.nameLabel.AutoSize = true;
+ this.nameLabel.Location = new System.Drawing.Point(11, 47);
+ this.nameLabel.Name = "nameLabel";
+ this.nameLabel.Size = new System.Drawing.Size(35, 13);
+ this.nameLabel.TabIndex = 2;
+ this.nameLabel.Text = "Name";
+ //
+ // parentNameTextBox
+ //
+ this.parentNameTextBox.Enabled = false;
+ this.parentNameTextBox.Location = new System.Drawing.Point(77, 44);
+ this.parentNameTextBox.Name = "parentNameTextBox";
+ this.parentNameTextBox.Size = new System.Drawing.Size(299, 20);
+ this.parentNameTextBox.TabIndex = 3;
+ //
+ // configureParentButton
+ //
+ this.configureParentButton.Location = new System.Drawing.Point(395, 19);
+ this.configureParentButton.Name = "configureParentButton";
+ this.configureParentButton.Size = new System.Drawing.Size(73, 45);
+ this.configureParentButton.TabIndex = 4;
+ this.configureParentButton.Text = "Configure";
+ this.configureParentButton.UseVisualStyleBackColor = true;
+ this.configureParentButton.Click += new System.EventHandler(this.configureParentButton_Click);
+ //
+ // startButton
+ //
+ this.startButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.startButton.Location = new System.Drawing.Point(520, 19);
+ this.startButton.Name = "startButton";
+ this.startButton.Size = new System.Drawing.Size(73, 45);
+ this.startButton.TabIndex = 7;
+ this.startButton.Text = "Start";
+ this.startButton.UseVisualStyleBackColor = true;
+ this.startButton.Click += new System.EventHandler(this.startButton_Click);
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.configureParentButton);
+ this.groupBox1.Controls.Add(this.parentNameTextBox);
+ this.groupBox1.Controls.Add(this.nameLabel);
+ this.groupBox1.Controls.Add(this.classLabel);
+ this.groupBox1.Controls.Add(this.parentClassNameComboBox);
+ this.groupBox1.Location = new System.Drawing.Point(12, 12);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(486, 75);
+ this.groupBox1.TabIndex = 8;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Parent component";
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.configureComponent1Button);
+ this.groupBox2.Controls.Add(this.componentNameTextBox);
+ this.groupBox2.Controls.Add(this.label1);
+ this.groupBox2.Controls.Add(this.label2);
+ this.groupBox2.Controls.Add(this.component1ClassNameComboBox);
+ this.groupBox2.Location = new System.Drawing.Point(12, 93);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(486, 75);
+ this.groupBox2.TabIndex = 9;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "Component 1";
+ //
+ // configureComponentButton
+ //
+ this.configureComponent1Button.Location = new System.Drawing.Point(395, 19);
+ this.configureComponent1Button.Name = "configureComponentButton";
+ this.configureComponent1Button.Size = new System.Drawing.Size(73, 45);
+ this.configureComponent1Button.TabIndex = 4;
+ this.configureComponent1Button.Text = "Configure";
+ this.configureComponent1Button.UseVisualStyleBackColor = true;
+ this.configureComponent1Button.Click += new System.EventHandler(this.configureComponent1Button_Click);
+ //
+ // componentNameTextBox
+ //
+ this.componentNameTextBox.Enabled = false;
+ this.componentNameTextBox.Location = new System.Drawing.Point(77, 44);
+ this.componentNameTextBox.Name = "componentNameTextBox";
+ this.componentNameTextBox.Size = new System.Drawing.Size(299, 20);
+ this.componentNameTextBox.TabIndex = 3;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(11, 47);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(35, 13);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "Name";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(11, 22);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(32, 13);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "Class";
+ //
+ // componentClassNameComboBox
+ //
+ this.component1ClassNameComboBox.FormattingEnabled = true;
+ this.component1ClassNameComboBox.Location = new System.Drawing.Point(77, 19);
+ this.component1ClassNameComboBox.Name = "componentClassNameComboBox";
+ this.component1ClassNameComboBox.Size = new System.Drawing.Size(299, 21);
+ this.component1ClassNameComboBox.TabIndex = 0;
+ //
+ // radioButton4
+ //
+ this.radioButton4.AutoSize = true;
+ this.radioButton4.Location = new System.Drawing.Point(13, 118);
+ this.radioButton4.Name = "radioButton4";
+ this.radioButton4.Size = new System.Drawing.Size(51, 17);
+ this.radioButton4.TabIndex = 9;
+ this.radioButton4.TabStop = true;
+ this.radioButton4.Text = "spare";
+ this.radioButton4.UseVisualStyleBackColor = true;
+ this.radioButton4.CheckedChanged += new System.EventHandler(this.radioButton4_CheckedChanged);
+ //
+ // radioButton3
+ //
+ this.radioButton3.AutoSize = true;
+ this.radioButton3.Location = new System.Drawing.Point(13, 95);
+ this.radioButton3.Name = "radioButton3";
+ this.radioButton3.Size = new System.Drawing.Size(51, 17);
+ this.radioButton3.TabIndex = 8;
+ this.radioButton3.TabStop = true;
+ this.radioButton3.Text = "spare";
+ this.radioButton3.UseVisualStyleBackColor = true;
+ this.radioButton3.CheckedChanged += new System.EventHandler(this.radioButton3_CheckedChanged);
+ //
+ // radioButton2
+ //
+ this.radioButton2.AutoSize = true;
+ this.radioButton2.Location = new System.Drawing.Point(13, 72);
+ this.radioButton2.Name = "radioButton2";
+ this.radioButton2.Size = new System.Drawing.Size(51, 17);
+ this.radioButton2.TabIndex = 7;
+ this.radioButton2.TabStop = true;
+ this.radioButton2.Text = "spare";
+ this.radioButton2.UseVisualStyleBackColor = true;
+ this.radioButton2.CheckedChanged += new System.EventHandler(this.radioButton2_CheckedChanged);
+ //
+ // radioButton1
+ //
+ this.radioButton1.AutoSize = true;
+ this.radioButton1.Location = new System.Drawing.Point(13, 49);
+ this.radioButton1.Name = "radioButton1";
+ this.radioButton1.Size = new System.Drawing.Size(106, 17);
+ this.radioButton1.TabIndex = 6;
+ this.radioButton1.TabStop = true;
+ this.radioButton1.Text = "ReadPressureOp";
+ this.radioButton1.UseVisualStyleBackColor = true;
+ this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButton1_CheckedChanged);
+ //
+ // radioButton0
+ //
+ this.radioButton0.AutoSize = true;
+ this.radioButton0.Location = new System.Drawing.Point(13, 26);
+ this.radioButton0.Name = "radioButton0";
+ this.radioButton0.Size = new System.Drawing.Size(94, 17);
+ this.radioButton0.TabIndex = 5;
+ this.radioButton0.TabStop = true;
+ this.radioButton0.Text = "Stop operation";
+ this.radioButton0.UseVisualStyleBackColor = true;
+ this.radioButton0.CheckedChanged += new System.EventHandler(this.radioButton0_CheckedChanged);
+ //
+ // stopButton
+ //
+ this.stopButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.stopButton.Location = new System.Drawing.Point(520, 77);
+ this.stopButton.Name = "stopButton";
+ this.stopButton.Size = new System.Drawing.Size(73, 45);
+ this.stopButton.TabIndex = 10;
+ this.stopButton.Text = "Stop";
+ this.stopButton.UseVisualStyleBackColor = true;
+ this.stopButton.Click += new System.EventHandler(this.stopButton_Click);
+ //
+ // groupBox3
+ //
+ this.groupBox3.Controls.Add(this.configureComponent2Button);
+ this.groupBox3.Controls.Add(this.component2NameTextBox);
+ this.groupBox3.Controls.Add(this.label3);
+ this.groupBox3.Controls.Add(this.label4);
+ this.groupBox3.Controls.Add(this.component2ClassNameComboBox);
+ this.groupBox3.Location = new System.Drawing.Point(12, 174);
+ this.groupBox3.Name = "groupBox3";
+ this.groupBox3.Size = new System.Drawing.Size(486, 75);
+ this.groupBox3.TabIndex = 11;
+ this.groupBox3.TabStop = false;
+ this.groupBox3.Text = "Component 2";
+ //
+ // configureComponent2Button
+ //
+ this.configureComponent2Button.Location = new System.Drawing.Point(395, 19);
+ this.configureComponent2Button.Name = "configureComponent2Button";
+ this.configureComponent2Button.Size = new System.Drawing.Size(73, 45);
+ this.configureComponent2Button.TabIndex = 4;
+ this.configureComponent2Button.Text = "Configure";
+ this.configureComponent2Button.UseVisualStyleBackColor = true;
+ this.configureComponent2Button.Click += new System.EventHandler(this.configureComponent2Button_Click);
+ //
+ // component2NameTextBox
+ //
+ this.component2NameTextBox.Enabled = false;
+ this.component2NameTextBox.Location = new System.Drawing.Point(77, 44);
+ this.component2NameTextBox.Name = "component2NameTextBox";
+ this.component2NameTextBox.Size = new System.Drawing.Size(299, 20);
+ this.component2NameTextBox.TabIndex = 3;
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(11, 47);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(35, 13);
+ this.label3.TabIndex = 2;
+ this.label3.Text = "Name";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(11, 22);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(32, 13);
+ this.label4.TabIndex = 1;
+ this.label4.Text = "Class";
+ //
+ // component2ClassNameComboBox
+ //
+ this.component2ClassNameComboBox.FormattingEnabled = true;
+ this.component2ClassNameComboBox.Location = new System.Drawing.Point(77, 19);
+ this.component2ClassNameComboBox.Name = "component2ClassNameComboBox";
+ this.component2ClassNameComboBox.Size = new System.Drawing.Size(299, 21);
+ this.component2ClassNameComboBox.TabIndex = 0;
+ //
+ // radioButton24
+ //
+ this.radioButton24.AutoSize = true;
+ this.radioButton24.Location = new System.Drawing.Point(212, 118);
+ this.radioButton24.Name = "radioButton24";
+ this.radioButton24.Size = new System.Drawing.Size(51, 17);
+ this.radioButton24.TabIndex = 9;
+ this.radioButton24.TabStop = true;
+ this.radioButton24.Text = "spare";
+ this.radioButton24.UseVisualStyleBackColor = true;
+ this.radioButton24.CheckedChanged += new System.EventHandler(this.radioButton24_CheckedChanged);
+ //
+ // radioButton23
+ //
+ this.radioButton23.AutoSize = true;
+ this.radioButton23.Location = new System.Drawing.Point(212, 95);
+ this.radioButton23.Name = "radioButton23";
+ this.radioButton23.Size = new System.Drawing.Size(51, 17);
+ this.radioButton23.TabIndex = 8;
+ this.radioButton23.TabStop = true;
+ this.radioButton23.Text = "spare";
+ this.radioButton23.UseVisualStyleBackColor = true;
+ this.radioButton23.CheckedChanged += new System.EventHandler(this.radioButton23_CheckedChanged);
+ //
+ // radioButton22
+ //
+ this.radioButton22.AutoSize = true;
+ this.radioButton22.Location = new System.Drawing.Point(212, 72);
+ this.radioButton22.Name = "radioButton22";
+ this.radioButton22.Size = new System.Drawing.Size(51, 17);
+ this.radioButton22.TabIndex = 7;
+ this.radioButton22.TabStop = true;
+ this.radioButton22.Text = "spare";
+ this.radioButton22.UseVisualStyleBackColor = true;
+ this.radioButton22.CheckedChanged += new System.EventHandler(this.radioButton22_CheckedChanged);
+ //
+ // radioButton21
+ //
+ this.radioButton21.AutoSize = true;
+ this.radioButton21.Location = new System.Drawing.Point(212, 49);
+ this.radioButton21.Name = "radioButton21";
+ this.radioButton21.Size = new System.Drawing.Size(106, 17);
+ this.radioButton21.TabIndex = 6;
+ this.radioButton21.TabStop = true;
+ this.radioButton21.Text = "ReadPressureOp";
+ this.radioButton21.UseVisualStyleBackColor = true;
+ this.radioButton21.CheckedChanged += new System.EventHandler(this.radioButton21_CheckedChanged);
+ //
+ // groupBox4
+ //
+ this.groupBox4.Controls.Add(this.radioButton34);
+ this.groupBox4.Controls.Add(this.radioButton33);
+ this.groupBox4.Controls.Add(this.radioButton32);
+ this.groupBox4.Controls.Add(this.radioButton31);
+ this.groupBox4.Controls.Add(this.radioButton24);
+ this.groupBox4.Controls.Add(this.radioButton4);
+ this.groupBox4.Controls.Add(this.radioButton23);
+ this.groupBox4.Controls.Add(this.radioButton0);
+ this.groupBox4.Controls.Add(this.radioButton22);
+ this.groupBox4.Controls.Add(this.radioButton3);
+ this.groupBox4.Controls.Add(this.radioButton21);
+ this.groupBox4.Controls.Add(this.radioButton1);
+ this.groupBox4.Controls.Add(this.radioButton2);
+ this.groupBox4.Location = new System.Drawing.Point(12, 349);
+ this.groupBox4.Name = "groupBox4";
+ this.groupBox4.Size = new System.Drawing.Size(581, 145);
+ this.groupBox4.TabIndex = 12;
+ this.groupBox4.TabStop = false;
+ this.groupBox4.Text = "Operations";
+ //
+ // radioButton34
+ //
+ this.radioButton34.AutoSize = true;
+ this.radioButton34.Location = new System.Drawing.Point(405, 118);
+ this.radioButton34.Name = "radioButton34";
+ this.radioButton34.Size = new System.Drawing.Size(51, 17);
+ this.radioButton34.TabIndex = 13;
+ this.radioButton34.TabStop = true;
+ this.radioButton34.Text = "spare";
+ this.radioButton34.UseVisualStyleBackColor = true;
+ this.radioButton34.CheckedChanged += new System.EventHandler(this.radioButton34_CheckedChanged);
+ //
+ // radioButton33
+ //
+ this.radioButton33.AutoSize = true;
+ this.radioButton33.Location = new System.Drawing.Point(405, 95);
+ this.radioButton33.Name = "radioButton33";
+ this.radioButton33.Size = new System.Drawing.Size(51, 17);
+ this.radioButton33.TabIndex = 12;
+ this.radioButton33.TabStop = true;
+ this.radioButton33.Text = "spare";
+ this.radioButton33.UseVisualStyleBackColor = true;
+ this.radioButton33.CheckedChanged += new System.EventHandler(this.radioButton33_CheckedChanged);
+ //
+ // radioButton32
+ //
+ this.radioButton32.AutoSize = true;
+ this.radioButton32.Location = new System.Drawing.Point(405, 72);
+ this.radioButton32.Name = "radioButton32";
+ this.radioButton32.Size = new System.Drawing.Size(51, 17);
+ this.radioButton32.TabIndex = 11;
+ this.radioButton32.TabStop = true;
+ this.radioButton32.Text = "spare";
+ this.radioButton32.UseVisualStyleBackColor = true;
+ this.radioButton32.CheckedChanged += new System.EventHandler(this.radioButton32_CheckedChanged);
+ //
+ // radioButton31
+ //
+ this.radioButton31.AutoSize = true;
+ this.radioButton31.Location = new System.Drawing.Point(405, 49);
+ this.radioButton31.Name = "radioButton31";
+ this.radioButton31.Size = new System.Drawing.Size(106, 17);
+ this.radioButton31.TabIndex = 10;
+ this.radioButton31.TabStop = true;
+ this.radioButton31.Text = "ReadPressureOp";
+ this.radioButton31.UseVisualStyleBackColor = true;
+ this.radioButton31.CheckedChanged += new System.EventHandler(this.radioButton31_CheckedChanged);
+ //
+ // groupBox5
+ //
+ this.groupBox5.Controls.Add(this.configureComponent3Button);
+ this.groupBox5.Controls.Add(this.component3NameTextBox);
+ this.groupBox5.Controls.Add(this.label5);
+ this.groupBox5.Controls.Add(this.label6);
+ this.groupBox5.Controls.Add(this.component3ClassNameComboBox);
+ this.groupBox5.Location = new System.Drawing.Point(12, 255);
+ this.groupBox5.Name = "groupBox5";
+ this.groupBox5.Size = new System.Drawing.Size(486, 75);
+ this.groupBox5.TabIndex = 13;
+ this.groupBox5.TabStop = false;
+ this.groupBox5.Text = "Component 3";
+ //
+ // configureComponent3Button
+ //
+ this.configureComponent3Button.Location = new System.Drawing.Point(395, 19);
+ this.configureComponent3Button.Name = "configureComponent3Button";
+ this.configureComponent3Button.Size = new System.Drawing.Size(73, 45);
+ this.configureComponent3Button.TabIndex = 4;
+ this.configureComponent3Button.Text = "Configure";
+ this.configureComponent3Button.UseVisualStyleBackColor = true;
+ this.configureComponent3Button.Click += new System.EventHandler(this.configureComponent3Button_Click);
+ //
+ // component3NameTextBox
+ //
+ this.component3NameTextBox.Enabled = false;
+ this.component3NameTextBox.Location = new System.Drawing.Point(77, 44);
+ this.component3NameTextBox.Name = "component3NameTextBox";
+ this.component3NameTextBox.Size = new System.Drawing.Size(299, 20);
+ this.component3NameTextBox.TabIndex = 3;
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(11, 47);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(35, 13);
+ this.label5.TabIndex = 2;
+ this.label5.Text = "Name";
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(11, 22);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(32, 13);
+ this.label6.TabIndex = 1;
+ this.label6.Text = "Class";
+ //
+ // component3ClassNameComboBox
+ //
+ this.component3ClassNameComboBox.FormattingEnabled = true;
+ this.component3ClassNameComboBox.Location = new System.Drawing.Point(77, 19);
+ this.component3ClassNameComboBox.Name = "component3ClassNameComboBox";
+ this.component3ClassNameComboBox.Size = new System.Drawing.Size(299, 21);
+ this.component3ClassNameComboBox.TabIndex = 0;
+ //
+ // DeviceTestDlg
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(613, 502);
+ this.Controls.Add(this.groupBox5);
+ this.Controls.Add(this.groupBox4);
+ this.Controls.Add(this.groupBox3);
+ this.Controls.Add(this.stopButton);
+ this.Controls.Add(this.groupBox2);
+ this.Controls.Add(this.startButton);
+ this.Controls.Add(this.groupBox1);
+ this.Name = "DeviceTestDlg";
+ this.Text = "Device test";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DeviceTestDlg_FormClosing);
+ this.Load += new System.EventHandler(this.DeviceTestDlg_Load);
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ this.groupBox2.ResumeLayout(false);
+ this.groupBox2.PerformLayout();
+ this.groupBox3.ResumeLayout(false);
+ this.groupBox3.PerformLayout();
+ this.groupBox4.ResumeLayout(false);
+ this.groupBox4.PerformLayout();
+ this.groupBox5.ResumeLayout(false);
+ this.groupBox5.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ComboBox parentClassNameComboBox;
+ private System.Windows.Forms.Label classLabel;
+ private System.Windows.Forms.Label nameLabel;
+ private System.Windows.Forms.TextBox parentNameTextBox;
+ private System.Windows.Forms.Button configureParentButton;
+ private System.Windows.Forms.Button startButton;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.Button configureComponent1Button;
+ private System.Windows.Forms.TextBox componentNameTextBox;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.ComboBox component1ClassNameComboBox;
+ private System.Windows.Forms.RadioButton radioButton4;
+ private System.Windows.Forms.RadioButton radioButton3;
+ private System.Windows.Forms.RadioButton radioButton2;
+ private System.Windows.Forms.RadioButton radioButton1;
+ private System.Windows.Forms.RadioButton radioButton0;
+ private System.Windows.Forms.Button stopButton;
+ private System.Windows.Forms.GroupBox groupBox3;
+ private System.Windows.Forms.RadioButton radioButton24;
+ private System.Windows.Forms.RadioButton radioButton23;
+ private System.Windows.Forms.RadioButton radioButton22;
+ private System.Windows.Forms.RadioButton radioButton21;
+ private System.Windows.Forms.Button configureComponent2Button;
+ private System.Windows.Forms.TextBox component2NameTextBox;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.ComboBox component2ClassNameComboBox;
+ private System.Windows.Forms.GroupBox groupBox4;
+ private System.Windows.Forms.GroupBox groupBox5;
+ private System.Windows.Forms.Button configureComponent3Button;
+ private System.Windows.Forms.TextBox component3NameTextBox;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.ComboBox component3ClassNameComboBox;
+ private System.Windows.Forms.RadioButton radioButton34;
+ private System.Windows.Forms.RadioButton radioButton33;
+ private System.Windows.Forms.RadioButton radioButton32;
+ private System.Windows.Forms.RadioButton radioButton31;
+ }
+}
+
diff --git a/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.cs b/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.cs
new file mode 100644
index 00000000..57be4d3f
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.cs
@@ -0,0 +1,835 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+using TBF.BenchControl;
+using TBF.BenchControl.Generic;
+using TBF.BenchControl.GenericDevices;
+using System.Xml.Serialization;
+
+
+namespace DeviceTest
+{
+ public partial class DeviceTestDlg : Form
+ {
+ IList compClasses;
+
+ IComponentFactory parentFactory;
+ IComponentFactory component1Factory;
+ IComponentFactory component2Factory;
+ IComponentFactory component3Factory;
+
+ IComponentCfg parentCfg;
+ IComponentCfg component1Cfg;
+ IComponentCfg component2Cfg;
+ IComponentCfg component3Cfg;
+
+ static IList tbfDevices;
+ static IList tbfComponents;
+ static TBF.BenchControl.Generic.IComponent tbfComponent1forOp;
+ static TBF.BenchControl.Generic.IComponent tbfComponent2forOp;
+ static TBF.BenchControl.Generic.IComponent tbfComponent3forOp;
+
+ static Thread workerThread;
+ static bool workerThreadRunning;
+
+
+ static int activeOperationId;
+
+ static IOperation operation1;
+ static IOperation operation2;
+ static IOperation operation3;
+ static IOperation operation4;
+
+ static IOperation operation21;
+ static IOperation operation22;
+ static IOperation operation23;
+ static IOperation operation24;
+
+ static IOperation operation31;
+ static IOperation operation32;
+ static IOperation operation33;
+ static IOperation operation34;
+
+
+ static TBF.Boxes.FloatBox floatBox;
+ static Event evnt;
+
+
+ static DeviceTestDlg()
+ {
+ floatBox = new TBF.Boxes.FloatBox();
+ floatBox.Format = "F2";
+ }
+
+ public DeviceTestDlg()
+ {
+ InitializeComponent();
+ radioButton0.Checked = true;
+ stopButton.Enabled = false;
+
+ compClasses = new List();
+ foreach (var componentFactory in TbfComponents.Factories)
+ {
+ compClasses.Add(componentFactory.ClassName);
+ }
+
+ tbfComponents = new List();
+ tbfDevices = new List();
+ }
+
+ private void DeviceTestDlg_Load(object sender, EventArgs e)
+ {
+
+ foreach (var clName in compClasses)
+ {
+ parentClassNameComboBox.Items.Add(clName);
+ component1ClassNameComboBox.Items.Add(clName);
+ component2ClassNameComboBox.Items.Add(clName);
+ component3ClassNameComboBox.Items.Add(clName);
+ }
+
+ try
+ {
+ if (!string.IsNullOrEmpty(Program.LocalSettings.ParentClassName) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.ParentName) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.ParentSettings))
+ {
+ FactoryFromClassName(Program.LocalSettings.ParentClassName, ref parentFactory);
+
+ using (var reader = new StringReader(Program.LocalSettings.ParentSettings))
+ {
+ IComponentCfg config = (IComponentCfg)(new XmlSerializer(parentFactory.DefaultConfig().GetType())).Deserialize(reader);
+ config.Name = Program.LocalSettings.ParentName;
+ config.ParentName = string.Empty;
+ config.ItemNr = 0;
+ config.DebugLevel = Config.Entities.DebugMode.Normal;
+ config.LogLevel = Config.Entities.LogLevel.Debug;
+ config.Corrections = null;
+ config.Factory = parentFactory;
+ parentCfg = config;
+ }
+
+ parentClassNameComboBox.Text = Program.LocalSettings.ParentClassName;
+ parentNameTextBox.Text = Program.LocalSettings.ParentName;
+ }
+ }
+ catch
+ {
+ parentFactory = null;
+ parentCfg = null;
+ parentClassNameComboBox.Text = string.Empty;
+ parentNameTextBox.Text = string.Empty;
+ }
+
+ try
+ {
+ if (!string.IsNullOrEmpty(Program.LocalSettings.ComponentClassName) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.ComponentName) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.ComponentSettings))
+ {
+ FactoryFromClassName(Program.LocalSettings.ComponentClassName, ref component1Factory);
+
+ using (var reader = new StringReader(Program.LocalSettings.ComponentSettings))
+ {
+ IComponentCfg config = (IComponentCfg)(new XmlSerializer(component1Factory.DefaultConfig().GetType())).Deserialize(reader);
+ config.Name = Program.LocalSettings.ComponentName;
+ config.ParentName = string.IsNullOrEmpty(Program.LocalSettings.ComponentParentName) ? string.Empty : Program.LocalSettings.ComponentParentName;
+ config.ItemNr = 1;
+ config.DebugLevel = Config.Entities.DebugMode.Normal;
+ config.LogLevel = Config.Entities.LogLevel.Debug;
+ config.Corrections = null;
+ config.Factory = component1Factory;
+ component1Cfg = config;
+ }
+
+ component1ClassNameComboBox.Text = Program.LocalSettings.ComponentClassName;
+ componentNameTextBox.Text = Program.LocalSettings.ComponentName;
+
+ UpdateOperations(component1ClassNameComboBox.Text);
+ }
+ }
+ catch
+ {
+ component1Factory = null;
+ component1Cfg = null;
+ component1ClassNameComboBox.Text = string.Empty;
+ componentNameTextBox.Text = string.Empty;
+ }
+
+ try
+ {
+ if (!string.IsNullOrEmpty(Program.LocalSettings.Component2ClassName) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.Component2Name) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.Component2Settings))
+ {
+ FactoryFromClassName(Program.LocalSettings.Component2ClassName, ref component2Factory);
+
+ using (var reader = new StringReader(Program.LocalSettings.Component2Settings))
+ {
+ IComponentCfg config = (IComponentCfg)(new XmlSerializer(component2Factory.DefaultConfig().GetType())).Deserialize(reader);
+ config.Name = Program.LocalSettings.Component2Name;
+ config.ParentName = string.IsNullOrEmpty(Program.LocalSettings.Component2ParentName) ? string.Empty : Program.LocalSettings.Component2ParentName;
+ config.ItemNr = 2;
+ config.DebugLevel = Config.Entities.DebugMode.Normal;
+ config.LogLevel = Config.Entities.LogLevel.Debug;
+ config.Corrections = null;
+ config.Factory = component2Factory;
+ component2Cfg = config;
+ }
+
+ component2ClassNameComboBox.Text = Program.LocalSettings.Component2ClassName;
+ component2NameTextBox.Text = Program.LocalSettings.Component2Name;
+
+ UpdateOperations2(component2ClassNameComboBox.Text);
+ }
+ }
+ catch
+ {
+ component2Factory = null;
+ component2Cfg = null;
+ component2ClassNameComboBox.Text = string.Empty;
+ component2NameTextBox.Text = string.Empty;
+ }
+
+ try
+ {
+ if (!string.IsNullOrEmpty(Program.LocalSettings.Component3ClassName) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.Component3Name) &&
+ !string.IsNullOrEmpty(Program.LocalSettings.Component3Settings))
+ {
+ FactoryFromClassName(Program.LocalSettings.Component3ClassName, ref component3Factory);
+
+ using (var reader = new StringReader(Program.LocalSettings.Component3Settings))
+ {
+ IComponentCfg config = (IComponentCfg)(new XmlSerializer(component3Factory.DefaultConfig().GetType())).Deserialize(reader);
+ config.Name = Program.LocalSettings.Component3Name;
+ config.ParentName = string.IsNullOrEmpty(Program.LocalSettings.Component3ParentName) ? string.Empty : Program.LocalSettings.Component3ParentName;
+ config.ItemNr = 3;
+ config.DebugLevel = Config.Entities.DebugMode.Normal;
+ config.LogLevel = Config.Entities.LogLevel.Debug;
+ config.Corrections = null;
+ config.Factory = component3Factory;
+ component3Cfg = config;
+ }
+
+ component3ClassNameComboBox.Text = Program.LocalSettings.Component3ClassName;
+ component3NameTextBox.Text = Program.LocalSettings.Component3Name;
+
+ UpdateOperations3(component3ClassNameComboBox.Text);
+ }
+ }
+ catch
+ {
+ component3Factory = null;
+ component3Cfg = null;
+ component3ClassNameComboBox.Text = string.Empty;
+ component3NameTextBox.Text = string.Empty;
+ }
+ }
+
+ void SaveSettings()
+ {
+ Program.LocalSettings.ParentClassName = parentClassNameComboBox.Text;
+ Program.LocalSettings.ParentName = parentNameTextBox.Text;
+ Program.LocalSettings.ParentSettings = (parentCfg != null) ? parentCfg.CreateDbEntity().Parameters : string.Empty;
+
+ Program.LocalSettings.ComponentClassName = component1ClassNameComboBox.Text;
+ Program.LocalSettings.ComponentName = componentNameTextBox.Text;
+ Program.LocalSettings.ComponentParentName = (component1Cfg != null) ? component1Cfg.ParentName : string.Empty;
+ Program.LocalSettings.ComponentSettings = (component1Cfg != null) ? component1Cfg.CreateDbEntity().Parameters : string.Empty;
+
+ Program.LocalSettings.Component2ClassName = component2ClassNameComboBox.Text;
+ Program.LocalSettings.Component2Name = component2NameTextBox.Text;
+ Program.LocalSettings.Component2ParentName = (component2Cfg != null) ? component2Cfg.ParentName : string.Empty;
+ Program.LocalSettings.Component2Settings = (component2Cfg != null) ? component2Cfg.CreateDbEntity().Parameters : string.Empty;
+
+ Program.LocalSettings.Component3ClassName = component3ClassNameComboBox.Text;
+ Program.LocalSettings.Component3Name = component3NameTextBox.Text;
+ Program.LocalSettings.Component3ParentName = (component3Cfg != null) ? component3Cfg.ParentName : string.Empty;
+ Program.LocalSettings.Component3Settings = (component3Cfg != null) ? component3Cfg.CreateDbEntity().Parameters : string.Empty;
+
+ Program.LocalSettings.Save();
+ }
+
+
+ void UpdateOperations(string className)
+ {
+ if (className == "Keithley.TempMeter") radioButton1.Text = "ReadPressureOp";
+ else if (className == "Network.Camera.CLP1611") radioButton1.Text = "Livestream";
+ else if (className == "Network.Camera.Roi") radioButton1.Text = "RoiDetection";
+ else if (className == "Modbus.Easytherm")
+ {
+ radioButton1.Text = "SetTemperature(10)";
+ radioButton2.Text = "SetTemperature(20)";
+ }
+ else if (className == "Modbus.TankSelector")
+ {
+ radioButton1.Text = "SelectTank 1";
+ radioButton2.Text = "SelectTank 2";
+ radioButton3.Text = "SelectTank 3";
+ radioButton4.Text = "SelectTank -";
+ }
+ else radioButton1.Text = "spare";
+ }
+ ///
+ void UpdateOperations2(string className)
+ {
+ if (className == "Keithley.TempMeter") radioButton21.Text = "ReadPressureOp";
+ else if (className == "Network.Camera.CLP1611") radioButton21.Text = "Livestream";
+ else if (className == "Network.Camera.Roi") radioButton21.Text = "RoiDetection";
+ else if (className == "Modbus.Easytherm")
+ {
+ radioButton21.Text = "SetTemperature(10)";
+ radioButton22.Text = "SetTemperature(20)";
+ }
+ else if (className == "Modbus.TankSelector")
+ {
+ radioButton21.Text = "SelectTank 1";
+ radioButton22.Text = "SelectTank 2";
+ radioButton23.Text = "SelectTank 3";
+ radioButton24.Text = "SelectTank -";
+ }
+ else radioButton21.Text = "spare";
+ }
+ ///
+ void UpdateOperations3(string className)
+ {
+ if (className == "Keithley.TempMeter") radioButton31.Text = "ReadPressureOp";
+ else if (className == "Network.Camera.CLP1611") radioButton31.Text = "Livestream";
+ else if (className == "Network.Camera.Roi") radioButton31.Text = "RoiDetection";
+ else if (className == "Modbus.Easytherm")
+ {
+ radioButton31.Text = "SetTemperature(10)";
+ radioButton32.Text = "SetTemperature(20)";
+ }
+ else if (className == "Modbus.TankSelector")
+ {
+ radioButton31.Text = "SelectTank 1";
+ radioButton32.Text = "SelectTank 2";
+ radioButton33.Text = "SelectTank 3";
+ radioButton34.Text = "SelectTank -";
+ }
+ else radioButton31.Text = "spare";
+ }
+
+
+ int GetActiveOperationId()
+ {
+ if (radioButton1.Checked) { return 1; }
+ else if (radioButton2.Checked) { return 2; }
+ else if (radioButton3.Checked) { return 3; }
+ else if (radioButton4.Checked) { return 4; }
+ else if (radioButton21.Checked) { return 21; }
+ else if (radioButton22.Checked) { return 22; }
+ else if (radioButton23.Checked) { return 23; }
+ else if (radioButton24.Checked) { return 24; }
+ else if (radioButton31.Checked) { return 31; }
+ else if (radioButton32.Checked) { return 32; }
+ else if (radioButton33.Checked) { return 33; }
+ else if (radioButton34.Checked) { return 34; }
+ else return 0; /// stopOperationRadioButton.Checked
+ }
+
+
+ private void radioButton0_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton1_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton2_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton3_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton4_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ ///
+ private void radioButton21_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton22_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton23_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton24_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ ///
+ private void radioButton31_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton32_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton33_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+ private void radioButton34_CheckedChanged(object sender, EventArgs e) { activeOperationId = GetActiveOperationId(); }
+
+
+ ///
+ /// Updates component factory
+ ///
+ /// Component class name
+ /// Reference to a factory
+ /// true when factory changed
+ bool FactoryFromClassName(string className, ref IComponentFactory factory)
+ {
+ foreach (var fac in TbfComponents.Factories)
+ {
+ if (className == fac.ClassName)
+ {
+ if (factory != fac)
+ {
+ factory = fac;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ if (factory != null)
+ {
+ factory = null;
+ return true;
+ }
+
+ return false;
+ }
+
+ private void configureParentButton_Click(object sender, EventArgs e)
+ {
+ bool factoryChanged = FactoryFromClassName(parentClassNameComboBox.Text, ref parentFactory);
+ if (parentFactory == null)
+ {
+ MessageBox.Show("Invalid parent class", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ return;
+ }
+
+ if (factoryChanged || parentCfg == null)
+ {
+ parentCfg = parentFactory.DefaultConfig();
+ }
+ IComponentCfgCtrl cfgControl = parentCfg.GetControl();
+ cfgControl.Config = parentCfg;
+ cfgControl.Config.ItemNr = 0;
+
+ TBF.ComponentParametersDlg cfgForm = new TBF.ComponentParametersDlg();
+ cfgForm.TbfComponents = new List();
+
+ cfgForm.ComponentCfgCtrl = cfgControl;
+ cfgForm.UnlockAfterStart = true;
+ DialogResult dr = cfgForm.ShowDialog();
+ if (dr != DialogResult.OK) return;
+
+ parentNameTextBox.Text = parentCfg.Name;
+ }
+
+
+ private void configureComponent1Button_Click(object sender, EventArgs e)
+ {
+ bool factoryChanged = FactoryFromClassName(component1ClassNameComboBox.Text, ref component1Factory);
+ if (component1Factory == null)
+ {
+ MessageBox.Show("Invalid component class", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ return;
+ }
+
+ if (factoryChanged || component1Cfg == null)
+ {
+ component1Cfg = component1Factory.DefaultConfig();
+ }
+ IComponentCfgCtrl cfgControl = component1Cfg.GetControl();
+ cfgControl.Config = component1Cfg;
+ cfgControl.Config.ItemNr = 1;
+
+ TBF.ComponentParametersDlg cfgForm = new TBF.ComponentParametersDlg();
+ ///
+ IList compEntities = new List();
+ if (parentFactory != null && parentCfg != null) compEntities.Add(parentCfg.CreateDbEntity());
+ cfgForm.TbfComponents = compEntities;
+
+ cfgForm.ComponentCfgCtrl = cfgControl;
+ cfgForm.UnlockAfterStart = true;
+ DialogResult dr = cfgForm.ShowDialog();
+ if (dr != DialogResult.OK) return;
+
+ componentNameTextBox.Text = component1Cfg.Name;
+
+ UpdateOperations(component1ClassNameComboBox.Text);
+ }
+
+
+ private void configureComponent2Button_Click(object sender, EventArgs e)
+ {
+ bool factoryChanged = FactoryFromClassName(component2ClassNameComboBox.Text, ref component2Factory);
+ if (component2Factory == null)
+ {
+ MessageBox.Show("Invalid component class", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ return;
+ }
+
+ if (factoryChanged || component2Cfg == null)
+ {
+ component2Cfg = component2Factory.DefaultConfig();
+ }
+ IComponentCfgCtrl cfgControl = component2Cfg.GetControl();
+ cfgControl.Config = component2Cfg;
+ cfgControl.Config.ItemNr = 1;
+
+ TBF.ComponentParametersDlg cfgForm = new TBF.ComponentParametersDlg();
+ ///
+ IList compEntities = new List();
+ if (parentFactory != null && parentCfg != null) compEntities.Add(parentCfg.CreateDbEntity());
+ if (component1Factory != null && component1Cfg != null) compEntities.Add(component1Cfg.CreateDbEntity());
+ cfgForm.TbfComponents = compEntities;
+
+ cfgForm.ComponentCfgCtrl = cfgControl;
+ cfgForm.UnlockAfterStart = true;
+ DialogResult dr = cfgForm.ShowDialog();
+ if (dr != DialogResult.OK) return;
+
+ component2NameTextBox.Text = component2Cfg.Name;
+
+ UpdateOperations2(component2ClassNameComboBox.Text);
+ }
+
+
+ private void configureComponent3Button_Click(object sender, EventArgs e)
+ {
+ bool factoryChanged = FactoryFromClassName(component3ClassNameComboBox.Text, ref component3Factory);
+ if (component3Factory == null)
+ {
+ MessageBox.Show("Invalid component class", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ return;
+ }
+
+ if (factoryChanged || component3Cfg == null)
+ {
+ component3Cfg = component3Factory.DefaultConfig();
+ }
+ IComponentCfgCtrl cfgControl = component3Cfg.GetControl();
+ cfgControl.Config = component3Cfg;
+ cfgControl.Config.ItemNr = 1;
+
+ TBF.ComponentParametersDlg cfgForm = new TBF.ComponentParametersDlg();
+ ///
+ IList compEntities = new List();
+ if (parentFactory != null && parentCfg != null) compEntities.Add(parentCfg.CreateDbEntity());
+ if (component1Factory != null && component1Cfg != null) compEntities.Add(component1Cfg.CreateDbEntity());
+ if (component2Factory != null && component2Cfg != null) compEntities.Add(component2Cfg.CreateDbEntity());
+ cfgForm.TbfComponents = compEntities;
+
+ cfgForm.ComponentCfgCtrl = cfgControl;
+ cfgForm.UnlockAfterStart = true;
+ DialogResult dr = cfgForm.ShowDialog();
+ if (dr != DialogResult.OK) return;
+
+ component3NameTextBox.Text = component3Cfg.Name;
+
+ UpdateOperations3(component3ClassNameComboBox.Text);
+ }
+
+
+ private void startButton_Click(object sender, EventArgs e)
+ {
+ tbfComponents.Clear();
+ tbfDevices.Clear();
+ tbfComponent1forOp = null;
+ operation1 = null;
+ operation2 = null;
+ operation3 = null;
+ operation4 = null;
+ tbfComponent2forOp = null;
+ operation21 = null;
+ operation22 = null;
+ operation23 = null;
+ operation24 = null;
+ tbfComponent3forOp = null;
+ operation31 = null;
+ operation32 = null;
+ operation33 = null;
+ operation34 = null;
+ workerThreadRunning = false;
+
+ string initializedDeviceName = "none";
+ try
+ {
+ if (parentFactory != null && parentCfg != null)
+ {
+ TBF.BenchControl.Generic.IComponent component = parentFactory.GetComponent(parentCfg, tbfComponents);
+ tbfComponents.Add(component);
+ IDevice dev = component as IDevice;
+ if (dev != null)
+ {
+ initializedDeviceName = dev.Name;
+ dev.Initialize();
+ tbfDevices.Add(dev);
+ }
+ }
+ if (component1Factory != null && component1Cfg != null)
+ {
+ TBF.BenchControl.Generic.IComponent component = component1Factory.GetComponent(component1Cfg, tbfComponents);
+ tbfComponents.Add(component);
+ tbfComponent1forOp = component;
+ IDevice dev = component as IDevice;
+ if (dev != null)
+ {
+ initializedDeviceName = dev.Name;
+ dev.Initialize();
+ tbfDevices.Add(dev);
+ }
+ }
+ if (component2Factory != null && component2Cfg != null)
+ {
+ TBF.BenchControl.Generic.IComponent component2 = component2Factory.GetComponent(component2Cfg, tbfComponents);
+ tbfComponents.Add(component2);
+ tbfComponent2forOp = component2;
+ IDevice dev = component2 as IDevice;
+ if (dev != null)
+ {
+ initializedDeviceName = dev.Name;
+ dev.Initialize();
+ tbfDevices.Add(dev);
+ }
+ }
+ if (component3Factory != null && component3Cfg != null)
+ {
+ TBF.BenchControl.Generic.IComponent component3 = component3Factory.GetComponent(component3Cfg, tbfComponents);
+ tbfComponents.Add(component3);
+ tbfComponent3forOp = component3;
+ IDevice dev = component3 as IDevice;
+ if (dev != null)
+ {
+ initializedDeviceName = dev.Name;
+ dev.Initialize();
+ tbfDevices.Add(dev);
+ }
+ }
+
+ if (tbfComponents.Count == 0) throw new Exception("There are no components");
+
+ SaveSettings(); /// Save settings after successful initialization
+
+ workerThread = new Thread(Worker);
+ workerThread.CurrentCulture = Thread.CurrentThread.CurrentCulture;
+ workerThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
+ workerThreadRunning = true;
+ workerThread.Start();
+
+ startButton.Enabled = false;
+ stopButton.Enabled = true;
+ configureComponent2Button.Enabled = false;
+ configureComponent1Button.Enabled = false;
+ configureParentButton.Enabled = false;
+ }
+ catch (Exception exc)
+ {
+ workerThreadRunning = false;
+ workerThread = null;
+
+ MessageBox.Show(exc.Message,
+ string.Format("'{0}' initialization failed", initializedDeviceName),
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Exclamation);
+
+ foreach (var dev in tbfDevices) dev.StopDevice();
+ tbfDevices.Clear();
+
+ startButton.Enabled = true;
+ stopButton.Enabled = false;
+ configureComponent2Button.Enabled = true;
+ configureComponent1Button.Enabled = true;
+ configureParentButton.Enabled = true;
+ }
+ }
+
+
+ static void Worker()
+ {
+ int activeOperationLocal = 0;
+ int previousOperation = 0;
+
+
+ if (tbfComponent1forOp is TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter)
+ {
+ operation1 = (tbfComponent1forOp as TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter).ReadPressureOp(ref floatBox);
+ }
+ else if (tbfComponent1forOp is TBF.BenchControl.Network.Camera.CLP1611.Camera)
+ {
+ operation1 = (tbfComponent1forOp as TBF.BenchControl.Network.Camera.CLP1611.Camera).LiveStreamOp(false);
+ operation2 = (tbfComponent1forOp as TBF.BenchControl.Network.Camera.CLP1611.Camera).LiveStreamOp(true);
+ }
+ else if (tbfComponent1forOp is TBF.BenchControl.Network.Camera.Roi.Roi)
+ {
+ operation1 = (tbfComponent1forOp as TBF.BenchControl.Network.Camera.Roi.Roi).RoiDetectionOp();
+ }
+ else if (tbfComponent1forOp is TBF.BenchControl.Modbus.Easytherm.Easytherm)
+ {
+ operation1 = (tbfComponent1forOp as TBF.BenchControl.Modbus.Easytherm.Easytherm).SetTemperatureOp(10);
+ operation2 = (tbfComponent1forOp as TBF.BenchControl.Modbus.Easytherm.Easytherm).SetTemperatureOp(20);
+ }
+ else if (tbfComponent1forOp is TBF.BenchControl.Modbus.TankSelector.TankSelector)
+ {
+ //operation1 = (tbfComponent1forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(1);
+ //operation2 = (tbfComponent1forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(2);
+ //operation3 = (tbfComponent1forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(3);
+ //operation4 = (tbfComponent1forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(0);
+ }
+
+
+ if (tbfComponent2forOp is TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter)
+ {
+ operation21 = (tbfComponent2forOp as TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter).ReadPressureOp(ref floatBox);
+ }
+ else if (tbfComponent2forOp is TBF.BenchControl.Network.Camera.CLP1611.Camera)
+ {
+ operation21 = (tbfComponent2forOp as TBF.BenchControl.Network.Camera.CLP1611.Camera).LiveStreamOp(false);
+ operation22 = (tbfComponent2forOp as TBF.BenchControl.Network.Camera.CLP1611.Camera).LiveStreamOp(true);
+ }
+ else if (tbfComponent2forOp is TBF.BenchControl.Network.Camera.Roi.Roi)
+ {
+ operation21 = (tbfComponent2forOp as TBF.BenchControl.Network.Camera.Roi.Roi).RoiDetectionOp();
+ }
+ else if (tbfComponent2forOp is TBF.BenchControl.Modbus.Easytherm.Easytherm)
+ {
+ operation21 = (tbfComponent1forOp as TBF.BenchControl.Modbus.Easytherm.Easytherm).SetTemperatureOp(10);
+ operation22 = (tbfComponent1forOp as TBF.BenchControl.Modbus.Easytherm.Easytherm).SetTemperatureOp(20);
+ }
+ else if (tbfComponent2forOp is TBF.BenchControl.Modbus.TankSelector.TankSelector)
+ {
+ //operation21 = (tbfComponent2forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(1);
+ //operation22 = (tbfComponent2forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(2);
+ //operation23 = (tbfComponent2forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(3);
+ //operation24 = (tbfComponent2forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(0);
+ }
+
+
+ if (tbfComponent3forOp is TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter)
+ {
+ operation31 = (tbfComponent3forOp as TBF.BenchControl.Modbus.PressureMeter.Meret.PressureMeter).ReadPressureOp(ref floatBox);
+ }
+ else if (tbfComponent3forOp is TBF.BenchControl.Network.Camera.CLP1611.Camera)
+ {
+ operation31 = (tbfComponent3forOp as TBF.BenchControl.Network.Camera.CLP1611.Camera).LiveStreamOp(false);
+ operation33 = (tbfComponent3forOp as TBF.BenchControl.Network.Camera.CLP1611.Camera).LiveStreamOp(true);
+ }
+ else if (tbfComponent3forOp is TBF.BenchControl.Network.Camera.Roi.Roi)
+ {
+ operation31 = (tbfComponent3forOp as TBF.BenchControl.Network.Camera.Roi.Roi).RoiDetectionOp();
+ }
+ else if (tbfComponent3forOp is TBF.BenchControl.Modbus.Easytherm.Easytherm)
+ {
+ operation31 = (tbfComponent1forOp as TBF.BenchControl.Modbus.Easytherm.Easytherm).SetTemperatureOp(10);
+ operation32 = (tbfComponent1forOp as TBF.BenchControl.Modbus.Easytherm.Easytherm).SetTemperatureOp(20);
+ }
+ else if (tbfComponent3forOp is TBF.BenchControl.Modbus.TankSelector.TankSelector)
+ {
+ //operation31 = (tbfComponent3forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(1);
+ //operation32 = (tbfComponent3forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(2);
+ //operation33 = (tbfComponent3forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(3);
+ //operation34 = (tbfComponent3forOp as TBF.BenchControl.Modbus.TankSelector.TankSelector).SelectTankOp(0);
+ }
+
+
+ while (workerThreadRunning)
+ {
+ Thread.Sleep(1000);
+
+ if (workerThreadRunning)
+ {
+ foreach (var d in tbfDevices) d.RunDeviceBefore();
+
+ if (tbfComponent1forOp != null)
+ {
+ previousOperation = activeOperationLocal;
+ activeOperationLocal = activeOperationId;
+ if (previousOperation == 0 && activeOperationLocal != 0)
+ {
+ switch (activeOperationLocal)
+ {
+ case 1: if (operation1 != null) operation1.Start(); Debug.WriteLine("op1.Start()"); break;
+ case 2: if (operation2 != null) operation2.Start(); Debug.WriteLine("op2.Start()"); break;
+ case 3: if (operation3 != null) operation3.Start(); Debug.WriteLine("op3.Start()"); break;
+ case 4: if (operation4 != null) operation4.Start(); Debug.WriteLine("op4.Start()"); break;
+ case 21: if (operation21 != null) operation21.Start(); Debug.WriteLine("op21.Start()"); break;
+ case 22: if (operation22 != null) operation22.Start(); Debug.WriteLine("op22.Start()"); break;
+ case 23: if (operation23 != null) operation23.Start(); Debug.WriteLine("op23.Start()"); break;
+ case 24: if (operation24 != null) operation24.Start(); Debug.WriteLine("op24.Start()"); break;
+ case 31: if (operation31 != null) operation31.Start(); Debug.WriteLine("op31.Start()"); break;
+ case 32: if (operation32 != null) operation32.Start(); Debug.WriteLine("op32.Start()"); break;
+ case 33: if (operation33 != null) operation33.Start(); Debug.WriteLine("op33.Start()"); break;
+ case 34: if (operation34 != null) operation34.Start(); Debug.WriteLine("op34.Start()"); break;
+ }
+ }
+ else if (previousOperation == activeOperationLocal && activeOperationLocal != 0)
+ {
+ switch (activeOperationLocal)
+ {
+ case 1: if (operation1 != null) evnt = operation1.Run(); Debug.WriteLine("op1.Run() -> {0}", evnt); break;
+ case 2: if (operation2 != null) evnt = operation2.Run(); Debug.WriteLine("op2.Run() -> {0}", evnt); break;
+ case 3: if (operation3 != null) evnt = operation3.Run(); Debug.WriteLine("op3.Run() -> {0}", evnt); break;
+ case 4: if (operation4 != null) evnt = operation4.Run(); Debug.WriteLine("op4.Run() -> {0}", evnt); break;
+ case 21: if (operation21 != null) evnt = operation21.Run(); Debug.WriteLine("op21.Run() -> {0}", evnt); break;
+ case 22: if (operation22 != null) evnt = operation22.Run(); Debug.WriteLine("op22.Run() -> {0}", evnt); break;
+ case 23: if (operation23 != null) evnt = operation23.Run(); Debug.WriteLine("op23.Run() -> {0}", evnt); break;
+ case 24: if (operation24 != null) evnt = operation24.Run(); Debug.WriteLine("op24.Run() -> {0}", evnt); break;
+ case 31: if (operation31 != null) evnt = operation31.Run(); Debug.WriteLine("op31.Run() -> {0}", evnt); break;
+ case 32: if (operation32 != null) evnt = operation32.Run(); Debug.WriteLine("op32.Run() -> {0}", evnt); break;
+ case 33: if (operation33 != null) evnt = operation33.Run(); Debug.WriteLine("op33.Run() -> {0}", evnt); break;
+ case 34: if (operation34 != null) evnt = operation34.Run(); Debug.WriteLine("op34.Run() -> {0}", evnt); break;
+ default: evnt = Event.None; break;
+ }
+ }
+ else if (previousOperation != 0 && activeOperationLocal == 0)
+ {
+ switch (previousOperation)
+ {
+ case 1: if (operation1 != null) operation1.Stop(); Debug.WriteLine("op1.Stop()"); break;
+ case 2: if (operation2 != null) operation2.Stop(); Debug.WriteLine("op2.Stop()"); break;
+ case 3: if (operation3 != null) operation3.Stop(); Debug.WriteLine("op3.Stop()"); break;
+ case 4: if (operation4 != null) operation4.Stop(); Debug.WriteLine("op4.Stop()"); break;
+ case 21: if (operation21 != null) operation21.Stop(); Debug.WriteLine("op21.Stop()"); break;
+ case 22: if (operation22 != null) operation22.Stop(); Debug.WriteLine("op22.Stop()"); break;
+ case 23: if (operation23 != null) operation23.Stop(); Debug.WriteLine("op23.Stop()"); break;
+ case 24: if (operation24 != null) operation24.Stop(); Debug.WriteLine("op24.Stop()"); break;
+ case 31: if (operation31 != null) operation31.Stop(); Debug.WriteLine("op31.Stop()"); break;
+ case 32: if (operation32 != null) operation32.Stop(); Debug.WriteLine("op32.Stop()"); break;
+ case 33: if (operation33 != null) operation33.Stop(); Debug.WriteLine("op33.Stop()"); break;
+ case 34: if (operation34 != null) operation34.Stop(); Debug.WriteLine("op34.Stop()"); break;
+ }
+ }
+ }
+
+ foreach (var d in tbfDevices) d.RunDeviceAfter();
+ }
+ }
+
+ foreach (var d in tbfDevices) d.StopDevice();
+ }
+
+ private void stopButton_Click(object sender, EventArgs e)
+ {
+ Cursor = Cursors.WaitCursor;
+
+ workerThreadRunning = false;
+ workerThread.Join(5000);
+ workerThread = null;
+
+ Cursor = Cursors.Default;
+
+ startButton.Enabled = true;
+ stopButton.Enabled = false;
+ configureParentButton.Enabled = true;
+ configureComponent1Button.Enabled = true;
+ configureComponent2Button.Enabled = true;
+ configureComponent3Button.Enabled = true;
+ }
+
+ private void DeviceTestDlg_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ Cursor = Cursors.WaitCursor;
+
+ if (workerThread != null)
+ {
+ workerThreadRunning = false;
+ workerThread.Join(3000);
+ workerThread = null;
+ }
+
+ Cursor = Cursors.Default;
+
+ SaveSettings();
+
+ Cursor = Cursors.Default;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.resx b/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/DeviceTestDlg.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/DeviceTest/LocalSettings.cs b/TBF_V2/Sources/TBF/DeviceTest/LocalSettings.cs
new file mode 100644
index 00000000..08bfaef9
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/LocalSettings.cs
@@ -0,0 +1,126 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace DeviceTest
+{
+ ///
+ /// Class to be serialized to an XML file...
+ ///
+ [XmlRootAttribute("DeviceTest")]
+ public class LocalSettings
+ {
+ public string ParentClassName;
+ public string ParentName;
+ public string ParentSettings;
+
+ public string ComponentClassName;
+ public string ComponentName;
+ public string ComponentParentName;
+ public string ComponentSettings;
+
+ public string Component2ClassName;
+ public string Component2Name;
+ public string Component2ParentName;
+ public string Component2Settings;
+
+ public string Component3ClassName;
+ public string Component3Name;
+ public string Component3ParentName;
+ public string Component3Settings;
+
+ public LocalSettings()
+ {
+ }
+
+ ///
+ /// Load public fields of this class from the XML file.
+ ///
+ /// LocalSettings object or null when Load() fails
+ public static LocalSettings Load(string fileName)
+ {
+ try
+ {
+ using (TextReader reader = new StreamReader(fileName))
+ {
+ LocalSettings ls = (new XmlSerializer(typeof(LocalSettings))).Deserialize(reader) as LocalSettings;
+ // Copy the settings just in case De-serialize() completes OK
+ return ls;
+ }
+ }
+ catch (Exception e)
+ {
+ string msg = e.Message;
+ return null;
+ }
+ }
+
+ ///
+ /// Save public fields of this class to the XML file.
+ ///
+ public void Save()
+ {
+ try
+ {
+ using (TextWriter writer = new StreamWriter(Program.LocalSettingsFileName))
+ {
+ (new XmlSerializer(typeof(LocalSettings))).Serialize(writer, this);
+ }
+ }
+ catch (Exception e)
+ {
+ string msg = e.Message;
+ }
+ }
+
+ ///
+ /// Updates history stored in a string array by a new latest string.
+ ///
+ /// Last entered string
+ /// true = updated and saved
+ public bool UpdateHistory(string lastStrValue, ref string[] history)
+ {
+ const int MaxHistoryLen = 10;
+
+ if (string.IsNullOrEmpty(lastStrValue)) return false;
+
+ int currentHistoryLength = (history != null) ? history.Length : 0;
+
+ int match = -1;
+ for (int i = 0; i < currentHistoryLength; i++)
+ {
+ if (history[i] == lastStrValue)
+ {
+ match = i;
+ break;
+ }
+ }
+
+ if (match >= 0 || currentHistoryLength >= MaxHistoryLen)
+ {
+ /// History does not have to be extended (because of a match) or should not be extended (because of the lenght)
+ if (match < 0) match = currentHistoryLength - 1;
+
+ for (int j = match; j > 0; j--)
+ {
+ history[j] = history[j - 1];
+ }
+ history[0] = lastStrValue;
+ }
+ else
+ {
+ /// History will be extended, new item inserted at the beginning
+ string[] newHistory = new string[currentHistoryLength + 1];
+ newHistory[0] = lastStrValue;
+ for (int j = 1; j <= currentHistoryLength; j++)
+ {
+ newHistory[j] = history[j - 1];
+ }
+ history = newHistory;
+ }
+ Save();
+ return true;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/DeviceTest/Program.cs b/TBF_V2/Sources/TBF/DeviceTest/Program.cs
new file mode 100644
index 00000000..5720fe88
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/Program.cs
@@ -0,0 +1,111 @@
+///
+/// Copyright (c) 2016-2017 Sensus Metering Systems
+///
+using System;
+using System.IO;
+using System.Windows.Forms;
+using log4net;
+
+namespace DeviceTest
+{
+ static class Program
+ {
+ /// Program information
+ public static string Version; /// version string
+ public static DateTime BuildDateTime; /// date and time of program build
+
+ /// log4net
+ static ILog log;
+ const string log4netConfigFName = "log4netConfig.xml";
+
+ /// Local settings
+ public static readonly string LocAppDataDir;
+ public static readonly string LocalSettingsFileName;
+ public static readonly string LocalSettingsBackupName;
+ public static LocalSettings LocalSettings;
+
+ static Program()
+ {
+ /// Program version string
+ System.Reflection.Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly();
+ Version ver = thisAssembly.GetName().Version;
+ Version = string.Format("{0}.{1}.{2}", ver.Major, ver.Minor, ver.Build);
+ BuildDateTime = new System.IO.FileInfo(thisAssembly.Location).LastWriteTime;
+
+ /// Local program configuration directory including the trailing backslash
+ LocAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) +
+ Path.DirectorySeparatorChar + "TestBenchFramework" + Path.DirectorySeparatorChar;
+ LocalSettingsFileName = LocAppDataDir + "DeviceTest.xml";
+ LocalSettingsBackupName = LocAppDataDir + "DeviceTest.backup.xml";
+ }
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ ///
+ /// Load the local settings
+ ///
+ Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsFileName);
+ if (Program.LocalSettings == null)
+ {
+ /// Loading local seetings from regular config file failed. Use the backup
+ Program.LocalSettings = LocalSettings.Load(Program.LocalSettingsBackupName);
+ if (Program.LocalSettings == null)
+ {
+ MessageBox.Show("Na tomto počítači nebol tento program ani raz spustený.\r\nPoužijú sa základné nastavenia.", "Upozornenie", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ Program.LocalSettings = new LocalSettings();
+ Directory.CreateDirectory(LocAppDataDir);
+ Program.LocalSettings.Save();
+ }
+ else
+ {
+ LocalSettings.Save(); /// Save the settings to overwrite the wrong file
+ }
+ }
+ else
+ {
+ /// Loading local seetings from the regular config file was successful. Update the backup
+ File.Copy(Program.LocalSettingsFileName, Program.LocalSettingsBackupName, true);
+ }
+
+ /// Configure and start logging
+ log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(LocAppDataDir + log4netConfigFName));
+ log = LogManager.GetLogger(typeof(Program));
+ log.Fatal("--------------------------------------------------------------------------------");
+ log.Fatal(string.Format("TBF ver.{0}", Version));
+
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+
+ try
+ {
+ DeviceTestDlg dlg = new DeviceTestDlg();
+ Application.Run(dlg);
+ }
+ catch (Exception exc)
+ {
+ LogException(log, "Exception in Application.Run(DeviceTestDlg)", exc);
+ MessageBox.Show("Program havaroval:" +
+ Environment.NewLine + Environment.NewLine + exc.Message +
+ ((exc.InnerException == null) ? string.Empty : (Environment.NewLine + exc.InnerException.Message)) +
+ Environment.NewLine + exc.StackTrace,
+ "Pozor!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ }
+ }
+
+ static void LogException(ILog log, string description, Exception e)
+ {
+ log.FatalFormat("---------------( {0} )---------------", description);
+ log.FatalFormat("Message : {0}", e.Message);
+ if (e.InnerException != null)
+ {
+ log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
+ }
+ log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace);
+ log.Fatal("--------------------------------------");
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/DeviceTest/Properties/AssemblyInfo.cs b/TBF_V2/Sources/TBF/DeviceTest/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..6fcf0125
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DeviceTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DeviceTest")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a3e8ad92-6617-4f5c-88ce-346d28120fb7")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TBF_V2/Sources/TBF/DeviceTest/Properties/Resources.Designer.cs b/TBF_V2/Sources/TBF/DeviceTest/Properties/Resources.Designer.cs
new file mode 100644
index 00000000..9e195144
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace DeviceTest.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DeviceTest.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/DeviceTest/Properties/Resources.resx b/TBF_V2/Sources/TBF/DeviceTest/Properties/Resources.resx
new file mode 100644
index 00000000..af7dbebb
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/DeviceTest/Properties/Settings.Designer.cs b/TBF_V2/Sources/TBF/DeviceTest/Properties/Settings.Designer.cs
new file mode 100644
index 00000000..14cb028c
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace DeviceTest.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/DeviceTest/Properties/Settings.settings b/TBF_V2/Sources/TBF/DeviceTest/Properties/Settings.settings
new file mode 100644
index 00000000..39645652
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/TBF_V2/Sources/TBF/DeviceTest/app.config b/TBF_V2/Sources/TBF/DeviceTest/app.config
new file mode 100644
index 00000000..e3656033
--- /dev/null
+++ b/TBF_V2/Sources/TBF/DeviceTest/app.config
@@ -0,0 +1,3 @@
+
+
+
diff --git a/TBF_V2/Sources/TBF/Dirichlet.Numerics/Dirichlet.Numerics.csproj b/TBF_V2/Sources/TBF/Dirichlet.Numerics/Dirichlet.Numerics.csproj
new file mode 100644
index 00000000..6e1ff9f2
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Dirichlet.Numerics/Dirichlet.Numerics.csproj
@@ -0,0 +1,51 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {439D0878-C76E-452B-B17D-209A89E91D36}
+ Library
+ Properties
+ Dirichlet.Numerics
+ Dirichlet.Numerics
+ v4.0
+ 512
+ Client
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TBF_V2/Sources/TBF/Dirichlet.Numerics/Int128.cs b/TBF_V2/Sources/TBF/Dirichlet.Numerics/Int128.cs
new file mode 100644
index 00000000..8473c9cc
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Dirichlet.Numerics/Int128.cs
@@ -0,0 +1,1753 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Numerics;
+
+namespace Dirichlet.Numerics
+{
+ public struct Int128 : IFormattable, IComparable, IComparable, IEquatable
+ {
+ private UInt128 v;
+
+ private static readonly Int128 minValue = (Int128)((UInt128)1 << 127);
+ private static readonly Int128 maxValue = (Int128)(((UInt128)1 << 127) - 1);
+ private static readonly Int128 zero = (Int128)0;
+ private static readonly Int128 one = (Int128)1;
+ private static readonly Int128 minusOne = (Int128)(-1);
+
+ public static Int128 MinValue { get { return minValue; } }
+ public static Int128 MaxValue { get { return maxValue; } }
+ public static Int128 Zero { get { return zero; } }
+ public static Int128 One { get { return one; } }
+ public static Int128 MinusOne { get { return minusOne; } }
+
+ public static Int128 Parse(string value)
+ {
+ Int128 c;
+ if (!TryParse(value, out c))
+ throw new FormatException();
+ return c;
+ }
+
+ public static bool TryParse(string value, out Int128 result)
+ {
+ return TryParse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(string value, NumberStyles style, IFormatProvider format, out Int128 result)
+ {
+ BigInteger a;
+ if (!BigInteger.TryParse(value, style, format, out a))
+ {
+ result = Int128.Zero;
+ return false;
+ }
+ UInt128.Create(out result.v, a);
+ return true;
+ }
+
+ public Int128(long value)
+ {
+ UInt128.Create(out v, value);
+ }
+
+ public Int128(ulong value)
+ {
+ UInt128.Create(out v, value);
+ }
+
+ public Int128(double value)
+ {
+ UInt128.Create(out v, value);
+ }
+
+ public Int128(decimal value)
+ {
+ UInt128.Create(out v, value);
+ }
+
+ public Int128(BigInteger value)
+ {
+ UInt128.Create(out v, value);
+ }
+
+ public ulong S0 { get { return v.S0; } }
+ public ulong S1 { get { return v.S1; } }
+
+ public bool IsZero { get { return v.IsZero; } }
+ public bool IsOne { get { return v.IsOne; } }
+ public bool IsPowerOfTwo { get { return v.IsPowerOfTwo; } }
+ public bool IsEven { get { return v.IsEven; } }
+ public bool IsNegative { get { return v.S1 > long.MaxValue; } }
+ public int Sign { get { return IsNegative ? -1 : v.Sign; } }
+
+ public override string ToString()
+ {
+ return ((BigInteger)this).ToString();
+ }
+
+ public string ToString(string format)
+ {
+ return ((BigInteger)this).ToString(format);
+ }
+
+ public string ToString(IFormatProvider provider)
+ {
+ return ToString(null, provider);
+ }
+
+ public string ToString(string format, IFormatProvider provider)
+ {
+ return ((BigInteger)this).ToString(format, provider);
+ }
+
+ public static explicit operator Int128(double a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static implicit operator Int128(sbyte a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static implicit operator Int128(byte a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static implicit operator Int128(short a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static implicit operator Int128(ushort a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static implicit operator Int128(int a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static implicit operator Int128(uint a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, (ulong)a);
+ return c;
+ }
+
+ public static implicit operator Int128(long a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static implicit operator Int128(ulong a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static explicit operator Int128(decimal a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static explicit operator Int128(UInt128 a)
+ {
+ Int128 c;
+ c.v = a;
+ return c;
+ }
+
+ public static explicit operator UInt128(Int128 a)
+ {
+ return a.v;
+ }
+
+ public static explicit operator Int128(BigInteger a)
+ {
+ Int128 c;
+ UInt128.Create(out c.v, a);
+ return c;
+ }
+
+ public static explicit operator sbyte(Int128 a)
+ {
+ return (sbyte)a.v.S0;
+ }
+
+ public static explicit operator byte(Int128 a)
+ {
+ return (byte)a.v.S0;
+ }
+
+ public static explicit operator short(Int128 a)
+ {
+ return (short)a.v.S0;
+ }
+
+ public static explicit operator ushort(Int128 a)
+ {
+ return (ushort)a.v.S0;
+ }
+
+ public static explicit operator int(Int128 a)
+ {
+ return (int)a.v.S0;
+ }
+
+ public static explicit operator uint(Int128 a)
+ {
+ return (uint)a.v.S0;
+ }
+
+ public static explicit operator long(Int128 a)
+ {
+ return (long)a.v.S0;
+ }
+
+ public static explicit operator ulong(Int128 a)
+ {
+ return a.v.S0;
+ }
+
+ public static explicit operator decimal(Int128 a)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 c;
+ UInt128.Negate(out c, ref a.v);
+ return -(decimal)c;
+ }
+ return (decimal)a.v;
+ }
+
+ public static implicit operator BigInteger(Int128 a)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 c;
+ UInt128.Negate(out c, ref a.v);
+ return -(BigInteger)c;
+ }
+ return (BigInteger)a.v;
+ }
+
+ public static explicit operator float(Int128 a)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 c;
+ UInt128.Negate(out c, ref a.v);
+ return -UInt128.ConvertToFloat(ref c);
+ }
+ return UInt128.ConvertToFloat(ref a.v);
+ }
+
+ public static explicit operator double(Int128 a)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 c;
+ UInt128.Negate(out c, ref a.v);
+ return -UInt128.ConvertToDouble(ref c);
+ }
+ return UInt128.ConvertToDouble(ref a.v);
+ }
+
+ public static Int128 operator <<(Int128 a, int b)
+ {
+ Int128 c;
+ UInt128.LeftShift(out c.v, ref a.v, b);
+ return c;
+ }
+
+ public static Int128 operator >>(Int128 a, int b)
+ {
+ Int128 c;
+ UInt128.ArithmeticRightShift(out c.v, ref a.v, b);
+ return c;
+ }
+
+ public static Int128 operator &(Int128 a, Int128 b)
+ {
+ Int128 c;
+ UInt128.And(out c.v, ref a.v, ref b.v);
+ return c;
+ }
+
+ public static int operator &(Int128 a, int b)
+ {
+ return (int)(a.v & (uint)b);
+ }
+
+ public static int operator &(int a, Int128 b)
+ {
+ return (int)(b.v & (uint)a);
+ }
+
+ public static long operator &(Int128 a, long b)
+ {
+ return (long)(a.v & (ulong)b);
+ }
+
+ public static long operator &(long a, Int128 b)
+ {
+ return (long)(b.v & (ulong)a);
+ }
+
+ public static Int128 operator |(Int128 a, Int128 b)
+ {
+ Int128 c;
+ UInt128.Or(out c.v, ref a.v, ref b.v);
+ return c;
+ }
+
+ public static Int128 operator ^(Int128 a, Int128 b)
+ {
+ Int128 c;
+ UInt128.ExclusiveOr(out c.v, ref a.v, ref b.v);
+ return c;
+ }
+
+ public static Int128 operator ~(Int128 a)
+ {
+ Int128 c;
+ UInt128.Not(out c.v, ref a.v);
+ return c;
+ }
+
+ public static Int128 operator +(Int128 a, long b)
+ {
+ Int128 c;
+ if (b < 0)
+ UInt128.Subtract(out c.v, ref a.v, (ulong)(-b));
+ else
+ UInt128.Add(out c.v, ref a.v, (ulong)b);
+ return c;
+ }
+
+ public static Int128 operator +(long a, Int128 b)
+ {
+ Int128 c;
+ if (a < 0)
+ UInt128.Subtract(out c.v, ref b.v, (ulong)(-a));
+ else
+ UInt128.Add(out c.v, ref b.v, (ulong)a);
+ return c;
+ }
+
+ public static Int128 operator +(Int128 a, Int128 b)
+ {
+ Int128 c;
+ UInt128.Add(out c.v, ref a.v, ref b.v);
+ return c;
+ }
+
+ public static Int128 operator ++(Int128 a)
+ {
+ Int128 c;
+ UInt128.Add(out c.v, ref a.v, 1);
+ return c;
+ }
+
+ public static Int128 operator -(Int128 a, long b)
+ {
+ Int128 c;
+ if (b < 0)
+ UInt128.Add(out c.v, ref a.v, (ulong)(-b));
+ else
+ UInt128.Subtract(out c.v, ref a.v, (ulong)b);
+ return c;
+ }
+
+ public static Int128 operator -(Int128 a, Int128 b)
+ {
+ Int128 c;
+ UInt128.Subtract(out c.v, ref a.v, ref b.v);
+ return c;
+ }
+
+ public static Int128 operator +(Int128 a)
+ {
+ return a;
+ }
+
+ public static Int128 operator -(Int128 a)
+ {
+ Int128 c;
+ UInt128.Negate(out c.v, ref a.v);
+ return c;
+ }
+
+ public static Int128 operator --(Int128 a)
+ {
+ Int128 c;
+ UInt128.Subtract(out c.v, ref a.v, 1);
+ return c;
+ }
+
+ public static Int128 operator *(Int128 a, int b)
+ {
+ Int128 c;
+ Multiply(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator *(int a, Int128 b)
+ {
+ Int128 c;
+ Multiply(out c, ref b, a);
+ return c;
+ }
+
+ public static Int128 operator *(Int128 a, uint b)
+ {
+ Int128 c;
+ Multiply(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator *(uint a, Int128 b)
+ {
+ Int128 c;
+ Multiply(out c, ref b, a);
+ return c;
+ }
+
+ public static Int128 operator *(Int128 a, long b)
+ {
+ Int128 c;
+ Multiply(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator *(long a, Int128 b)
+ {
+ Int128 c;
+ Multiply(out c, ref b, a);
+ return c;
+ }
+
+ public static Int128 operator *(Int128 a, ulong b)
+ {
+ Int128 c;
+ Multiply(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator *(ulong a, Int128 b)
+ {
+ Int128 c;
+ Multiply(out c, ref b, a);
+ return c;
+ }
+
+ public static Int128 operator *(Int128 a, Int128 b)
+ {
+ Int128 c;
+ Multiply(out c, ref a, ref b);
+ return c;
+ }
+
+ public static Int128 operator /(Int128 a, int b)
+ {
+ Int128 c;
+ Divide(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator /(Int128 a, uint b)
+ {
+ Int128 c;
+ Divide(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator /(Int128 a, long b)
+ {
+ Int128 c;
+ Divide(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator /(Int128 a, ulong b)
+ {
+ Int128 c;
+ Divide(out c, ref a, b);
+ return c;
+ }
+
+ public static Int128 operator /(Int128 a, Int128 b)
+ {
+ Int128 c;
+ Divide(out c, ref a, ref b);
+ return c;
+ }
+
+ public static int operator %(Int128 a, int b)
+ {
+ return Remainder(ref a, b);
+ }
+
+ public static int operator %(Int128 a, uint b)
+ {
+ return Remainder(ref a, b);
+ }
+
+ public static long operator %(Int128 a, long b)
+ {
+ return Remainder(ref a, b);
+ }
+
+ public static long operator %(Int128 a, ulong b)
+ {
+ return Remainder(ref a, b);
+ }
+
+ public static Int128 operator %(Int128 a, Int128 b)
+ {
+ Int128 c;
+ Remainder(out c, ref a, ref b);
+ return c;
+ }
+
+ public static bool operator <(Int128 a, UInt128 b)
+ {
+ return a.CompareTo(b) < 0;
+ }
+
+ public static bool operator <(UInt128 a, Int128 b)
+ {
+ return b.CompareTo(a) > 0;
+ }
+
+ public static bool operator <(Int128 a, Int128 b)
+ {
+ return LessThan(ref a.v, ref b.v);
+ }
+
+ public static bool operator <(Int128 a, int b)
+ {
+ return LessThan(ref a.v, b);
+ }
+
+ public static bool operator <(int a, Int128 b)
+ {
+ return LessThan(a, ref b.v);
+ }
+
+ public static bool operator <(Int128 a, uint b)
+ {
+ return LessThan(ref a.v, b);
+ }
+
+ public static bool operator <(uint a, Int128 b)
+ {
+ return LessThan(a, ref b.v);
+ }
+
+ public static bool operator <(Int128 a, long b)
+ {
+ return LessThan(ref a.v, b);
+ }
+
+ public static bool operator <(long a, Int128 b)
+ {
+ return LessThan(a, ref b.v);
+ }
+
+ public static bool operator <(Int128 a, ulong b)
+ {
+ return LessThan(ref a.v, b);
+ }
+
+ public static bool operator <(ulong a, Int128 b)
+ {
+ return LessThan(a, ref b.v);
+ }
+
+ public static bool operator <=(Int128 a, UInt128 b)
+ {
+ return a.CompareTo(b) <= 0;
+ }
+
+ public static bool operator <=(UInt128 a, Int128 b)
+ {
+ return b.CompareTo(a) >= 0;
+ }
+
+ public static bool operator <=(Int128 a, Int128 b)
+ {
+ return !LessThan(ref b.v, ref a.v);
+ }
+
+ public static bool operator <=(Int128 a, int b)
+ {
+ return !LessThan(b, ref a.v);
+ }
+
+ public static bool operator <=(int a, Int128 b)
+ {
+ return !LessThan(ref b.v, a);
+ }
+
+ public static bool operator <=(Int128 a, uint b)
+ {
+ return !LessThan(b, ref a.v);
+ }
+
+ public static bool operator <=(uint a, Int128 b)
+ {
+ return !LessThan(ref b.v, a);
+ }
+
+ public static bool operator <=(Int128 a, long b)
+ {
+ return !LessThan(b, ref a.v);
+ }
+
+ public static bool operator <=(long a, Int128 b)
+ {
+ return !LessThan(ref b.v, a);
+ }
+
+ public static bool operator <=(Int128 a, ulong b)
+ {
+ return !LessThan(b, ref a.v);
+ }
+
+ public static bool operator <=(ulong a, Int128 b)
+ {
+ return !LessThan(ref b.v, a);
+ }
+
+ public static bool operator >(Int128 a, UInt128 b)
+ {
+ return a.CompareTo(b) > 0;
+ }
+
+ public static bool operator >(UInt128 a, Int128 b)
+ {
+ return b.CompareTo(a) < 0;
+ }
+
+ public static bool operator >(Int128 a, Int128 b)
+ {
+ return LessThan(ref b.v, ref a.v);
+ }
+
+ public static bool operator >(Int128 a, int b)
+ {
+ return LessThan(b, ref a.v);
+ }
+
+ public static bool operator >(int a, Int128 b)
+ {
+ return LessThan(ref b.v, a);
+ }
+
+ public static bool operator >(Int128 a, uint b)
+ {
+ return LessThan(b, ref a.v);
+ }
+
+ public static bool operator >(uint a, Int128 b)
+ {
+ return LessThan(ref b.v, a);
+ }
+
+ public static bool operator >(Int128 a, long b)
+ {
+ return LessThan(b, ref a.v);
+ }
+
+ public static bool operator >(long a, Int128 b)
+ {
+ return LessThan(ref b.v, a);
+ }
+
+ public static bool operator >(Int128 a, ulong b)
+ {
+ return LessThan(b, ref a.v);
+ }
+
+ public static bool operator >(ulong a, Int128 b)
+ {
+ return LessThan(ref b.v, a);
+ }
+
+ public static bool operator >=(Int128 a, UInt128 b)
+ {
+ return a.CompareTo(b) >= 0;
+ }
+
+ public static bool operator >=(UInt128 a, Int128 b)
+ {
+ return b.CompareTo(a) <= 0;
+ }
+
+ public static bool operator >=(Int128 a, Int128 b)
+ {
+ return !LessThan(ref a.v, ref b.v);
+ }
+
+ public static bool operator >=(Int128 a, int b)
+ {
+ return !LessThan(ref a.v, b);
+ }
+
+ public static bool operator >=(int a, Int128 b)
+ {
+ return !LessThan(a, ref b.v);
+ }
+
+ public static bool operator >=(Int128 a, uint b)
+ {
+ return !LessThan(ref a.v, b);
+ }
+
+ public static bool operator >=(uint a, Int128 b)
+ {
+ return !LessThan(a, ref b.v);
+ }
+
+ public static bool operator >=(Int128 a, long b)
+ {
+ return !LessThan(ref a.v, b);
+ }
+
+ public static bool operator >=(long a, Int128 b)
+ {
+ return !LessThan(a, ref b.v);
+ }
+
+ public static bool operator >=(Int128 a, ulong b)
+ {
+ return !LessThan(ref a.v, b);
+ }
+
+ public static bool operator >=(ulong a, Int128 b)
+ {
+ return !LessThan(a, ref b.v);
+ }
+
+ public static bool operator ==(UInt128 a, Int128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator ==(Int128 a, UInt128 b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(Int128 a, Int128 b)
+ {
+ return a.v.Equals(b.v);
+ }
+
+ public static bool operator ==(Int128 a, int b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(int a, Int128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator ==(Int128 a, uint b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(uint a, Int128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator ==(Int128 a, long b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(long a, Int128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator ==(Int128 a, ulong b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(ulong a, Int128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator !=(UInt128 a, Int128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public static bool operator !=(Int128 a, UInt128 b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(Int128 a, Int128 b)
+ {
+ return !a.v.Equals(b.v);
+ }
+
+ public static bool operator !=(Int128 a, int b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(int a, Int128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public static bool operator !=(Int128 a, uint b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(uint a, Int128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public static bool operator !=(Int128 a, long b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(long a, Int128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public static bool operator !=(Int128 a, ulong b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(ulong a, Int128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public int CompareTo(UInt128 other)
+ {
+ if (IsNegative)
+ return -1;
+ return v.CompareTo(other);
+ }
+
+ public int CompareTo(Int128 other)
+ {
+ return SignedCompare(ref v, other.S0, other.S1);
+ }
+
+ public int CompareTo(int other)
+ {
+ return SignedCompare(ref v, (ulong)other, (ulong)(other >> 31));
+ }
+
+ public int CompareTo(uint other)
+ {
+ return SignedCompare(ref v, (ulong)other, 0);
+ }
+
+ public int CompareTo(long other)
+ {
+ return SignedCompare(ref v, (ulong)other, (ulong)(other >> 63));
+ }
+
+ public int CompareTo(ulong other)
+ {
+ return SignedCompare(ref v, other, 0);
+ }
+
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ return 1;
+ if (!(obj is Int128))
+ throw new ArgumentException();
+ return CompareTo((Int128)obj);
+ }
+
+ private static bool LessThan(ref UInt128 a, ref UInt128 b)
+ {
+ var as1 = (long)a.S1;
+ var bs1 = (long)b.S1;
+ if (as1 != bs1)
+ return as1 < bs1;
+ return a.S0 < b.S0;
+ }
+
+ private static bool LessThan(ref UInt128 a, long b)
+ {
+ var as1 = (long)a.S1;
+ var bs1 = b >> 63;
+ if (as1 != bs1)
+ return as1 < bs1;
+ return a.S0 < (ulong)b;
+ }
+
+ private static bool LessThan(long a, ref UInt128 b)
+ {
+ var as1 = a >> 63;
+ var bs1 = (long)b.S1;
+ if (as1 != bs1)
+ return as1 < bs1;
+ return (ulong)a < b.S0;
+ }
+
+ private static bool LessThan(ref UInt128 a, ulong b)
+ {
+ var as1 = (long)a.S1;
+ if (as1 != 0)
+ return as1 < 0;
+ return a.S0 < b;
+ }
+
+ private static bool LessThan(ulong a, ref UInt128 b)
+ {
+ var bs1 = (long)b.S1;
+ if (0 != bs1)
+ return 0 < bs1;
+ return a < b.S0;
+ }
+
+ private static int SignedCompare(ref UInt128 a, ulong bs0, ulong bs1)
+ {
+ var as1 = a.S1;
+ if (as1 != bs1)
+ return ((long)as1).CompareTo((long)bs1);
+ return a.S0.CompareTo(bs0);
+ }
+
+ public bool Equals(UInt128 other)
+ {
+ return !IsNegative && v.Equals(other);
+ }
+
+ public bool Equals(Int128 other)
+ {
+ return v.Equals(other.v);
+ }
+
+ public bool Equals(int other)
+ {
+ if (other < 0)
+ return v.S1 == ulong.MaxValue && v.S0 == (uint)other;
+ return v.S1 == 0 && v.S0 == (uint)other;
+ }
+
+ public bool Equals(uint other)
+ {
+ return v.S1 == 0 && v.S0 == other;
+ }
+
+ public bool Equals(long other)
+ {
+ if (other < 0)
+ return v.S1 == ulong.MaxValue && v.S0 == (ulong)other;
+ return v.S1 == 0 && v.S0 == (ulong)other;
+ }
+
+ public bool Equals(ulong other)
+ {
+ return v.S1 == 0 && v.S0 == other;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is Int128))
+ return false;
+ return Equals((Int128)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return v.GetHashCode();
+ }
+
+ public static void Multiply(out Int128 c, ref Int128 a, int b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b < 0)
+ UInt128.Multiply(out c.v, ref aneg, (uint)(-b));
+ else
+ {
+ UInt128.Multiply(out c.v, ref aneg, (uint)b);
+ UInt128.Negate(ref c.v);
+ }
+ }
+ else
+ {
+ if (b < 0)
+ {
+ UInt128.Multiply(out c.v, ref a.v, (uint)(-b));
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Multiply(out c.v, ref a.v, (uint)b);
+ }
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b);
+ }
+
+ public static void Multiply(out Int128 c, ref Int128 a, uint b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ UInt128.Multiply(out c.v, ref aneg, b);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Multiply(out c.v, ref a.v, b);
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b);
+ }
+
+ public static void Multiply(out Int128 c, ref Int128 a, long b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b < 0)
+ UInt128.Multiply(out c.v, ref aneg, (ulong)(-b));
+ else
+ {
+ UInt128.Multiply(out c.v, ref aneg, (ulong)b);
+ UInt128.Negate(ref c.v);
+ }
+ }
+ else
+ {
+ if (b < 0)
+ {
+ UInt128.Multiply(out c.v, ref a.v, (ulong)(-b));
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Multiply(out c.v, ref a.v, (ulong)b);
+ }
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b);
+ }
+
+ public static void Multiply(out Int128 c, ref Int128 a, ulong b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ UInt128.Multiply(out c.v, ref aneg, b);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Multiply(out c.v, ref a.v, b);
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b);
+ }
+
+ public static void Multiply(out Int128 c, ref Int128 a, ref Int128 b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.Multiply(out c.v, ref aneg, ref bneg);
+ }
+ else
+ {
+ UInt128.Multiply(out c.v, ref aneg, ref b.v);
+ UInt128.Negate(ref c.v);
+ }
+ }
+ else
+ {
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.Multiply(out c.v, ref a.v, ref bneg);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Multiply(out c.v, ref a.v, ref b.v);
+ }
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b);
+ }
+
+ public static void Divide(out Int128 c, ref Int128 a, int b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b < 0)
+ UInt128.Multiply(out c.v, ref aneg, (uint)(-b));
+ else
+ {
+ UInt128.Multiply(out c.v, ref aneg, (uint)b);
+ UInt128.Negate(ref c.v);
+ }
+ }
+ else
+ {
+ if (b < 0)
+ {
+ UInt128.Multiply(out c.v, ref a.v, (uint)(-b));
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Multiply(out c.v, ref a.v, (uint)b);
+ }
+ Debug.Assert((BigInteger)c == (BigInteger)a / (BigInteger)b);
+ }
+
+ public static void Divide(out Int128 c, ref Int128 a, uint b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ UInt128.Divide(out c.v, ref aneg, b);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Divide(out c.v, ref a.v, b);
+ Debug.Assert((BigInteger)c == (BigInteger)a / (BigInteger)b);
+ }
+
+ public static void Divide(out Int128 c, ref Int128 a, long b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b < 0)
+ UInt128.Divide(out c.v, ref aneg, (ulong)(-b));
+ else
+ {
+ UInt128.Divide(out c.v, ref aneg, (ulong)b);
+ UInt128.Negate(ref c.v);
+ }
+ }
+ else
+ {
+ if (b < 0)
+ {
+ UInt128.Divide(out c.v, ref a.v, (ulong)(-b));
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Divide(out c.v, ref a.v, (ulong)b);
+ }
+ Debug.Assert((BigInteger)c == (BigInteger)a / (BigInteger)b);
+ }
+
+ public static void Divide(out Int128 c, ref Int128 a, ulong b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ UInt128.Divide(out c.v, ref aneg, b);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Divide(out c.v, ref a.v, b);
+ Debug.Assert((BigInteger)c == (BigInteger)a / (BigInteger)b);
+ }
+
+ public static void Divide(out Int128 c, ref Int128 a, ref Int128 b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.Divide(out c.v, ref aneg, ref bneg);
+ }
+ else
+ {
+ UInt128.Divide(out c.v, ref aneg, ref b.v);
+ UInt128.Negate(ref c.v);
+ }
+ }
+ else
+ {
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.Divide(out c.v, ref a.v, ref bneg);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Divide(out c.v, ref a.v, ref b.v);
+ }
+ Debug.Assert((BigInteger)c == (BigInteger)a / (BigInteger)b);
+ }
+
+ public static int Remainder(ref Int128 a, int b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b < 0)
+ return (int)UInt128.Remainder(ref aneg, (uint)(-b));
+ else
+ return -(int)UInt128.Remainder(ref aneg, (uint)b);
+ }
+ else
+ {
+ if (b < 0)
+ return -(int)UInt128.Remainder(ref a.v, (uint)(-b));
+ else
+ return (int)UInt128.Remainder(ref a.v, (uint)b);
+ }
+ }
+
+ public static int Remainder(ref Int128 a, uint b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ return -(int)UInt128.Remainder(ref aneg, b);
+ }
+ else
+ return (int)UInt128.Remainder(ref a.v, b);
+ }
+
+ public static long Remainder(ref Int128 a, long b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b < 0)
+ return (long)UInt128.Remainder(ref aneg, (ulong)(-b));
+ else
+ return -(long)UInt128.Remainder(ref aneg, (ulong)b);
+ }
+ else
+ {
+ if (b < 0)
+ return -(long)UInt128.Remainder(ref a.v, (ulong)(-b));
+ else
+ return (long)UInt128.Remainder(ref a.v, (ulong)b);
+ }
+ }
+
+ public static long Remainder(ref Int128 a, ulong b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ return -(long)UInt128.Remainder(ref aneg, b);
+ }
+ else
+ return (long)UInt128.Remainder(ref a.v, b);
+ }
+
+ public static void Remainder(out Int128 c, ref Int128 a, ref Int128 b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.Remainder(out c.v, ref aneg, ref bneg);
+ }
+ else
+ {
+ UInt128.Remainder(out c.v, ref aneg, ref b.v);
+ UInt128.Negate(ref c.v);
+ }
+ }
+ else
+ {
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.Remainder(out c.v, ref a.v, ref bneg);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Remainder(out c.v, ref a.v, ref b.v);
+ }
+ Debug.Assert((BigInteger)c == (BigInteger)a % (BigInteger)b);
+ }
+
+ public static Int128 Abs(Int128 a)
+ {
+ if (!a.IsNegative)
+ return a;
+ Int128 c;
+ UInt128.Negate(out c.v, ref a.v);
+ return c;
+ }
+
+ public static Int128 Square(long a)
+ {
+ if (a < 0)
+ a = -a;
+ Int128 c;
+ UInt128.Square(out c.v, (ulong)a);
+ return c;
+ }
+
+ public static Int128 Square(Int128 a)
+ {
+ Int128 c;
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ UInt128.Square(out c.v, ref aneg);
+ }
+ else
+ UInt128.Square(out c.v, ref a.v);
+ return c;
+ }
+
+ public static Int128 Cube(long a)
+ {
+ Int128 c;
+ if (a < 0)
+ {
+ UInt128.Cube(out c.v, (ulong)(-a));
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Cube(out c.v, (ulong)a);
+ return c;
+ }
+
+ public static Int128 Cube(Int128 a)
+ {
+ Int128 c;
+ if (a < 0)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ UInt128.Cube(out c.v, ref aneg);
+ UInt128.Negate(ref c.v);
+ }
+ else
+ UInt128.Cube(out c.v, ref a.v);
+ return c;
+ }
+
+ public static void Add(ref Int128 a, long b)
+ {
+ if (b < 0)
+ UInt128.Subtract(ref a.v, (ulong)(-b));
+ else
+ UInt128.Add(ref a.v, (ulong)b);
+ }
+
+ public static void Add(ref Int128 a, ref Int128 b)
+ {
+ UInt128.Add(ref a.v, ref b.v);
+ }
+
+ public static void Subtract(ref Int128 a, long b)
+ {
+ if (b < 0)
+ UInt128.Add(ref a.v, (ulong)(-b));
+ else
+ UInt128.Subtract(ref a.v, (ulong)b);
+ }
+
+ public static void Subtract(ref Int128 a, ref Int128 b)
+ {
+ UInt128.Subtract(ref a.v, ref b.v);
+ }
+
+ public static void Add(ref Int128 a, Int128 b)
+ {
+ UInt128.Add(ref a.v, ref b.v);
+ }
+
+ public static void Subtract(ref Int128 a, Int128 b)
+ {
+ UInt128.Subtract(ref a.v, ref b.v);
+ }
+
+ public static void AddProduct(ref Int128 a, ref UInt128 b, int c)
+ {
+ UInt128 product;
+ if (c < 0)
+ {
+ UInt128.Multiply(out product, ref b, (uint)(-c));
+ UInt128.Subtract(ref a.v, ref product);
+ }
+ else
+ {
+ UInt128.Multiply(out product, ref b, (uint)c);
+ UInt128.Add(ref a.v, ref product);
+ }
+ }
+
+ public static void AddProduct(ref Int128 a, ref UInt128 b, long c)
+ {
+ UInt128 product;
+ if (c < 0)
+ {
+ UInt128.Multiply(out product, ref b, (ulong)(-c));
+ UInt128.Subtract(ref a.v, ref product);
+ }
+ else
+ {
+ UInt128.Multiply(out product, ref b, (ulong)c);
+ UInt128.Add(ref a.v, ref product);
+ }
+ }
+
+ public static void SubtractProduct(ref Int128 a, ref UInt128 b, int c)
+ {
+ UInt128 d;
+ if (c < 0)
+ {
+ UInt128.Multiply(out d, ref b, (uint)(-c));
+ UInt128.Add(ref a.v, ref d);
+ }
+ else
+ {
+ UInt128.Multiply(out d, ref b, (uint)c);
+ UInt128.Subtract(ref a.v, ref d);
+ }
+ }
+
+ public static void SubtractProduct(ref Int128 a, ref UInt128 b, long c)
+ {
+ UInt128 d;
+ if (c < 0)
+ {
+ UInt128.Multiply(out d, ref b, (ulong)(-c));
+ UInt128.Add(ref a.v, ref d);
+ }
+ else
+ {
+ UInt128.Multiply(out d, ref b, (ulong)c);
+ UInt128.Subtract(ref a.v, ref d);
+ }
+ }
+
+ public static void AddProduct(ref Int128 a, UInt128 b, int c)
+ {
+ AddProduct(ref a, ref b, c);
+ }
+
+ public static void AddProduct(ref Int128 a, UInt128 b, long c)
+ {
+ AddProduct(ref a, ref b, c);
+ }
+
+ public static void SubtractProduct(ref Int128 a, UInt128 b, int c)
+ {
+ SubtractProduct(ref a, ref b, c);
+ }
+
+ public static void SubtractProduct(ref Int128 a, UInt128 b, long c)
+ {
+ SubtractProduct(ref a, ref b, c);
+ }
+
+ public static void Pow(out Int128 result, ref Int128 value, int exponent)
+ {
+ if (exponent < 0)
+ throw new ArgumentException("exponent must not be negative");
+ if (value.IsNegative)
+ {
+ UInt128 valueneg;
+ UInt128.Negate(out valueneg, ref value.v);
+ if ((exponent & 1) == 0)
+ UInt128.Pow(out result.v, ref valueneg, (uint)exponent);
+ else
+ {
+ UInt128.Pow(out result.v, ref valueneg, (uint)exponent);
+ UInt128.Negate(ref result.v);
+ }
+ }
+ else
+ UInt128.Pow(out result.v, ref value.v, (uint)exponent);
+ }
+
+ public static Int128 Pow(Int128 value, int exponent)
+ {
+ Int128 result;
+ Pow(out result, ref value, exponent);
+ return result;
+ }
+
+ public static ulong FloorSqrt(Int128 a)
+ {
+ if (a.IsNegative)
+ throw new ArgumentException("argument must not be negative");
+ return UInt128.FloorSqrt(a.v);
+ }
+
+ public static ulong CeilingSqrt(Int128 a)
+ {
+ if (a.IsNegative)
+ throw new ArgumentException("argument must not be negative");
+ return UInt128.CeilingSqrt(a.v);
+ }
+
+ public static long FloorCbrt(Int128 a)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ return -(long)UInt128.FloorCbrt(aneg);
+ }
+ return (long)UInt128.FloorCbrt(a.v);
+ }
+
+ public static long CeilingCbrt(Int128 a)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ return -(long)UInt128.CeilingCbrt(aneg);
+ }
+ return (long)UInt128.CeilingCbrt(a.v);
+ }
+
+ public static Int128 Min(Int128 a, Int128 b)
+ {
+ if (LessThan(ref a.v, ref b.v))
+ return a;
+ return b;
+ }
+
+ public static Int128 Max(Int128 a, Int128 b)
+ {
+ if (LessThan(ref b.v, ref a.v))
+ return a;
+ return b;
+ }
+
+ public static double Log(Int128 a)
+ {
+ return Log(a, Math.E);
+ }
+
+ public static double Log10(Int128 a)
+ {
+ return Log(a, 10);
+ }
+
+ public static double Log(Int128 a, double b)
+ {
+ if (a.IsNegative || a.IsZero)
+ throw new ArgumentException("argument must be positive");
+ return Math.Log(UInt128.ConvertToDouble(ref a.v), b);
+ }
+
+ public static Int128 Add(Int128 a, Int128 b)
+ {
+ Int128 c;
+ UInt128.Add(out c.v, ref a.v, ref b.v);
+ return c;
+ }
+
+ public static Int128 Subtract(Int128 a, Int128 b)
+ {
+ Int128 c;
+ UInt128.Subtract(out c.v, ref a.v, ref b.v);
+ return c;
+ }
+
+ public static Int128 Multiply(Int128 a, Int128 b)
+ {
+ Int128 c;
+ Multiply(out c, ref a, ref b);
+ return c;
+ }
+
+ public static Int128 Divide(Int128 a, Int128 b)
+ {
+ Int128 c;
+ Divide(out c, ref a, ref b);
+ return c;
+ }
+
+ public static Int128 Remainder(Int128 a, Int128 b)
+ {
+ Int128 c;
+ Remainder(out c, ref a, ref b);
+ return c;
+ }
+
+ public static Int128 DivRem(Int128 a, Int128 b, out Int128 remainder)
+ {
+ Int128 c;
+ Divide(out c, ref a, ref b);
+ Remainder(out remainder, ref a, ref b);
+ return c;
+ }
+
+ public static Int128 Negate(Int128 a)
+ {
+ Int128 c;
+ UInt128.Negate(out c.v, ref a.v);
+ return c;
+ }
+
+ public static Int128 GreatestCommonDivisor(Int128 a, Int128 b)
+ {
+ Int128 c;
+ GreatestCommonDivisor(out c, ref a, ref b);
+ return c;
+ }
+
+ public static void GreatestCommonDivisor(out Int128 c, ref Int128 a, ref Int128 b)
+ {
+ if (a.IsNegative)
+ {
+ UInt128 aneg;
+ UInt128.Negate(out aneg, ref a.v);
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.GreatestCommonDivisor(out c.v, ref aneg, ref bneg);
+ }
+ else
+ UInt128.GreatestCommonDivisor(out c.v, ref aneg, ref b.v);
+ }
+ else
+ {
+ if (b.IsNegative)
+ {
+ UInt128 bneg;
+ UInt128.Negate(out bneg, ref b.v);
+ UInt128.GreatestCommonDivisor(out c.v, ref a.v, ref bneg);
+ }
+ else
+ UInt128.GreatestCommonDivisor(out c.v, ref a.v, ref b.v);
+ }
+ }
+
+ public static void LeftShift(ref Int128 c, int d)
+ {
+ UInt128.LeftShift(ref c.v, d);
+ }
+
+ public static void LeftShift(ref Int128 c)
+ {
+ UInt128.LeftShift(ref c.v);
+ }
+
+ public static void RightShift(ref Int128 c, int d)
+ {
+ UInt128.ArithmeticRightShift(ref c.v, d);
+ }
+
+ public static void RightShift(ref Int128 c)
+ {
+ UInt128.ArithmeticRightShift(ref c.v);
+ }
+
+ public static void Swap(ref Int128 a, ref Int128 b)
+ {
+ UInt128.Swap(ref a.v, ref b.v);
+ }
+
+ public static int Compare(Int128 a, Int128 b)
+ {
+ return a.CompareTo(b);
+ }
+
+ public static void Shift(out Int128 c, ref Int128 a, int d)
+ {
+ UInt128.ArithmeticShift(out c.v, ref a.v, d);
+ }
+
+ public static void Shift(ref Int128 c, int d)
+ {
+ UInt128.ArithmeticShift(ref c.v, d);
+ }
+
+ public static Int128 ModAdd(Int128 a, Int128 b, Int128 modulus)
+ {
+ Int128 c;
+ UInt128.ModAdd(out c.v, ref a.v, ref b.v, ref modulus.v);
+ return c;
+ }
+
+ public static Int128 ModSub(Int128 a, Int128 b, Int128 modulus)
+ {
+ Int128 c;
+ UInt128.ModSub(out c.v, ref a.v, ref b.v, ref modulus.v);
+ return c;
+ }
+
+ public static Int128 ModMul(Int128 a, Int128 b, Int128 modulus)
+ {
+ Int128 c;
+ UInt128.ModMul(out c.v, ref a.v, ref b.v, ref modulus.v);
+ return c;
+ }
+
+ public static Int128 ModPow(Int128 value, Int128 exponent, Int128 modulus)
+ {
+Int128 result;
+ UInt128.ModPow(out result.v, ref value.v, ref exponent.v, ref modulus.v);
+ return result;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Dirichlet.Numerics/Properties/AssemblyInfo.cs b/TBF_V2/Sources/TBF/Dirichlet.Numerics/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..0c435d92
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Dirichlet.Numerics/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Dirichlet.Numerics")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Dirichlet.Numerics")]
+[assembly: AssemblyCopyright("Copyright 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a588abc0-c631-4475-9eab-4163d9f81fed")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TBF_V2/Sources/TBF/Dirichlet.Numerics/UInt128.cs b/TBF_V2/Sources/TBF/Dirichlet.Numerics/UInt128.cs
new file mode 100644
index 00000000..c3867176
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Dirichlet.Numerics/UInt128.cs
@@ -0,0 +1,2638 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Numerics;
+
+namespace Dirichlet.Numerics
+{
+ public struct UInt128 : IFormattable, IComparable, IComparable, IEquatable
+ {
+ private struct UInt256
+ {
+ public ulong s0;
+ public ulong s1;
+ public ulong s2;
+ public ulong s3;
+
+ public uint r0 { get { return (uint)s0; } }
+ public uint r1 { get { return (uint)(s0 >> 32); } }
+ public uint r2 { get { return (uint)s1; } }
+ public uint r3 { get { return (uint)(s1 >> 32); } }
+ public uint r4 { get { return (uint)s2; } }
+ public uint r5 { get { return (uint)(s2 >> 32); } }
+ public uint r6 { get { return (uint)s3; } }
+ public uint r7 { get { return (uint)(s3 >> 32); } }
+
+ public UInt128 t0 { get { UInt128 result; UInt128.Create(out result, s0, s1); return result; } }
+ public UInt128 t1 { get { UInt128 result; UInt128.Create(out result, s2, s3); return result; } }
+
+ public static implicit operator BigInteger(UInt256 a)
+ {
+ return (BigInteger)a.s3 << 192 | (BigInteger)a.s2 << 128 | (BigInteger)a.s1 << 64 | a.s0;
+ }
+
+ public override string ToString()
+ {
+ return ((BigInteger)this).ToString();
+ }
+ }
+
+ private ulong s0;
+ private ulong s1;
+
+ private static readonly UInt128 maxValue = ~(UInt128)0;
+ private static readonly UInt128 zero = (UInt128)0;
+ private static readonly UInt128 one = (UInt128)1;
+
+ public static UInt128 MinValue { get { return zero; } }
+ public static UInt128 MaxValue { get { return maxValue; } }
+ public static UInt128 Zero { get { return zero; } }
+ public static UInt128 One { get { return one; } }
+
+ public static UInt128 Parse(string value)
+ {
+ UInt128 c;
+ if (!TryParse(value, out c))
+ throw new FormatException();
+ return c;
+ }
+
+ public static bool TryParse(string value, out UInt128 result)
+ {
+ return TryParse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out UInt128 result)
+ {
+ BigInteger a;
+ if (!BigInteger.TryParse(value, style, provider, out a))
+ {
+ result = Zero;
+ return false;
+ }
+ Create(out result, a);
+ return true;
+ }
+
+ public UInt128(long value)
+ {
+ Create(out this, value);
+ }
+
+ public UInt128(ulong value)
+ {
+ Create(out this, value);
+ }
+
+ public UInt128(decimal value)
+ {
+ Create(out this, value);
+ }
+
+ public UInt128(double value)
+ {
+ Create(out this, value);
+ }
+
+ public UInt128(BigInteger value)
+ {
+ Create(out this, value);
+ }
+
+ public static void Create(out UInt128 c, uint r0, uint r1, uint r2, uint r3)
+ {
+ c.s0 = (ulong)r1 << 32 | r0;
+ c.s1 = (ulong)r3 << 32 | r2;
+ }
+
+ public static void Create(out UInt128 c, ulong s0, ulong s1)
+ {
+ c.s0 = s0;
+ c.s1 = s1;
+ }
+
+ public static void Create(out UInt128 c, long a)
+ {
+ c.s0 = (ulong)a;
+ c.s1 = a < 0 ? ulong.MaxValue : 0;
+ }
+
+ public static void Create(out UInt128 c, ulong a)
+ {
+ c.s0 = a;
+ c.s1 = 0;
+ }
+
+ public static void Create(out UInt128 c, decimal a)
+ {
+ var bits = decimal.GetBits(decimal.Truncate(a));
+ Create(out c, (uint)bits[0], (uint)bits[1], (uint)bits[2], 0);
+ if (a < 0)
+ Negate(ref c);
+ }
+
+ public static void Create(out UInt128 c, BigInteger a)
+ {
+ var sign = a.Sign;
+ if (sign == -1)
+ a = -a;
+ c.s0 = (ulong)(a & ulong.MaxValue);
+ c.s1 = (ulong)(a >> 64);
+ if (sign == -1)
+ Negate(ref c);
+ }
+
+ public static void Create(out UInt128 c, double a)
+ {
+ var negate = false;
+ if (a < 0)
+ {
+ negate = true;
+ a = -a;
+ }
+ if (a <= ulong.MaxValue)
+ {
+ c.s0 = (ulong)a;
+ c.s1 = 0;
+ }
+ else
+ {
+ var shift = Math.Max((int)Math.Ceiling(Math.Log(a, 2)) - 63, 0);
+ c.s0 = (ulong)(a / Math.Pow(2, shift));
+ c.s1 = 0;
+ LeftShift(ref c, shift);
+ }
+ if (negate)
+ Negate(ref c);
+ }
+
+ private uint r0 { get { return (uint)s0; } }
+ private uint r1 { get { return (uint)(s0 >> 32); } }
+ private uint r2 { get { return (uint)s1; } }
+ private uint r3 { get { return (uint)(s1 >> 32); } }
+
+ public ulong S0 { get { return s0; } }
+ public ulong S1 { get { return s1; } }
+
+ public bool IsZero { get { return (s0 | s1) == 0; } }
+ public bool IsOne { get { return (s1 ^ s0) == 1; } }
+ public bool IsPowerOfTwo { get { return (this & (this - 1)).IsZero; } }
+ public bool IsEven { get { return (s0 & 1) == 0; } }
+ public int Sign { get { return IsZero ? 0 : 1; } }
+
+ public override string ToString()
+ {
+ return ((BigInteger)this).ToString();
+ }
+
+ public string ToString(string format)
+ {
+ return ((BigInteger)this).ToString(format);
+ }
+
+ public string ToString(IFormatProvider provider)
+ {
+ return ToString(null, provider);
+ }
+
+ public string ToString(string format, IFormatProvider provider)
+ {
+ return ((BigInteger)this).ToString(format, provider);
+ }
+
+ public static explicit operator UInt128(double a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static explicit operator UInt128(sbyte a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static implicit operator UInt128(byte a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static explicit operator UInt128(short a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static implicit operator UInt128(ushort a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static explicit operator UInt128(int a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static implicit operator UInt128(uint a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static explicit operator UInt128(long a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static implicit operator UInt128(ulong a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static explicit operator UInt128(decimal a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static explicit operator UInt128(BigInteger a)
+ {
+ UInt128 c;
+ Create(out c, a);
+ return c;
+ }
+
+ public static explicit operator float(UInt128 a)
+ {
+ return ConvertToFloat(ref a);
+ }
+
+ public static explicit operator double(UInt128 a)
+ {
+ return ConvertToDouble(ref a);
+ }
+
+ public static float ConvertToFloat(ref UInt128 a)
+ {
+ if (a.s1 == 0)
+ return a.s0;
+ return a.s1 * (float)ulong.MaxValue + a.s0;
+ }
+
+ public static double ConvertToDouble(ref UInt128 a)
+ {
+ if (a.s1 == 0)
+ return a.s0;
+ return a.s1 * (double)ulong.MaxValue + a.s0;
+ }
+
+ public static explicit operator sbyte(UInt128 a)
+ {
+ return (sbyte)a.s0;
+ }
+
+ public static explicit operator byte(UInt128 a)
+ {
+ return (byte)a.s0;
+ }
+
+ public static explicit operator short(UInt128 a)
+ {
+ return (short)a.s0;
+ }
+
+ public static explicit operator ushort(UInt128 a)
+ {
+ return (ushort)a.s0;
+ }
+
+ public static explicit operator int(UInt128 a)
+ {
+ return (int)a.s0;
+ }
+
+ public static explicit operator uint(UInt128 a)
+ {
+ return (uint)a.s0;
+ }
+
+ public static explicit operator long(UInt128 a)
+ {
+ return (long)a.s0;
+ }
+
+ public static explicit operator ulong(UInt128 a)
+ {
+ return a.s0;
+ }
+
+ public static explicit operator decimal(UInt128 a)
+ {
+ if (a.s1 == 0)
+ return a.s0;
+ var shift = Math.Max(0, 32 - GetBitLength(a.s1));
+ UInt128 ashift;
+ RightShift(out ashift, ref a, shift);
+ return new decimal((int)a.r0, (int)a.r1, (int)a.r2, false, (byte)shift);
+ }
+
+ public static implicit operator BigInteger(UInt128 a)
+ {
+ if (a.s1 == 0)
+ return a.s0;
+ return (BigInteger)a.s1 << 64 | a.s0;
+ }
+
+ public static UInt128 operator <<(UInt128 a, int b)
+ {
+ UInt128 c;
+ LeftShift(out c, ref a, b);
+ return c;
+ }
+
+ public static UInt128 operator >>(UInt128 a, int b)
+ {
+ UInt128 c;
+ RightShift(out c, ref a, b);
+ return c;
+ }
+
+ public static UInt128 operator &(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ And(out c, ref a, ref b);
+ return c;
+ }
+
+ public static uint operator &(UInt128 a, uint b)
+ {
+ return (uint)a.s0 & b;
+ }
+
+ public static uint operator &(uint a, UInt128 b)
+ {
+ return a & (uint)b.s0;
+ }
+
+ public static ulong operator &(UInt128 a, ulong b)
+ {
+ return a.s0 & b;
+ }
+
+ public static ulong operator &(ulong a, UInt128 b)
+ {
+ return a & b.s0;
+ }
+
+ public static UInt128 operator |(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Or(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 operator ^(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ ExclusiveOr(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 operator ~(UInt128 a)
+ {
+ UInt128 c;
+ Not(out c, ref a);
+ return c;
+ }
+
+ public static UInt128 operator +(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Add(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 operator +(UInt128 a, ulong b)
+ {
+ UInt128 c;
+ Add(out c, ref a, b);
+ return c;
+ }
+
+ public static UInt128 operator +(ulong a, UInt128 b)
+ {
+ UInt128 c;
+ Add(out c, ref b, a);
+ return c;
+ }
+
+ public static UInt128 operator ++(UInt128 a)
+ {
+ UInt128 c;
+ Add(out c, ref a, 1);
+ return c;
+ }
+
+ public static UInt128 operator -(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Subtract(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 operator -(UInt128 a, ulong b)
+ {
+ UInt128 c;
+ Subtract(out c, ref a, b);
+ return c;
+ }
+
+ public static UInt128 operator -(ulong a, UInt128 b)
+ {
+ UInt128 c;
+ Subtract(out c, a, ref b);
+ return c;
+ }
+
+ public static UInt128 operator --(UInt128 a)
+ {
+ UInt128 c;
+ Subtract(out c, ref a, 1);
+ return c;
+ }
+
+ public static UInt128 operator +(UInt128 a)
+ {
+ return a;
+ }
+
+ public static UInt128 operator *(UInt128 a, uint b)
+ {
+ UInt128 c;
+ Multiply(out c, ref a, b);
+ return c;
+ }
+
+ public static UInt128 operator *(uint a, UInt128 b)
+ {
+ UInt128 c;
+ Multiply(out c, ref b, a);
+ return c;
+ }
+
+ public static UInt128 operator *(UInt128 a, ulong b)
+ {
+ UInt128 c;
+ Multiply(out c, ref a, b);
+ return c;
+ }
+
+ public static UInt128 operator *(ulong a, UInt128 b)
+ {
+ UInt128 c;
+ Multiply(out c, ref b, a);
+ return c;
+ }
+
+ public static UInt128 operator *(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Multiply(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 operator /(UInt128 a, ulong b)
+ {
+ UInt128 c;
+ Divide(out c, ref a, b);
+ return c;
+ }
+
+ public static UInt128 operator /(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Divide(out c, ref a, ref b);
+ return c;
+ }
+
+ public static ulong operator %(UInt128 a, uint b)
+ {
+ return Remainder(ref a, b);
+ }
+
+ public static ulong operator %(UInt128 a, ulong b)
+ {
+ return Remainder(ref a, b);
+ }
+
+ public static UInt128 operator %(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Remainder(out c, ref a, ref b);
+ return c;
+ }
+
+ public static bool operator <(UInt128 a, UInt128 b)
+ {
+ return LessThan(ref a, ref b);
+ }
+
+ public static bool operator <(UInt128 a, int b)
+ {
+ return LessThan(ref a, b);
+ }
+
+ public static bool operator <(int a, UInt128 b)
+ {
+ return LessThan(a, ref b);
+ }
+
+ public static bool operator <(UInt128 a, uint b)
+ {
+ return LessThan(ref a, b);
+ }
+
+ public static bool operator <(uint a, UInt128 b)
+ {
+ return LessThan(a, ref b);
+ }
+
+ public static bool operator <(UInt128 a, long b)
+ {
+ return LessThan(ref a, b);
+ }
+
+ public static bool operator <(long a, UInt128 b)
+ {
+ return LessThan(a, ref b);
+ }
+
+ public static bool operator <(UInt128 a, ulong b)
+ {
+ return LessThan(ref a, b);
+ }
+
+ public static bool operator <(ulong a, UInt128 b)
+ {
+ return LessThan(a, ref b);
+ }
+
+ public static bool operator <=(UInt128 a, UInt128 b)
+ {
+ return !LessThan(ref b, ref a);
+ }
+
+ public static bool operator <=(UInt128 a, int b)
+ {
+ return !LessThan(b, ref a);
+ }
+
+ public static bool operator <=(int a, UInt128 b)
+ {
+ return !LessThan(ref b, a);
+ }
+
+ public static bool operator <=(UInt128 a, uint b)
+ {
+ return !LessThan(b, ref a);
+ }
+
+ public static bool operator <=(uint a, UInt128 b)
+ {
+ return !LessThan(ref b, a);
+ }
+
+ public static bool operator <=(UInt128 a, long b)
+ {
+ return !LessThan(b, ref a);
+ }
+
+ public static bool operator <=(long a, UInt128 b)
+ {
+ return !LessThan(ref b, a);
+ }
+
+ public static bool operator <=(UInt128 a, ulong b)
+ {
+ return !LessThan(b, ref a);
+ }
+
+ public static bool operator <=(ulong a, UInt128 b)
+ {
+ return !LessThan(ref b, a);
+ }
+
+ public static bool operator >(UInt128 a, UInt128 b)
+ {
+ return LessThan(ref b, ref a);
+ }
+
+ public static bool operator >(UInt128 a, int b)
+ {
+ return LessThan(b, ref a);
+ }
+
+ public static bool operator >(int a, UInt128 b)
+ {
+ return LessThan(ref b, a);
+ }
+
+ public static bool operator >(UInt128 a, uint b)
+ {
+ return LessThan(b, ref a);
+ }
+
+ public static bool operator >(uint a, UInt128 b)
+ {
+ return LessThan(ref b, a);
+ }
+
+ public static bool operator >(UInt128 a, long b)
+ {
+ return LessThan(b, ref a);
+ }
+
+ public static bool operator >(long a, UInt128 b)
+ {
+ return LessThan(ref b, a);
+ }
+
+ public static bool operator >(UInt128 a, ulong b)
+ {
+ return LessThan(b, ref a);
+ }
+
+ public static bool operator >(ulong a, UInt128 b)
+ {
+ return LessThan(ref b, a);
+ }
+
+ public static bool operator >=(UInt128 a, UInt128 b)
+ {
+ return !LessThan(ref a, ref b);
+ }
+
+ public static bool operator >=(UInt128 a, int b)
+ {
+ return !LessThan(ref a, b);
+ }
+
+ public static bool operator >=(int a, UInt128 b)
+ {
+ return !LessThan(a, ref b);
+ }
+
+ public static bool operator >=(UInt128 a, uint b)
+ {
+ return !LessThan(ref a, b);
+ }
+
+ public static bool operator >=(uint a, UInt128 b)
+ {
+ return !LessThan(a, ref b);
+ }
+
+ public static bool operator >=(UInt128 a, long b)
+ {
+ return !LessThan(ref a, b);
+ }
+
+ public static bool operator >=(long a, UInt128 b)
+ {
+ return !LessThan(a, ref b);
+ }
+
+ public static bool operator >=(UInt128 a, ulong b)
+ {
+ return !LessThan(ref a, b);
+ }
+
+ public static bool operator >=(ulong a, UInt128 b)
+ {
+ return !LessThan(a, ref b);
+ }
+
+ public static bool operator ==(UInt128 a, UInt128 b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(UInt128 a, int b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(int a, UInt128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator ==(UInt128 a, uint b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(uint a, UInt128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator ==(UInt128 a, long b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(long a, UInt128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator ==(UInt128 a, ulong b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator ==(ulong a, UInt128 b)
+ {
+ return b.Equals(a);
+ }
+
+ public static bool operator !=(UInt128 a, UInt128 b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(UInt128 a, int b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(int a, UInt128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public static bool operator !=(UInt128 a, uint b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(uint a, UInt128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public static bool operator !=(UInt128 a, long b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(long a, UInt128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public static bool operator !=(UInt128 a, ulong b)
+ {
+ return !a.Equals(b);
+ }
+
+ public static bool operator !=(ulong a, UInt128 b)
+ {
+ return !b.Equals(a);
+ }
+
+ public int CompareTo(UInt128 other)
+ {
+ if (s1 != other.s1)
+ return s1.CompareTo(other.s1);
+ return s0.CompareTo(other.s0);
+ }
+
+ public int CompareTo(int other)
+ {
+ if (s1 != 0 || other < 0)
+ return 1;
+ return s0.CompareTo((ulong)other);
+ }
+
+ public int CompareTo(uint other)
+ {
+ if (s1 != 0)
+ return 1;
+ return s0.CompareTo((ulong)other);
+ }
+
+ public int CompareTo(long other)
+ {
+ if (s1 != 0 || other < 0)
+ return 1;
+ return s0.CompareTo((ulong)other);
+ }
+
+ public int CompareTo(ulong other)
+ {
+ if (s1 != 0)
+ return 1;
+ return s0.CompareTo(other);
+ }
+
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ return 1;
+ if (!(obj is UInt128))
+ throw new ArgumentException();
+ return CompareTo((UInt128)obj);
+ }
+
+ private static bool LessThan(ref UInt128 a, long b)
+ {
+ return b >= 0 && a.s1 == 0 && a.s0 < (ulong)b;
+ }
+
+ private static bool LessThan(long a, ref UInt128 b)
+ {
+ return a < 0 || b.s1 != 0 || (ulong)a < b.s0;
+ }
+
+ private static bool LessThan(ref UInt128 a, ulong b)
+ {
+ return a.s1 == 0 && a.s0 < b;
+ }
+
+ private static bool LessThan(ulong a, ref UInt128 b)
+ {
+ return b.s1 != 0 || a < b.s0;
+ }
+
+ private static bool LessThan(ref UInt128 a, ref UInt128 b)
+ {
+ if (a.s1 != b.s1)
+ return a.s1 < b.s1;
+ return a.s0 < b.s0;
+ }
+
+ public static bool Equals(ref UInt128 a, ref UInt128 b)
+ {
+ return a.s0 == b.s0 && a.s1 == b.s1;
+ }
+
+ public bool Equals(UInt128 other)
+ {
+ return s0 == other.s0 && s1 == other.s1;
+ }
+
+ public bool Equals(int other)
+ {
+ return other >= 0 && s0 == (uint)other && s1 == 0;
+ }
+
+ public bool Equals(uint other)
+ {
+ return s0 == other && s1 == 0;
+ }
+
+ public bool Equals(long other)
+ {
+ return other >= 0 && s0 == (ulong)other && s1 == 0;
+ }
+
+ public bool Equals(ulong other)
+ {
+ return s0 == other && s1 == 0;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is UInt128))
+ return false;
+ return Equals((UInt128)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return s0.GetHashCode() ^ s1.GetHashCode();
+ }
+
+ public static void Multiply(out UInt128 c, ulong a, ulong b)
+ {
+ Multiply64(out c, a, b);
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b);
+ }
+
+ public static void Multiply(out UInt128 c, ref UInt128 a, uint b)
+ {
+ if (a.s1 == 0)
+ Multiply64(out c, a.s0, b);
+ else
+ Multiply128(out c, ref a, b);
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b % ((BigInteger)1 << 128));
+ }
+
+ public static void Multiply(out UInt128 c, ref UInt128 a, ulong b)
+ {
+ if (a.s1 == 0)
+ Multiply64(out c, a.s0, b);
+ else
+ Multiply128(out c, ref a, b);
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b % ((BigInteger)1 << 128));
+ }
+
+ public static void Multiply(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ if ((a.s1 | b.s1) == 0)
+ Multiply64(out c, a.s0, b.s0);
+ else if (a.s1 == 0)
+ Multiply128(out c, ref b, a.s0);
+ else if (b.s1 == 0)
+ Multiply128(out c, ref a, b.s0);
+ else
+ Multiply128(out c, ref a, ref b);
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b % ((BigInteger)1 << 128));
+ }
+
+ private static void Multiply(out UInt256 c, ref UInt128 a, ref UInt128 b)
+ {
+#if true
+ UInt128 c00, c01, c10, c11;
+ Multiply64(out c00, a.s0, b.s0);
+ Multiply64(out c01, a.s0, b.s1);
+ Multiply64(out c10, a.s1, b.s0);
+ Multiply64(out c11, a.s1, b.s1);
+ var carry1 = (uint)0;
+ var carry2 = (uint)0;
+ c.s0 = c00.S0;
+ c.s1 = Add(Add(c00.s1, c01.s0, ref carry1), c10.s0, ref carry1);
+ c.s2 = Add(Add(Add(c01.s1, c10.s1, ref carry2), c11.s0, ref carry2), carry1, ref carry2);
+ c.s3 = c11.s1 + carry2;
+#else
+ // Karatsuba method.
+ // Warning: doesn't correctly handle overflow.
+ UInt128 z0, z1, z2;
+ Multiply64(out z0, a.s0, b.s0);
+ Multiply64(out z2, a.s1, b.s1);
+ Multiply64(out z1, a.s0 + a.s1, b.s0 + b.s1);
+ Subtract(ref z1, ref z2);
+ Subtract(ref z1, ref z0);
+ var carry1 = (uint)0;
+ var carry2 = (uint)0;
+ c.s0 = z0.S0;
+ c.s1 = Add(z0.s1, z1.s0, ref carry1);
+ c.s2 = Add(Add(z1.s1, z2.s0, ref carry2), carry1, ref carry2);
+ c.s3 = z2.s1 + carry2;
+#endif
+ Debug.Assert((BigInteger)c == (BigInteger)a * (BigInteger)b);
+ }
+
+ public static UInt128 Abs(UInt128 a)
+ {
+ return a;
+ }
+
+ public static UInt128 Square(ulong a)
+ {
+ UInt128 c;
+ Square(out c, a);
+ return c;
+ }
+
+ public static UInt128 Square(UInt128 a)
+ {
+ UInt128 c;
+ Square(out c, ref a);
+ return c;
+ }
+
+ public static void Square(out UInt128 c, ulong a)
+ {
+ Square64(out c, a);
+ }
+
+ public static void Square(out UInt128 c, ref UInt128 a)
+ {
+ if (a.s1 == 0)
+ Square64(out c, a.s0);
+ else
+ Multiply128(out c, ref a, ref a);
+ }
+
+ public static UInt128 Cube(ulong a)
+ {
+ UInt128 c;
+ Cube(out c, a);
+ return c;
+ }
+
+ public static UInt128 Cube(UInt128 a)
+ {
+ UInt128 c;
+ Cube(out c, ref a);
+ return c;
+ }
+
+ public static void Cube(out UInt128 c, ulong a)
+ {
+ UInt128 square;
+ Square(out square, a);
+ Multiply(out c, ref square, a);
+ }
+
+ public static void Cube(out UInt128 c, ref UInt128 a)
+ {
+ UInt128 square;
+ if (a.s1 == 0)
+ {
+ Square64(out square, a.s0);
+ Multiply(out c, ref square, a.s0);
+ }
+ else
+ {
+ Multiply128(out square, ref a, ref a);
+ Multiply128(out c, ref square, ref a);
+ }
+ }
+
+ public static void Add(out UInt128 c, ulong a, ulong b)
+ {
+ c.s0 = a + b;
+ c.s1 = 0;
+ if (c.s0 < a && c.s0 < b)
+ ++c.s1;
+ Debug.Assert((BigInteger)c == ((BigInteger)a + (BigInteger)b));
+ }
+
+ public static void Add(out UInt128 c, ref UInt128 a, ulong b)
+ {
+ c.s0 = a.s0 + b;
+ c.s1 = a.s1;
+ if (c.s0 < a.s0 && c.s0 < b)
+ ++c.s1;
+ Debug.Assert((BigInteger)c == ((BigInteger)a + (BigInteger)b) % ((BigInteger)1 << 128));
+ }
+
+ public static void Add(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ c.s0 = a.s0 + b.s0;
+ c.s1 = a.s1 + b.s1;
+ if (c.s0 < a.s0 && c.s0 < b.s0)
+ ++c.s1;
+ Debug.Assert((BigInteger)c == ((BigInteger)a + (BigInteger)b) % ((BigInteger)1 << 128));
+ }
+
+ private static ulong Add(ulong a, ulong b, ref uint carry)
+ {
+ var c = a + b;
+ if (c < a && c < b)
+ ++carry;
+ return c;
+ }
+
+ public static void Add(ref UInt128 a, ulong b)
+ {
+ var sum = a.s0 + b;
+ if (sum < a.s0 && sum < b)
+ ++a.s1;
+ a.s0 = sum;
+ }
+
+ public static void Add(ref UInt128 a, ref UInt128 b)
+ {
+ var sum = a.s0 + b.s0;
+ if (sum < a.s0 && sum < b.s0)
+ ++a.s1;
+ a.s0 = sum;
+ a.s1 += b.s1;
+ }
+
+ public static void Add(ref UInt128 a, UInt128 b)
+ {
+ Add(ref a, ref b);
+ }
+
+ public static void Subtract(out UInt128 c, ref UInt128 a, ulong b)
+ {
+ c.s0 = a.s0 - b;
+ c.s1 = a.s1;
+ if (a.s0 < b)
+ --c.s1;
+ Debug.Assert((BigInteger)c == ((BigInteger)a - (BigInteger)b + ((BigInteger)1 << 128)) % ((BigInteger)1 << 128));
+ }
+
+ public static void Subtract(out UInt128 c, ulong a, ref UInt128 b)
+ {
+ c.s0 = a - b.s0;
+ c.s1 = 0 - b.s1;
+ if (a < b.s0)
+ --c.s1;
+ Debug.Assert((BigInteger)c == ((BigInteger)a - (BigInteger)b + ((BigInteger)1 << 128)) % ((BigInteger)1 << 128));
+ }
+
+ public static void Subtract(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ c.s0 = a.s0 - b.s0;
+ c.s1 = a.s1 - b.s1;
+ if (a.s0 < b.s0)
+ --c.s1;
+ Debug.Assert((BigInteger)c == ((BigInteger)a - (BigInteger)b + ((BigInteger)1 << 128)) % ((BigInteger)1 << 128));
+ }
+
+ public static void Subtract(ref UInt128 a, ulong b)
+ {
+ if (a.s0 < b)
+ --a.s1;
+ a.s0 -= b;
+ }
+
+ public static void Subtract(ref UInt128 a, ref UInt128 b)
+ {
+ if (a.s0 < b.s0)
+ --a.s1;
+ a.s0 -= b.s0;
+ a.s1 -= b.s1;
+ }
+
+ public static void Subtract(ref UInt128 a, UInt128 b)
+ {
+ Subtract(ref a, ref b);
+ }
+
+ private static void Square64(out UInt128 w, ulong u)
+ {
+ var u0 = (ulong)(uint)u;
+ var u1 = u >> 32;
+ var carry = u0 * u0;
+ var r0 = (uint)carry;
+ var u0u1 = u0 * u1;
+ carry = (carry >> 32) + u0u1;
+ var r2 = carry >> 32;
+ carry = (uint)carry + u0u1;
+ w.s0 = carry << 32 | r0;
+ w.s1 = (carry >> 32) + r2 + u1 * u1;
+ Debug.Assert((BigInteger)w == (BigInteger)u * u);
+ }
+
+ private static void Multiply64(out UInt128 w, uint u, uint v)
+ {
+ w.s0 = (ulong)u * v;
+ w.s1 = 0;
+ Debug.Assert((BigInteger)w == (BigInteger)u * v);
+ }
+
+ private static void Multiply64(out UInt128 w, ulong u, uint v)
+ {
+ var u0 = (ulong)(uint)u;
+ var u1 = u >> 32;
+ var carry = u0 * v;
+ var r0 = (uint)carry;
+ carry = (carry >> 32) + u1 * v;
+ w.s0 = carry << 32 | r0;
+ w.s1 = carry >> 32;
+ Debug.Assert((BigInteger)w == (BigInteger)u * v);
+ }
+
+ private static void Multiply64(out UInt128 w, ulong u, ulong v)
+ {
+ var u0 = (ulong)(uint)u;
+ var u1 = u >> 32;
+ var v0 = (ulong)(uint)v;
+ var v1 = v >> 32;
+ var carry = u0 * v0;
+ var r0 = (uint)carry;
+ carry = (carry >> 32) + u0 * v1;
+ var r2 = carry >> 32;
+ carry = (uint)carry + u1 * v0;
+ w.s0 = carry << 32 | r0;
+ w.s1 = (carry >> 32) + r2 + u1 * v1;
+ Debug.Assert((BigInteger)w == (BigInteger)u * v);
+ }
+
+ private static void Multiply64(out UInt128 w, ulong u, ulong v, ulong c)
+ {
+ var u0 = (ulong)(uint)u;
+ var u1 = u >> 32;
+ var v0 = (ulong)(uint)v;
+ var v1 = v >> 32;
+ var carry = u0 * v0 + (uint)c;
+ var r0 = (uint)carry;
+ carry = (carry >> 32) + u0 * v1 + (c >> 32);
+ var r2 = carry >> 32;
+ carry = (uint)carry + u1 * v0;
+ w.s0 = carry << 32 | r0;
+ w.s1 = (carry >> 32) + r2 + u1 * v1;
+ Debug.Assert((BigInteger)w == (BigInteger)u * v + c);
+ }
+
+ private static ulong MultiplyHigh64(ulong u, ulong v, ulong c)
+ {
+ var u0 = (ulong)(uint)u;
+ var u1 = u >> 32;
+ var v0 = (ulong)(uint)v;
+ var v1 = v >> 32;
+ var carry = ((u0 * v0 + (uint)c) >> 32) + u0 * v1 + (c >> 32);
+ var r2 = carry >> 32;
+ carry = (uint)carry + u1 * v0;
+ return (carry >> 32) + r2 + u1 * v1;
+ }
+
+ private static void Multiply128(out UInt128 w, ref UInt128 u, uint v)
+ {
+ Multiply64(out w, u.s0, v);
+ w.s1 += u.s1 * v;
+ Debug.Assert((BigInteger)w == (BigInteger)u * v % ((BigInteger)1 << 128));
+ }
+
+ private static void Multiply128(out UInt128 w, ref UInt128 u, ulong v)
+ {
+ Multiply64(out w, u.s0, v);
+ w.s1 += u.s1 * v;
+ Debug.Assert((BigInteger)w == (BigInteger)u * v % ((BigInteger)1 << 128));
+ }
+
+ private static void Multiply128(out UInt128 w, ref UInt128 u, ref UInt128 v)
+ {
+ Multiply64(out w, u.s0, v.s0);
+ w.s1 += u.s1 * v.s0 + u.s0 * v.s1;
+ Debug.Assert((BigInteger)w == (BigInteger)u * v % ((BigInteger)1 << 128));
+ }
+
+ public static void Divide(out UInt128 w, ref UInt128 u, uint v)
+ {
+ if (u.s1 == 0)
+ Divide64(out w, u.s0, v);
+ else if (u.s1 <= uint.MaxValue)
+ Divide96(out w, ref u, v);
+ else
+ Divide128(out w, ref u, v);
+ }
+
+ public static void Divide(out UInt128 w, ref UInt128 u, ulong v)
+ {
+ if (u.s1 == 0)
+ Divide64(out w, u.s0, v);
+ else
+ {
+ var v0 = (uint)v;
+ if (v == v0)
+ {
+ if (u.s1 <= uint.MaxValue)
+ Divide96(out w, ref u, v0);
+ else
+ Divide128(out w, ref u, v0);
+ }
+ else
+ {
+ if (u.s1 <= uint.MaxValue)
+ Divide96(out w, ref u, v);
+ else
+ Divide128(out w, ref u, v);
+ }
+ }
+ }
+
+ public static void Divide(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ if (LessThan(ref a, ref b))
+ c = Zero;
+ else if (b.s1 == 0)
+ Divide(out c, ref a, b.s0);
+ else if (b.s1 <= uint.MaxValue)
+ {
+ UInt128 rem;
+ Create(out c, DivRem96(out rem, ref a, ref b));
+ }
+ else
+ {
+ UInt128 rem;
+ Create(out c, DivRem128(out rem, ref a, ref b));
+ }
+ }
+
+ public static uint Remainder(ref UInt128 u, uint v)
+ {
+ if (u.s1 == 0)
+ return (uint)(u.s0 % v);
+ if (u.s1 <= uint.MaxValue)
+ return Remainder96(ref u, v);
+ return Remainder128(ref u, v);
+ }
+
+ public static ulong Remainder(ref UInt128 u, ulong v)
+ {
+ if (u.s1 == 0)
+ return u.s0 % v;
+ var v0 = (uint)v;
+ if (v == v0)
+ {
+ if (u.s1 <= uint.MaxValue)
+ return Remainder96(ref u, v0);
+ return Remainder128(ref u, v0);
+ }
+ if (u.s1 <= uint.MaxValue)
+ return Remainder96(ref u, v);
+ return Remainder128(ref u, v);
+ }
+
+ public static void Remainder(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ if (LessThan(ref a, ref b))
+ c = a;
+ else if (b.s1 == 0)
+ Create(out c, Remainder(ref a, b.s0));
+ else if (b.s1 <= uint.MaxValue)
+ DivRem96(out c, ref a, ref b);
+ else
+ DivRem128(out c, ref a, ref b);
+ }
+
+ public static void Remainder(ref UInt128 a, ref UInt128 b)
+ {
+ UInt128 a2 = a;
+ Remainder(out a, ref a2, ref b);
+ }
+
+ private static void Remainder(out UInt128 c, ref UInt256 a, ref UInt128 b)
+ {
+ if (b.r3 == 0)
+ Remainder192(out c, ref a, ref b);
+ else
+ Remainder256(out c, ref a, ref b);
+ }
+
+ private static void Divide64(out UInt128 w, ulong u, ulong v)
+ {
+ w.s1 = 0;
+ w.s0 = u / v;
+ Debug.Assert((BigInteger)w == (BigInteger)u / v);
+ }
+
+ private static void Divide96(out UInt128 w, ref UInt128 u, uint v)
+ {
+ var r2 = u.r2;
+ var w2 = r2 / v;
+ var u0 = (ulong)(r2 - w2 * v);
+ var u0u1 = u0 << 32 | u.r1;
+ var w1 = (uint)(u0u1 / v);
+ u0 = u0u1 - w1 * v;
+ u0u1 = u0 << 32 | u.r0;
+ var w0 = (uint)(u0u1 / v);
+ w.s1 = w2;
+ w.s0 = (ulong)w1 << 32 | w0;
+ Debug.Assert((BigInteger)w == (BigInteger)u / v);
+ }
+
+ private static void Divide128(out UInt128 w, ref UInt128 u, uint v)
+ {
+ var r3 = u.r3;
+ var w3 = r3 / v;
+ var u0 = (ulong)(r3 - w3 * v);
+ var u0u1 = u0 << 32 | u.r2;
+ var w2 = (uint)(u0u1 / v);
+ u0 = u0u1 - w2 * v;
+ u0u1 = u0 << 32 | u.r1;
+ var w1 = (uint)(u0u1 / v);
+ u0 = u0u1 - w1 * v;
+ u0u1 = u0 << 32 | u.r0;
+ var w0 = (uint)(u0u1 / v);
+ w.s1 = (ulong)w3 << 32 | w2;
+ w.s0 = (ulong)w1 << 32 | w0;
+ Debug.Assert((BigInteger)w == (BigInteger)u / v);
+ }
+
+ private static void Divide96(out UInt128 w, ref UInt128 u, ulong v)
+ {
+ w.s0 = w.s1 = 0;
+ var dneg = GetBitLength((uint)(v >> 32));
+ var d = 32 - dneg;
+ var vPrime = v << d;
+ var v1 = (uint)(vPrime >> 32);
+ var v2 = (uint)vPrime;
+ var r0 = u.r0;
+ var r1 = u.r1;
+ var r2 = u.r2;
+ var r3 = (uint)0;
+ if (d != 0)
+ {
+ r3 = r2 >> dneg;
+ r2 = r2 << d | r1 >> dneg;
+ r1 = r1 << d | r0 >> dneg;
+ r0 <<= d;
+ }
+ var q1 = DivRem(r3, ref r2, ref r1, v1, v2);
+ var q0 = DivRem(r2, ref r1, ref r0, v1, v2);
+ w.s0 = (ulong)q1 << 32 | q0;
+ w.s1 = 0;
+ Debug.Assert((BigInteger)w == (BigInteger)u / v);
+ }
+
+ private static void Divide128(out UInt128 w, ref UInt128 u, ulong v)
+ {
+ w.s0 = w.s1 = 0;
+ var dneg = GetBitLength((uint)(v >> 32));
+ var d = 32 - dneg;
+ var vPrime = v << d;
+ var v1 = (uint)(vPrime >> 32);
+ var v2 = (uint)vPrime;
+ var r0 = u.r0;
+ var r1 = u.r1;
+ var r2 = u.r2;
+ var r3 = u.r3;
+ var r4 = (uint)0;
+ if (d != 0)
+ {
+ r4 = r3 >> dneg;
+ r3 = r3 << d | r2 >> dneg;
+ r2 = r2 << d | r1 >> dneg;
+ r1 = r1 << d | r0 >> dneg;
+ r0 <<= d;
+ }
+ w.s1 = DivRem(r4, ref r3, ref r2, v1, v2);
+ var q1 = DivRem(r3, ref r2, ref r1, v1, v2);
+ var q0 = DivRem(r2, ref r1, ref r0, v1, v2);
+ w.s0 = (ulong)q1 << 32 | q0;
+ Debug.Assert((BigInteger)w == (BigInteger)u / v);
+ }
+
+ private static uint Remainder96(ref UInt128 u, uint v)
+ {
+ var u0 = (ulong)(u.r2 % v);
+ var u0u1 = u0 << 32 | u.r1;
+ u0 = u0u1 % v;
+ u0u1 = u0 << 32 | u.r0;
+ return (uint)(u0u1 % v);
+ }
+
+ private static uint Remainder128(ref UInt128 u, uint v)
+ {
+ var u0 = (ulong)(u.r3 % v);
+ var u0u1 = u0 << 32 | u.r2;
+ u0 = u0u1 % v;
+ u0u1 = u0 << 32 | u.r1;
+ u0 = u0u1 % v;
+ u0u1 = u0 << 32 | u.r0;
+ return (uint)(u0u1 % v);
+ }
+
+ private static ulong Remainder96(ref UInt128 u, ulong v)
+ {
+ var dneg = GetBitLength((uint)(v >> 32));
+ var d = 32 - dneg;
+ var vPrime = v << d;
+ var v1 = (uint)(vPrime >> 32);
+ var v2 = (uint)vPrime;
+ var r0 = u.r0;
+ var r1 = u.r1;
+ var r2 = u.r2;
+ var r3 = (uint)0;
+ if (d != 0)
+ {
+ r3 = r2 >> dneg;
+ r2 = r2 << d | r1 >> dneg;
+ r1 = r1 << d | r0 >> dneg;
+ r0 <<= d;
+ }
+ DivRem(r3, ref r2, ref r1, v1, v2);
+ DivRem(r2, ref r1, ref r0, v1, v2);
+ return ((ulong)r1 << 32 | r0) >> d;
+ }
+
+ private static ulong Remainder128(ref UInt128 u, ulong v)
+ {
+ var dneg = GetBitLength((uint)(v >> 32));
+ var d = 32 - dneg;
+ var vPrime = v << d;
+ var v1 = (uint)(vPrime >> 32);
+ var v2 = (uint)vPrime;
+ var r0 = u.r0;
+ var r1 = u.r1;
+ var r2 = u.r2;
+ var r3 = u.r3;
+ var r4 = (uint)0;
+ if (d != 0)
+ {
+ r4 = r3 >> dneg;
+ r3 = r3 << d | r2 >> dneg;
+ r2 = r2 << d | r1 >> dneg;
+ r1 = r1 << d | r0 >> dneg;
+ r0 <<= d;
+ }
+ DivRem(r4, ref r3, ref r2, v1, v2);
+ DivRem(r3, ref r2, ref r1, v1, v2);
+ DivRem(r2, ref r1, ref r0, v1, v2);
+ return ((ulong)r1 << 32 | r0) >> d;
+ }
+
+ private static ulong DivRem96(out UInt128 rem, ref UInt128 a, ref UInt128 b)
+ {
+ var d = 32 - GetBitLength(b.r2);
+ UInt128 v;
+ LeftShift64(out v, ref b, d);
+ var r4 = (uint)LeftShift64(out rem, ref a, d);
+ var v1 = v.r2;
+ var v2 = v.r1;
+ var v3 = v.r0;
+ var r3 = rem.r3;
+ var r2 = rem.r2;
+ var r1 = rem.r1;
+ var r0 = rem.r0;
+ var q1 = DivRem(r4, ref r3, ref r2, ref r1, v1, v2, v3);
+ var q0 = DivRem(r3, ref r2, ref r1, ref r0, v1, v2, v3);
+ Create(out rem, r0, r1, r2, 0);
+ var div = (ulong)q1 << 32 | q0;
+ RightShift64(ref rem, d);
+ Debug.Assert((BigInteger)div == (BigInteger)a / (BigInteger)b);
+ Debug.Assert((BigInteger)rem == (BigInteger)a % (BigInteger)b);
+ return div;
+ }
+
+ private static uint DivRem128(out UInt128 rem, ref UInt128 a, ref UInt128 b)
+ {
+ var d = 32 - GetBitLength(b.r3);
+ UInt128 v;
+ LeftShift64(out v, ref b, d);
+ var r4 = (uint)LeftShift64(out rem, ref a, d);
+ var r3 = rem.r3;
+ var r2 = rem.r2;
+ var r1 = rem.r1;
+ var r0 = rem.r0;
+ var div = DivRem(r4, ref r3, ref r2, ref r1, ref r0, v.r3, v.r2, v.r1, v.r0);
+ Create(out rem, r0, r1, r2, r3);
+ RightShift64(ref rem, d);
+ Debug.Assert((BigInteger)div == (BigInteger)a / (BigInteger)b);
+ Debug.Assert((BigInteger)rem == (BigInteger)a % (BigInteger)b);
+ return div;
+ }
+
+ private static void Remainder192(out UInt128 c, ref UInt256 a, ref UInt128 b)
+ {
+ var d = 32 - GetBitLength(b.r2);
+ UInt128 v;
+ LeftShift64(out v, ref b, d);
+ var v1 = v.r2;
+ var v2 = v.r1;
+ var v3 = v.r0;
+ UInt256 rem;
+ LeftShift64(out rem, ref a, d);
+ var r6 = rem.r6;
+ var r5 = rem.r5;
+ var r4 = rem.r4;
+ var r3 = rem.r3;
+ var r2 = rem.r2;
+ var r1 = rem.r1;
+ var r0 = rem.r0;
+ DivRem(r6, ref r5, ref r4, ref r3, v1, v2, v3);
+ DivRem(r5, ref r4, ref r3, ref r2, v1, v2, v3);
+ DivRem(r4, ref r3, ref r2, ref r1, v1, v2, v3);
+ DivRem(r3, ref r2, ref r1, ref r0, v1, v2, v3);
+ Create(out c, r0, r1, r2, 0);
+ RightShift64(ref c, d);
+ Debug.Assert((BigInteger)c == (BigInteger)a % (BigInteger)b);
+ }
+
+ private static void Remainder256(out UInt128 c, ref UInt256 a, ref UInt128 b)
+ {
+ var d = 32 - GetBitLength(b.r3);
+ UInt128 v;
+ LeftShift64(out v, ref b, d);
+ var v1 = v.r3;
+ var v2 = v.r2;
+ var v3 = v.r1;
+ var v4 = v.r0;
+ UInt256 rem;
+ var r8 = (uint)LeftShift64(out rem, ref a, d);
+ var r7 = rem.r7;
+ var r6 = rem.r6;
+ var r5 = rem.r5;
+ var r4 = rem.r4;
+ var r3 = rem.r3;
+ var r2 = rem.r2;
+ var r1 = rem.r1;
+ var r0 = rem.r0;
+ DivRem(r8, ref r7, ref r6, ref r5, ref r4, v1, v2, v3, v4);
+ DivRem(r7, ref r6, ref r5, ref r4, ref r3, v1, v2, v3, v4);
+ DivRem(r6, ref r5, ref r4, ref r3, ref r2, v1, v2, v3, v4);
+ DivRem(r5, ref r4, ref r3, ref r2, ref r1, v1, v2, v3, v4);
+ DivRem(r4, ref r3, ref r2, ref r1, ref r0, v1, v2, v3, v4);
+ Create(out c, r0, r1, r2, r3);
+ RightShift64(ref c, d);
+ Debug.Assert((BigInteger)c == (BigInteger)a % (BigInteger)b);
+ }
+
+ private static ulong Q(uint u0, uint u1, uint u2, uint v1, uint v2)
+ {
+ var u0u1 = (ulong)u0 << 32 | u1;
+ var qhat = u0 == v1 ? uint.MaxValue : u0u1 / v1;
+ var r = u0u1 - qhat * v1;
+ if (r == (uint)r && v2 * qhat > (r << 32 | u2))
+ {
+ --qhat;
+ r += v1;
+ if (r == (uint)r && v2 * qhat > (r << 32 | u2))
+ {
+ --qhat;
+ r += v1;
+ }
+ }
+ return qhat;
+ }
+
+ private static uint DivRem(uint u0, ref uint u1, ref uint u2, uint v1, uint v2)
+ {
+ var qhat = Q(u0, u1, u2, v1, v2);
+ var carry = qhat * v2;
+ var borrow = (long)u2 - (uint)carry;
+ carry >>= 32;
+ u2 = (uint)borrow;
+ borrow >>= 32;
+ carry += qhat * v1;
+ borrow += (long)u1 - (uint)carry;
+ carry >>= 32;
+ u1 = (uint)borrow;
+ borrow >>= 32;
+ borrow += (long)u0 - (uint)carry;
+ if (borrow != 0)
+ {
+ --qhat;
+ carry = (ulong)u2 + v2;
+ u2 = (uint)carry;
+ carry >>= 32;
+ carry += (ulong)u1 + v1;
+ u1 = (uint)carry;
+ }
+ return (uint)qhat;
+ }
+
+ private static uint DivRem(uint u0, ref uint u1, ref uint u2, ref uint u3, uint v1, uint v2, uint v3)
+ {
+ var qhat = Q(u0, u1, u2, v1, v2);
+ var carry = qhat * v3;
+ var borrow = (long)u3 - (uint)carry;
+ carry >>= 32;
+ u3 = (uint)borrow;
+ borrow >>= 32;
+ carry += qhat * v2;
+ borrow += (long)u2 - (uint)carry;
+ carry >>= 32;
+ u2 = (uint)borrow;
+ borrow >>= 32;
+ carry += qhat * v1;
+ borrow += (long)u1 - (uint)carry;
+ carry >>= 32;
+ u1 = (uint)borrow;
+ borrow >>= 32;
+ borrow += (long)u0 - (uint)carry;
+ if (borrow != 0)
+ {
+ --qhat;
+ carry = (ulong)u3 + v3;
+ u3 = (uint)carry;
+ carry >>= 32;
+ carry += (ulong)u2 + v2;
+ u2 = (uint)carry;
+ carry >>= 32;
+ carry += (ulong)u1 + v1;
+ u1 = (uint)carry;
+ }
+ return (uint)qhat;
+ }
+
+ private static uint DivRem(uint u0, ref uint u1, ref uint u2, ref uint u3, ref uint u4, uint v1, uint v2, uint v3, uint v4)
+ {
+ var qhat = Q(u0, u1, u2, v1, v2);
+ var carry = qhat * v4;
+ var borrow = (long)u4 - (uint)carry;
+ carry >>= 32;
+ u4 = (uint)borrow;
+ borrow >>= 32;
+ carry += qhat * v3;
+ borrow += (long)u3 - (uint)carry;
+ carry >>= 32;
+ u3 = (uint)borrow;
+ borrow >>= 32;
+ carry += qhat * v2;
+ borrow += (long)u2 - (uint)carry;
+ carry >>= 32;
+ u2 = (uint)borrow;
+ borrow >>= 32;
+ carry += qhat * v1;
+ borrow += (long)u1 - (uint)carry;
+ carry >>= 32;
+ u1 = (uint)borrow;
+ borrow >>= 32;
+ borrow += (long)u0 - (uint)carry;
+ if (borrow != 0)
+ {
+ --qhat;
+ carry = (ulong)u4 + v4;
+ u4 = (uint)carry;
+ carry >>= 32;
+ carry += (ulong)u3 + v3;
+ u3 = (uint)carry;
+ carry >>= 32;
+ carry += (ulong)u2 + v2;
+ u2 = (uint)carry;
+ carry >>= 32;
+ carry += (ulong)u1 + v1;
+ u1 = (uint)carry;
+ }
+ return (uint)qhat;
+ }
+
+ public static void ModAdd(out UInt128 c, ref UInt128 a, ref UInt128 b, ref UInt128 modulus)
+ {
+ Add(out c, ref a, ref b);
+ if (!LessThan(ref c, ref modulus) || LessThan(ref c, ref a) && LessThan(ref c, ref b))
+ Subtract(ref c, ref modulus);
+ }
+
+ public static void ModSub(out UInt128 c, ref UInt128 a, ref UInt128 b, ref UInt128 modulus)
+ {
+ Subtract(out c, ref a, ref b);
+ if (LessThan(ref a, ref b))
+ Add(ref c, ref modulus);
+ }
+
+ public static void ModMul(out UInt128 c, ref UInt128 a, ref UInt128 b, ref UInt128 modulus)
+ {
+ if (modulus.s1 == 0)
+ {
+ UInt128 product;
+ Multiply64(out product, a.s0, b.s0);
+ Create(out c, UInt128.Remainder(ref product, modulus.s0));
+ }
+ else
+ {
+ UInt256 product;
+ Multiply(out product, ref a, ref b);
+ Remainder(out c, ref product, ref modulus);
+ }
+ }
+
+ public static void ModMul(ref UInt128 a, ref UInt128 b, ref UInt128 modulus)
+ {
+ if (modulus.s1 == 0)
+ {
+ UInt128 product;
+ Multiply64(out product, a.s0, b.s0);
+ Create(out a, UInt128.Remainder(ref product, modulus.s0));
+ }
+ else
+ {
+ UInt256 product;
+ Multiply(out product, ref a, ref b);
+ Remainder(out a, ref product, ref modulus);
+ }
+ }
+
+ public static void ModPow(out UInt128 result, ref UInt128 value, ref UInt128 exponent, ref UInt128 modulus)
+ {
+ result = one;
+ var v = value;
+ var e = exponent.s0;
+ if (exponent.s1 != 0)
+ {
+ for (var i = 0; i < 64; i++)
+ {
+ if ((e & 1) != 0)
+ ModMul(ref result, ref v, ref modulus);
+ ModMul(ref v, ref v, ref modulus);
+ e >>= 1;
+ }
+ e = exponent.s1;
+ }
+ while (e != 0)
+ {
+ if ((e & 1) != 0)
+ ModMul(ref result, ref v, ref modulus);
+ if (e != 1)
+ ModMul(ref v, ref v, ref modulus);
+ e >>= 1;
+ }
+ Debug.Assert(BigInteger.ModPow(value, exponent, modulus) == result);
+ }
+
+ public static void Shift(out UInt128 c, ref UInt128 a, int d)
+ {
+ if (d < 0)
+ RightShift(out c, ref a, -d);
+ else
+ LeftShift(out c, ref a, d);
+ }
+
+ public static void ArithmeticShift(out UInt128 c, ref UInt128 a, int d)
+ {
+ if (d < 0)
+ ArithmeticRightShift(out c, ref a, -d);
+ else
+ LeftShift(out c, ref a, d);
+ }
+
+ public static ulong LeftShift64(out UInt128 c, ref UInt128 a, int d)
+ {
+ if (d == 0)
+ {
+ c = a;
+ return 0;
+ }
+ var dneg = 64 - d;
+ c.s1 = a.s1 << d | a.s0 >> dneg;
+ c.s0 = a.s0 << d;
+ return a.s1 >> dneg;
+ }
+
+ private static ulong LeftShift64(out UInt256 c, ref UInt256 a, int d)
+ {
+ if (d == 0)
+ {
+ c = a;
+ return 0;
+ }
+ var dneg = 64 - d;
+ c.s3 = a.s3 << d | a.s2 >> dneg;
+ c.s2 = a.s2 << d | a.s1 >> dneg;
+ c.s1 = a.s1 << d | a.s0 >> dneg;
+ c.s0 = a.s0 << d;
+ return a.s3 >> dneg;
+ }
+
+ public static void LeftShift(out UInt128 c, ref UInt128 a, int b)
+ {
+ if (b < 64)
+ LeftShift64(out c, ref a, b);
+ else if (b == 64)
+ {
+ c.s0 = 0;
+ c.s1 = a.s0;
+ return;
+ }
+ else
+ {
+ c.s0 = 0;
+ c.s1 = a.s0 << (b - 64);
+ }
+ }
+
+ public static void RightShift64(out UInt128 c, ref UInt128 a, int b)
+ {
+ if (b == 0)
+ c = a;
+ else
+ {
+ c.s0 = a.s0 >> b | a.s1 << (64 - b);
+ c.s1 = a.s1 >> b;
+ }
+ }
+
+ public static void RightShift(out UInt128 c, ref UInt128 a, int b)
+ {
+ if (b < 64)
+ RightShift64(out c, ref a, b);
+ else if (b == 64)
+ {
+ c.s0 = a.s1;
+ c.s1 = 0;
+ }
+ else
+ {
+ c.s0 = a.s1 >> (b - 64);
+ c.s1 = 0;
+ }
+ }
+
+ public static void ArithmeticRightShift64(out UInt128 c, ref UInt128 a, int b)
+ {
+ if (b == 0)
+ c = a;
+ else
+ {
+ c.s0 = a.s0 >> b | a.s1 << (64 - b);
+ c.s1 = (ulong)((long)a.s1 >> b);
+ }
+ }
+
+ public static void ArithmeticRightShift(out UInt128 c, ref UInt128 a, int b)
+ {
+ if (b < 64)
+ ArithmeticRightShift64(out c, ref a, b);
+ else if (b == 64)
+ {
+ c.s0 = a.s1;
+ c.s1 = (ulong)((long)a.s1 >> 63);
+ }
+ else
+ {
+ c.s0 = a.s1 >> (b - 64);
+ c.s1 = (ulong)((long)a.s1 >> 63);
+ }
+ }
+
+ public static void And(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ c.s0 = a.s0 & b.s0;
+ c.s1 = a.s1 & b.s1;
+ }
+
+ public static void Or(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ c.s0 = a.s0 | b.s0;
+ c.s1 = a.s1 | b.s1;
+ }
+
+ public static void ExclusiveOr(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ c.s0 = a.s0 ^ b.s0;
+ c.s1 = a.s1 ^ b.s1;
+ }
+
+ public static void Not(out UInt128 c, ref UInt128 a)
+ {
+ c.s0 = ~a.s0;
+ c.s1 = ~a.s1;
+ }
+
+ public static void Negate(ref UInt128 a)
+ {
+ var s0 = a.s0;
+ a.s0 = 0 - s0;
+ a.s1 = 0 - a.s1;
+ if (s0 > 0)
+ --a.s1;
+ }
+
+
+ public static void Negate(out UInt128 c, ref UInt128 a)
+ {
+ c.s0 = 0 - a.s0;
+ c.s1 = 0 - a.s1;
+ if (a.s0 > 0)
+ --c.s1;
+ Debug.Assert((BigInteger)c == (BigInteger)(~a + 1));
+ }
+
+ public static void Pow(out UInt128 result, ref UInt128 value, uint exponent)
+ {
+ result = one;
+ while (exponent != 0)
+ {
+
+ if ((exponent & 1) != 0)
+ {
+ var previous = result;
+ Multiply(out result, ref previous, ref value);
+ }
+ if (exponent != 1)
+ {
+ var previous = value;
+ Square(out value, ref previous);
+ }
+ exponent >>= 1;
+ }
+ }
+
+ public static UInt128 Pow(UInt128 value, uint exponent)
+ {
+ UInt128 result;
+ Pow(out result, ref value, exponent);
+ return result;
+ }
+
+ private const int maxRepShift = 53;
+ private static readonly ulong maxRep = (ulong)1 << maxRepShift;
+ private static readonly UInt128 maxRepSquaredHigh = (ulong)1 << (2 * maxRepShift - 64);
+
+ public static ulong FloorSqrt(UInt128 a)
+ {
+ if (a.s1 == 0 && a.s0 <= maxRep)
+ return (ulong)Math.Sqrt(a.s0);
+ var s = (ulong)Math.Sqrt(ConvertToDouble(ref a));
+ if (a.s1 < maxRepSquaredHigh)
+ {
+ UInt128 s2;
+ Square(out s2, s);
+ var r = a.s0 - s2.s0;
+ if (r > long.MaxValue)
+ --s;
+ else if (r - (s << 1) <= long.MaxValue)
+ ++s;
+ Debug.Assert((BigInteger)s * s <= a && (BigInteger)(s + 1) * (s + 1) > a);
+ return s;
+ }
+ s = FloorSqrt(ref a, s);
+ Debug.Assert((BigInteger)s * s <= a && (BigInteger)(s + 1) * (s + 1) > a);
+ return s;
+ }
+
+ public static ulong CeilingSqrt(UInt128 a)
+ {
+ if (a.s1 == 0 && a.s0 <= maxRep)
+ return (ulong)Math.Ceiling(Math.Sqrt(a.s0));
+ var s = (ulong)Math.Ceiling(Math.Sqrt(ConvertToDouble(ref a)));
+ if (a.s1 < maxRepSquaredHigh)
+ {
+ UInt128 s2;
+ Square(out s2, s);
+ var r = s2.s0 - a.s0;
+ if (r > long.MaxValue)
+ ++s;
+ else if (r - (s << 1) <= long.MaxValue)
+ --s;
+ Debug.Assert((BigInteger)(s - 1) * (s - 1) < a && (BigInteger)s * s >= a);
+ return s;
+ }
+ s = FloorSqrt(ref a, s);
+ UInt128 square;
+ Square(out square, s);
+ if (square.S0 != a.S0 || square.S1 != a.S1)
+ ++s;
+ Debug.Assert((BigInteger)(s - 1) * (s - 1) < a && (BigInteger)s * s >= a);
+ return s;
+ }
+
+ private static ulong FloorSqrt(ref UInt128 a, ulong s)
+ {
+ var sprev = (ulong)0;
+ UInt128 div;
+ UInt128 sum;
+ while (true)
+ {
+ // Equivalent to:
+ // snext = (a / s + s) / 2;
+ Divide(out div, ref a, s);
+ Add(out sum, ref div, s);
+ var snext = sum.S0 >> 1;
+ if (sum.S1 != 0)
+ snext |= (ulong)1 << 63;
+ if (snext == sprev)
+ {
+ if (snext < s)
+ s = snext;
+ break;
+ }
+ sprev = s;
+ s = snext;
+ }
+ return s;
+ }
+
+ public static ulong FloorCbrt(UInt128 a)
+ {
+ var s = (ulong)Math.Pow(ConvertToDouble(ref a), (double)1 / 3);
+ UInt128 s3;
+ Cube(out s3, s);
+ if (a < s3)
+ --s;
+ else
+ {
+ UInt128 sum;
+ Multiply(out sum, 3 * s, s + 1);
+ UInt128 diff;
+ Subtract(out diff, ref a, ref s3);
+ if (LessThan(ref sum, ref diff))
+ ++s;
+ }
+ Debug.Assert((BigInteger)s * s * s <= a && (BigInteger)(s + 1) * (s + 1) * (s + 1) > a);
+ return s;
+ }
+
+ public static ulong CeilingCbrt(UInt128 a)
+ {
+ var s = (ulong)Math.Ceiling(Math.Pow(ConvertToDouble(ref a), (double)1 / 3));
+ UInt128 s3;
+ Cube(out s3, s);
+ if (s3 < a)
+ ++s;
+ else
+ {
+ UInt128 sum;
+ Multiply(out sum, 3 * s, s + 1);
+ UInt128 diff;
+ Subtract(out diff, ref s3, ref a);
+ if (LessThan(ref sum, ref diff))
+ --s;
+ }
+ Debug.Assert((BigInteger)(s - 1) * (s - 1) * (s - 1) < a && (BigInteger)s * s * s >= a);
+ return s;
+ }
+
+ public static UInt128 Min(UInt128 a, UInt128 b)
+ {
+ if (LessThan(ref a, ref b))
+ return a;
+ return b;
+ }
+
+ public static UInt128 Max(UInt128 a, UInt128 b)
+ {
+ if (LessThan(ref b, ref a))
+ return a;
+ return b;
+ }
+
+ public static double Log(UInt128 a)
+ {
+ return Log(a, Math.E);
+ }
+
+ public static double Log10(UInt128 a)
+ {
+ return Log(a, 10);
+ }
+
+ public static double Log(UInt128 a, double b)
+ {
+ return Math.Log(ConvertToDouble(ref a), b);
+ }
+
+ public static UInt128 Add(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Add(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 Subtract(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Subtract(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 Multiply(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Multiply(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 Divide(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Divide(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 Remainder(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ Remainder(out c, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 DivRem(UInt128 a, UInt128 b, out UInt128 remainder)
+ {
+ UInt128 c;
+ Divide(out c, ref a, ref b);
+ Remainder(out remainder, ref a, ref b);
+ return c;
+ }
+
+ public static UInt128 ModAdd(UInt128 a, UInt128 b, UInt128 modulus)
+ {
+ UInt128 c;
+ ModAdd(out c, ref a, ref b, ref modulus);
+ return c;
+ }
+
+ public static UInt128 ModSub(UInt128 a, UInt128 b, UInt128 modulus)
+ {
+ UInt128 c;
+ ModSub(out c, ref a, ref b, ref modulus);
+ return c;
+ }
+
+ public static UInt128 ModMul(UInt128 a, UInt128 b, UInt128 modulus)
+ {
+ UInt128 c;
+ ModMul(out c, ref a, ref b, ref modulus);
+ return c;
+ }
+
+ public static UInt128 ModPow(UInt128 value, UInt128 exponent, UInt128 modulus)
+ {
+ UInt128 result;
+ ModPow(out result, ref value, ref exponent, ref modulus);
+ return result;
+ }
+
+ public static UInt128 Negate(UInt128 a)
+ {
+ UInt128 c;
+ Negate(out c, ref a);
+ return c;
+ }
+
+ public static UInt128 GreatestCommonDivisor(UInt128 a, UInt128 b)
+ {
+ UInt128 c;
+ GreatestCommonDivisor(out c, ref a, ref b);
+ return c;
+ }
+
+ private static void RightShift64(ref UInt128 c, int d)
+ {
+ if (d == 0)
+ return;
+ c.s0 = c.s1 << (64 - d) | c.s0 >> d;
+ c.s1 >>= d;
+ }
+
+ public static void RightShift(ref UInt128 c, int d)
+ {
+ if (d < 64)
+ RightShift64(ref c, d);
+ else
+ {
+ c.s0 = c.s1 >> (d - 64);
+ c.s1 = 0;
+ }
+ }
+
+ public static void Shift(ref UInt128 c, int d)
+ {
+ if (d < 0)
+ RightShift(ref c, -d);
+ else
+ LeftShift(ref c, d);
+ }
+
+ public static void ArithmeticShift(ref UInt128 c, int d)
+ {
+ if (d < 0)
+ ArithmeticRightShift(ref c, -d);
+ else
+ LeftShift(ref c, d);
+ }
+
+ public static void RightShift(ref UInt128 c)
+ {
+ c.s0 = c.s1 << 63 | c.s0 >> 1;
+ c.s1 >>= 1;
+ }
+
+ private static void ArithmeticRightShift64(ref UInt128 c, int d)
+ {
+ if (d == 0)
+ return;
+ c.s0 = c.s1 << (64 - d) | c.s0 >> d;
+ c.s1 = (ulong)((long)c.s1 >> d);
+ }
+
+ public static void ArithmeticRightShift(ref UInt128 c, int d)
+ {
+ if (d < 64)
+ ArithmeticRightShift64(ref c, d);
+ else
+ {
+ c.s0 = (ulong)((long)c.s1 >> (d - 64));
+ c.s1 = 0;
+ }
+ }
+
+ public static void ArithmeticRightShift(ref UInt128 c)
+ {
+ c.s0 = c.s1 << 63 | c.s0 >> 1;
+ c.s1 = (ulong)((long)c.s1 >> 1);
+ }
+
+ private static ulong LeftShift64(ref UInt128 c, int d)
+ {
+ if (d == 0)
+ return 0;
+ var dneg = 64 - d;
+ var result = c.s1 >> dneg;
+ c.s1 = c.s1 << d | c.s0 >> dneg;
+ c.s0 <<= d;
+ return result;
+ }
+
+ public static void LeftShift(ref UInt128 c, int d)
+ {
+ if (d < 64)
+ LeftShift64(ref c, d);
+ else
+ {
+ c.s1 = c.s0 << (d - 64);
+ c.s0 = 0;
+ }
+ }
+
+ public static void LeftShift(ref UInt128 c)
+ {
+ c.s1 = c.s1 << 1 | c.s0 >> 63;
+ c.s0 <<= 1;
+ }
+
+ public static void Swap(ref UInt128 a, ref UInt128 b)
+ {
+ var as0 = a.s0;
+ var as1 = a.s1;
+ a.s0 = b.s0;
+ a.s1 = b.s1;
+ b.s0 = as0;
+ b.s1 = as1;
+ }
+
+ public static void GreatestCommonDivisor(out UInt128 c, ref UInt128 a, ref UInt128 b)
+ {
+ // Check whether one number is > 64 bits and the other is <= 64 bits and both are non-zero.
+ UInt128 a1, b1;
+ if ((a.s1 == 0) != (b.s1 == 0) && !a.IsZero && !b.IsZero)
+ {
+ // Perform a normal step so that both a and b are <= 64 bits.
+ if (LessThan(ref a, ref b))
+ {
+ a1 = a;
+ Remainder(out b1, ref b, ref a);
+ }
+ else
+ {
+ b1 = b;
+ Remainder(out a1, ref a, ref b);
+ }
+ }
+ else
+ {
+ a1 = a;
+ b1 = b;
+ }
+
+ // Make sure neither is zero.
+ if (a1.IsZero)
+ {
+ c = b1;
+ return;
+ }
+ if (b1.IsZero)
+ {
+ c = a1;
+ return;
+ }
+
+ // Ensure a >= b.
+ if (LessThan(ref a1, ref b1))
+ Swap(ref a1, ref b1);
+
+ // Lehmer-Euclid algorithm.
+ // See: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.31.693
+ while (a1.s1 != 0 && !b.IsZero)
+ {
+ // Extract the high 63 bits of a and b.
+ var norm = 63 - GetBitLength(a1.s1);
+ UInt128 ahat, bhat;
+ Shift(out ahat, ref a1, norm);
+ Shift(out bhat, ref b1, norm);
+ var uhat = (long)ahat.s1;
+ var vhat = (long)bhat.s1;
+
+ // Check whether q exceeds single-precision.
+ if (vhat == 0)
+ {
+ // Perform a normal step and try again.
+ UInt128 rem;
+ Remainder(out rem, ref a1, ref b1);
+ a1 = b1;
+ b1 = rem;
+ continue;
+ }
+
+ // Perform steps using signed single-precision arithmetic.
+ var x0 = (long)1;
+ var y0 = (long)0;
+ var x1 = (long)0;
+ var y1 = (long)1;
+ var even = true;
+ while (true)
+ {
+ // Calculate quotient, cosquence pair, and update uhat and vhat.
+ var q = uhat / vhat;
+ var x2 = x0 - q * x1;
+ var y2 = y0 - q * y1;
+ var t = uhat;
+ uhat = vhat;
+ vhat = t - q * vhat;
+ even = !even;
+
+ // Apply Jebelean's termination condition
+ // to check whether q is valid.
+ if (even)
+ {
+ if (vhat < -x2 || uhat - vhat < y2 - y1)
+ break;
+ }
+ else
+ {
+ if (vhat < -y2 || uhat - vhat < x2 - x1)
+ break;
+ }
+
+ // Adjust cosequence history.
+ x0 = x1; y0 = y1; x1 = x2; y1 = y2;
+ }
+
+ // Check whether a normal step is necessary.
+ if (x0 == 1 && y0 == 0)
+ {
+ UInt128 rem;
+ Remainder(out rem, ref a1, ref b1);
+ a1 = b1;
+ b1 = rem;
+ continue;
+ }
+
+ // Back calculate a and b from the last valid cosequence pairs.
+ UInt128 anew, bnew;
+ if (even)
+ {
+ AddProducts(out anew, y0, ref b1, x0, ref a1);
+ AddProducts(out bnew, x1, ref a1, y1, ref b1);
+ }
+ else
+ {
+ AddProducts(out anew, x0, ref a1, y0, ref b1);
+ AddProducts(out bnew, y1, ref b1, x1, ref a1);
+ }
+ a1 = anew;
+ b1 = bnew;
+ }
+
+ // Check whether we have any 64 bit work left.
+ if (!b1.IsZero)
+ {
+ var a2 = a1.s0;
+ var b2 = b1.s0;
+
+ // Perform 64 bit steps.
+ while (a2 > uint.MaxValue && b2 != 0)
+ {
+ var t = a2 % b2;
+ a2 = b2;
+ b2 = t;
+ }
+
+ // Check whether we have any 32 bit work left.
+ if (b2 != 0)
+ {
+ var a3 = (uint)a2;
+ var b3 = (uint)b2;
+
+ // Perform 32 bit steps.
+ while (b3 != 0)
+ {
+ var t = a3 % b3;
+ a3 = b3;
+ b3 = t;
+ }
+
+ Create(out c, a3);
+ }
+ else
+ Create(out c, a2);
+ }
+ else
+ c = a1;
+ }
+
+ private static void AddProducts(out UInt128 result, long x, ref UInt128 u, long y, ref UInt128 v)
+ {
+ // Compute x * u + y * v assuming y is negative and the result is positive and fits in 128 bits.
+ UInt128 product1;
+ Multiply(out product1, ref u, (ulong)x);
+ UInt128 product2;
+ Multiply(out product2, ref v, (ulong)(-y));
+ Subtract(out result, ref product1, ref product2);
+ }
+
+ public static int Compare(UInt128 a, UInt128 b)
+ {
+ return a.CompareTo(b);
+ }
+
+ private static byte[] bitLength = Enumerable.Range(0, byte.MaxValue + 1)
+ .Select(value =>
+ {
+ int count;
+ for (count = 0; value != 0; count++)
+ value >>= 1;
+ return (byte)count;
+ }).ToArray();
+
+ private static int GetBitLength(uint value)
+ {
+ var tt = value >> 16;
+ if (tt != 0)
+ {
+ var t = tt >> 8;
+ if (t != 0)
+ return bitLength[t] + 24;
+ return bitLength[tt] + 16;
+ }
+ else
+ {
+ var t = value >> 8;
+ if (t != 0)
+ return bitLength[t] + 8;
+ return bitLength[value];
+ }
+ }
+
+ private static int GetBitLength(ulong value)
+ {
+ var r1 = value >> 32;
+ if (r1 != 0)
+ return GetBitLength((uint)r1) + 32;
+ return GetBitLength((uint)value);
+ }
+
+ public static void Reduce(out UInt128 w, ref UInt128 u, ref UInt128 v, ref UInt128 n, ulong k0)
+ {
+ UInt128 carry;
+ Multiply64(out carry, u.s0, v.s0);
+ var t0 = carry.s0;
+ Multiply64(out carry, u.s1, v.s0, carry.s1);
+ var t1 = carry.s0;
+ var t2 = carry.s1;
+
+ var m = t0 * k0;
+ Multiply64(out carry, m, n.s1, MultiplyHigh64(m, n.s0, t0));
+ Add(ref carry, t1);
+ t0 = carry.s0;
+ Add(out carry, carry.s1, t2);
+ t1 = carry.s0;
+ t2 = carry.s1;
+
+ Multiply64(out carry, u.s0, v.s1, t0);
+ t0 = carry.s0;
+ Multiply64(out carry, u.s1, v.s1, carry.s1);
+ Add(ref carry, t1);
+ t1 = carry.s0;
+ Add(out carry, carry.s1, t2);
+ t2 = carry.s0;
+ var t3 = carry.s1;
+
+ m = t0 * k0;
+ Multiply64(out carry, m, n.s1, MultiplyHigh64(m, n.s0, t0));
+ Add(ref carry, t1);
+ t0 = carry.s0;
+ Add(out carry, carry.s1, t2);
+ t1 = carry.s0;
+ t2 = t3 + carry.s1;
+
+ Create(out w, t0, t1);
+ if (t2 != 0 || !LessThan(ref w, ref n))
+ Subtract(ref w, ref n);
+ }
+
+ public static void Reduce(out UInt128 w, ref UInt128 t, ref UInt128 n, ulong k0)
+ {
+ UInt128 carry;
+ var t0 = t.s0;
+ var t1 = t.s1;
+ var t2 = (ulong)0;
+
+ for (var i = 0; i < 2; i++)
+ {
+ var m = t0 * k0;
+ Multiply64(out carry, m, n.s1, MultiplyHigh64(m, n.s0, t0));
+ Add(ref carry, t1);
+ t0 = carry.s0;
+ Add(out carry, carry.s1, t2);
+ t1 = carry.s0;
+ t2 = carry.s1;
+ }
+
+ Create(out w, t0, t1);
+ if (t2 != 0 || !LessThan(ref w, ref n))
+ Subtract(ref w, ref n);
+ }
+
+ public static UInt128 Reduce(UInt128 u, UInt128 v, UInt128 n, ulong k0)
+ {
+ UInt128 w;
+ Reduce(out w, ref u, ref v, ref n, k0);
+ return w;
+ }
+
+ public static UInt128 Reduce(UInt128 t, UInt128 n, ulong k0)
+ {
+ UInt128 w;
+ Reduce(out w, ref t, ref n, k0);
+ return w;
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/Dirichlet.Numerics/license.txt b/TBF_V2/Sources/TBF/Dirichlet.Numerics/license.txt
new file mode 100644
index 00000000..5e6188c6
--- /dev/null
+++ b/TBF_V2/Sources/TBF/Dirichlet.Numerics/license.txt
@@ -0,0 +1,13 @@
+Copyright 2014 Rick Sladkey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GemCard/APDUCommand.cs b/TBF_V2/Sources/TBF/GemCard/APDUCommand.cs
new file mode 100644
index 00000000..6b32fb36
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/APDUCommand.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Text;
+
+namespace GemCard
+{
+ ///
+ /// This class represents a command APDU
+ ///
+ public class APDUCommand
+ {
+ ///
+ /// Minimun size of an APDU command in bytes
+ ///
+ public const int APDU_MIN_LENGTH = 4;
+
+ public byte Class; /// Class byte
+ public byte Ins; /// Instruction byte
+ public byte P1; /// Parameter P1 byte
+ public byte P2; /// Parameter P2 byte
+ public byte[] Data; /// Data to send to the card if any, null if no data to send
+ public byte Le; /// Number of data expected, 0 if none
+
+ ///
+ /// Constructor
+ ///
+ /// Class byte
+ /// Instruction byte
+ /// Parameter P1 byte
+ /// Parameter P2 byte
+ /// Data to send to the card if any, null if no data to send
+ /// Number of data expected, 0 if none
+ public APDUCommand(byte bCla, byte bIns, byte bP1, byte bP2, byte[] baData, byte bLe)
+ {
+ this.Class = bCla;
+ this.Ins = bIns;
+ this.P1 = bP1;
+ this.P2 = bP2;
+ this.Data = baData;
+ this.Le = bLe;
+ }
+
+
+ ///
+ /// Update the current APDU with selected parameters
+ ///
+ /// APDU parameters
+ public void Update(APDUParam apduParam)
+ {
+ if (apduParam.UseData) Data = apduParam.Data;
+ if (apduParam.UseLe) Le = apduParam.Le;
+ if (apduParam.UseP1) P1 = apduParam.P1;
+ if (apduParam.UseP2) P2 = apduParam.P2;
+ if (apduParam.UseChannel) Class += apduParam.Channel;
+ }
+
+ ///
+ /// Overrides the ToString method to format to a string the APDUCommand object
+ ///
+ ///
+ public override string ToString()
+ {
+ string strData = null;
+ byte bLc = 0;
+ byte bP3 = Le;
+
+ if (Data != null)
+ {
+ StringBuilder sData = new StringBuilder(Data.Length * 2);
+ for (int nI = 0; nI < Data.Length; nI++)
+ {
+ sData.AppendFormat("{0:X02}", Data[nI]);
+ }
+
+ strData = "Data=" + sData.ToString();
+ bLc = (byte) Data.Length;
+ bP3 = bLc;
+ }
+
+ //string strApdu = string.Format("Class={0:X02} Ins={1:X02} P1={2:X02} P2={3:X02} Le={4:X02} Lc={5:X02} ",
+ //m_bCla, m_bIns, m_bP1, m_bP2, m_bLe, bLc);
+ StringBuilder strApdu = new StringBuilder();
+
+ strApdu.AppendFormat("Class={0:X02} Ins={1:X02} P1={2:X02} P2={3:X02} P3={4:X02} ",
+ Class, Ins, P1, P2, bP3);
+
+ if (Data != null)
+ {
+ strApdu.Append(strData);
+ }
+
+ return strApdu.ToString();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/APDUParam.cs b/TBF_V2/Sources/TBF/GemCard/APDUParam.cs
new file mode 100644
index 00000000..a9be136f
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/APDUParam.cs
@@ -0,0 +1,147 @@
+using System;
+
+namespace GemCard
+{
+ ///
+ /// This class is used to update a set of parameters of an APDUCommand object
+ ///
+ public class APDUParam
+ {
+ byte bClass;
+ byte bChannel;
+ byte bP2;
+ byte bP1;
+
+ byte[] baData;
+ short nLe;
+
+ bool fUseP1;
+ bool fUseP2;
+ bool fChannel;
+ bool fData;
+ bool fClass;
+ bool fLe;
+
+ ///
+ /// Resets the current instance, all flags are set to false
+ ///
+ public void Reset()
+ {
+ bClass = 0;
+ bChannel = 0;
+ bP2 = 0;
+ bP1 = 0;
+
+ baData = null;
+ nLe = -1;
+
+ fUseP1 = false;
+ fUseP2 = false;
+ fChannel = false;
+ fData = false;
+ fClass = false;
+ fLe = false;
+ }
+
+ #region Constructors
+
+ public APDUParam()
+ {
+ Reset();
+ }
+
+ ///
+ /// Copy constructor (used for cloning)
+ ///
+ ///
+ public APDUParam(APDUParam param)
+ {
+ // Copy field
+ if (param.baData != null)
+ {
+ param.baData.CopyTo(baData, 0);
+ }
+
+ this.bClass = param.bClass;
+ this.bChannel = param.bChannel;
+ this.bP1 = param.bP1;
+ this.bP2 = param.bP2;
+ this.nLe = param.nLe;
+
+ // Copy flags field
+ this.fChannel = param.fChannel;
+ this.fClass = param.fClass;
+ this.fData = param.fData;
+ this.fLe = param.fLe;
+ this.fUseP1 = param.fUseP1;
+ this.fUseP2 = param.fUseP2;
+ }
+
+ public APDUParam(byte bClass, byte bP1, byte bP2, byte[] baData, short nLe)
+ {
+ this.Class = bClass;
+ this.P1 = bP1;
+ this.P2 = bP2;
+ this.Data = baData;
+ this.Le = (byte)nLe;
+ }
+
+ #endregion
+
+ ///
+ /// Clones the current APDUParam instance
+ ///
+ ///
+ public APDUParam Clone()
+ {
+ return new APDUParam(this);
+ }
+
+ #region Properties
+
+ public bool UseClass { get { return fClass; } }
+ public bool UseChannel { get { return fChannel; } }
+ public bool UseLe { get { return fLe; } }
+ public bool UseData { get { return fData; } }
+ public bool UseP1 { get { return fUseP1; } }
+ public bool UseP2 { get { return fUseP2; } }
+
+ public byte P1
+ {
+ get { return bP1; }
+ set { bP1 = value; fUseP1 = true; }
+ }
+
+ public byte P2
+ {
+ get { return bP2; }
+ set { bP2 = value; fUseP2 = true; }
+ }
+
+ public byte[] Data
+ {
+ get { return baData; }
+ set { baData = value; fData = true; }
+ }
+
+ public byte Le
+ {
+ get { return (byte)nLe; }
+ set { nLe = value; fLe = true; }
+ }
+
+ public byte Channel
+ {
+ get { return bChannel; }
+ set { bChannel = value; fChannel = true; }
+ }
+
+ public byte Class
+ {
+ get { return bClass; }
+ set { bClass = value; fClass = true; }
+ }
+
+ #endregion
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/APDUResponse.cs b/TBF_V2/Sources/TBF/GemCard/APDUResponse.cs
new file mode 100644
index 00000000..f54171a4
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/APDUResponse.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Text;
+
+namespace GemCard
+{
+ ///
+ /// This class represents the APDU response sent by the card
+ ///
+ public class APDUResponse
+ {
+ ///
+ /// Status bytes length
+ ///
+ public const int SW_LENGTH = 2;
+
+ ///
+ /// Response data. Contains the data sent by the card minus the 2 status bytes (SW1, SW2)
+ /// null if no data were sent by the card
+ ///
+ public byte[] Data;
+ public byte SW1;
+ public byte SW2;
+
+ ///
+ /// Status get property
+ ///
+ public ushort Status
+ {
+ get { return (ushort)(((short)SW1 << 8) + (short)SW2); }
+ }
+
+ ///
+ /// Constructor from the byte data sent back by the card
+ ///
+ /// Buffer of data from the card
+ public APDUResponse(byte[] baData)
+ {
+ if (baData.Length > SW_LENGTH)
+ {
+ Data = new byte[baData.Length - SW_LENGTH];
+
+ for (int nI = 0; nI < baData.Length - SW_LENGTH; nI++)
+ {
+ this.Data[nI] = baData[nI];
+ }
+ }
+
+ this.SW1 = baData[baData.Length - 2];
+ this.SW2 = baData[baData.Length - 1];
+ }
+
+ ///
+ /// Overrides the ToString method to format to a string the APDUResponse object
+ ///
+ ///
+ public override string ToString()
+ {
+ if (Data != null)
+ {
+ StringBuilder sData = new StringBuilder(Data.Length * 2);
+ for (int nI = 0; nI < Data.Length; nI++)
+ {
+ sData.AppendFormat("{0:X02}", Data[nI]);
+ }
+
+ return sData.ToString();
+ }
+ else
+ {
+ return string.Empty;
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/AssemblyInfo.cs b/TBF_V2/Sources/TBF/GemCard/AssemblyInfo.cs
new file mode 100644
index 00000000..9f89a328
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/AssemblyInfo.cs
@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project output directory which is
+// %Project Directory%\obj\. For example, if your KeyFile is
+// located in the project directory, you would specify the AssemblyKeyFile
+// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
diff --git a/TBF_V2/Sources/TBF/GemCard/CardBase.cs b/TBF_V2/Sources/TBF/GemCard/CardBase.cs
new file mode 100644
index 00000000..3c4ae310
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/CardBase.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace GemCard
+{
+ ///
+ /// Values for AttrId of SCardGetAttrib
+ ///
+ public class SCARD_ATTR_VALUE
+ {
+ private const uint
+ SCARD_CLASS_COMMUNICATIONS = 2,
+ SCARD_CLASS_PROTOCOL = 3,
+ SCARD_CLASS_MECHANICAL = 6,
+ SCARD_CLASS_VENDOR_DEFINED = 7,
+ SCARD_CLASS_IFD_PROTOCOL = 8,
+ SCARD_CLASS_ICC_STATE = 9,
+ SCARD_CLASS_SYSTEM = 0x7fff;
+
+ private static UInt32 SCardAttrValue(UInt32 attrClass, UInt32 val)
+ {
+ return (attrClass << 16) | val;
+ }
+
+ public static UInt32 CHANNEL_ID { get { return SCardAttrValue(SCARD_CLASS_COMMUNICATIONS, 0x0110); } }
+
+ public static UInt32 CHARACTERISTICS { get { return SCardAttrValue(SCARD_CLASS_MECHANICAL, 0x0150); } }
+
+ public static UInt32 CURRENT_PROTOCOL_TYPE { get { return SCardAttrValue(SCARD_CLASS_IFD_PROTOCOL, 0x0201); } }
+
+ public static UInt32 DEVICE_UNIT { get { return SCardAttrValue(SCARD_CLASS_SYSTEM, 0x0001); } }
+ public static UInt32 DEVICE_FRIENDLY_NAME { get { return SCardAttrValue(SCARD_CLASS_SYSTEM, 0x0003); } }
+ public UInt32 DEVICE_SYSTEM_NAME { get { return SCardAttrValue(SCARD_CLASS_SYSTEM, 0x0004); } }
+
+ public static UInt32 ICC_PRESENCE { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0300); } }
+ public static UInt32 ICC_INTERFACE_STATUS { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0301); } }
+ public static UInt32 ATR_STRING { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0303); } }
+ public static UInt32 ICC_TYPE_PER_ATR { get { return SCardAttrValue(SCARD_CLASS_ICC_STATE, 0x0304); } }
+
+ public static UInt32 PROTOCOL_TYPES { get { return SCardAttrValue(SCARD_CLASS_PROTOCOL, 0x0120); } }
+
+ public static UInt32 VENDOR_NAME { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0100); } }
+ public static UInt32 VENDOR_IFD_TYPE { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0101); } }
+ public static UInt32 VENDOR_IFD_VERSION { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0102); } }
+ public static UInt32 VENDOR_IFD_SERIAL_NO { get { return SCardAttrValue(SCARD_CLASS_VENDOR_DEFINED, 0x0103); } }
+ }
+
+ ///
+ /// Abstract class that adds a basic event management to the ICard interface.
+ ///
+ abstract public class CardBase : ICard
+ {
+ protected const uint INFINITE = 0xFFFFFFFF;
+ protected const uint WAIT_TIME = 250;
+
+ protected bool m_bRunCardDetection = true;
+ protected Thread m_thread = null;
+
+ ///
+ /// Event handler for the card insertion
+ ///
+ public event EventHandler OnCardInserted = null;
+
+ ///
+ /// Event handler for the card removal
+ ///
+ public event EventHandler OnCardRemoved = null;
+
+ ~CardBase()
+ {
+ // Stop any eventual card detection thread
+ StopCardEvents();
+ }
+
+ #region Abstract method that implement the ICard interface
+ abstract public string[] ListReaders();
+ abstract public void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols);
+ abstract public void Disconnect(DISCONNECT Disposition);
+ abstract public APDUResponse Transmit(APDUCommand ApduCmd);
+ abstract public void BeginTransaction();
+ abstract public void EndTransaction(DISCONNECT Disposition);
+ abstract public byte[] GetAttribute(UInt32 AttribId);
+ #endregion
+
+ ///
+ /// This method should start a thread that checks for card insertion or removal
+ ///
+ ///
+ public void StartCardEvents(string Reader)
+ {
+ if (m_thread == null)
+ {
+ m_bRunCardDetection = true;
+
+ m_thread = new Thread(new ParameterizedThreadStart(RunCardDetection));
+ m_thread.Start(Reader);
+ }
+ }
+
+ ///
+ /// Stops the card events thread
+ ///
+ public void StopCardEvents()
+ {
+ if (m_thread != null)
+ {
+ int
+ nTimeOut = 10,
+ nCount = 0;
+ bool m_bStop = false;
+ m_bRunCardDetection = false;
+
+ do
+ {
+ if (nCount > nTimeOut)
+ {
+ m_thread.Abort();
+ break;
+ }
+
+ if (m_thread.ThreadState == ThreadState.Aborted)
+ m_bStop = true;
+
+ if (m_thread.ThreadState == ThreadState.Stopped)
+ m_bStop = true;
+
+ Thread.Sleep(200);
+ ++nCount; // Manage time out
+ }
+ while (!m_bStop);
+
+ m_thread = null;
+ }
+ }
+
+ ///
+ /// This function must implement a card detection mechanism.
+ ///
+ /// When card insertion is detected, it must call the method CardInserted()
+ /// When card removal is detected, it must call the method CardRemoved()
+ ///
+ ///
+ /// Name of the reader to scan for card event
+ abstract protected void RunCardDetection(object Reader);
+
+ #region Event methods
+
+ protected void CardInserted(object sender, CardInsertedEventArgs args)
+ {
+ if (OnCardInserted != null) OnCardInserted(sender, args);
+ }
+
+ protected void CardRemoved(object sender, CardRemovedEventArgs args)
+ {
+ if (OnCardRemoved != null) OnCardRemoved(sender, args);
+ }
+
+ #endregion
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/CardCOM.cs b/TBF_V2/Sources/TBF/GemCard/CardCOM.cs
new file mode 100644
index 00000000..26269999
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/CardCOM.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Runtime.InteropServices;
+using SCARDSSPLib;
+using GemCardExLib;
+
+namespace GemCard
+{
+ ///
+ /// Implements the ICard interface using the SCard COM objects from Microsoft and SCardDatabaseEx object
+ /// for the ListReaders function.
+ ///
+ public class CardCOM : CardBase
+ {
+ private ISCard m_itfCard = null;
+
+ ///
+ /// Default constructor
+ ///
+ public CardCOM()
+ {
+ // Create the SCard object
+ m_itfCard = new CSCardClass();
+ }
+
+ #region ICard Members
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardListReaders(SCARDCONTEXT hContext,
+ /// LPCTSTR mszGroups,
+ /// LPTSTR mszReaders,
+ /// LPDWORD pcchReaders
+ /// );
+ ///
+ /// A string array of the readers
+ public override string[] ListReaders()
+ {
+ ISCardDatabaseEx itfCardBase = new SCardDatabaseEx();
+
+ return (string[]) itfCardBase.ListReaders();
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardConnect(
+ /// IN SCARDCONTEXT hContext,
+ /// IN LPCTSTR szReader,
+ /// IN DWORD dwShareMode,
+ /// IN DWORD dwPreferredProtocols,
+ /// OUT LPSCARDHANDLE phCard,
+ /// OUT LPDWORD pdwActiveProtocol
+ /// );
+ ///
+ ///
+ ///
+ ///
+ public override void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols)
+ {
+ // Calls AttachReader to connect to the card
+ m_itfCard.AttachByReader(Reader, (SCARD_SHARE_MODES) ShareMode, (SCARD_PROTOCOLS) PreferredProtocols);
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardDisconnect(
+ /// IN SCARDHANDLE hCard,
+ /// IN DWORD dwDisposition
+ /// );
+ ///
+ ///
+ public override void Disconnect(DISCONNECT Disposition)
+ {
+ // Off the connection with the card
+ m_itfCard.Detach((SCARD_DISPOSITIONS) Disposition);
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardTransmit(
+ /// SCARDHANDLE hCard,
+ /// LPCSCARD_I0_REQUEST pioSendPci,
+ /// LPCBYTE pbSendBuffer,
+ /// DWORD cbSendLength,
+ /// LPSCARD_IO_REQUEST pioRecvPci,
+ /// LPBYTE pbRecvBuffer,
+ /// LPDWORD pcbRecvLength
+ /// );
+ ///
+ /// APDUCommand object with the APDU to send to the card
+ /// An APDUResponse object with the response from the card
+ public override APDUResponse Transmit(APDUCommand ApduCmd)
+ {
+ CSCardCmd itfCmd = new CSCardCmdClass();
+ CByteBuffer itfData = new CByteBufferClass();
+ int nLe = ApduCmd.Le;
+
+ if (ApduCmd.Data == null)
+ {
+ itfData.SetSize(0);
+ }
+ else
+ {
+ int nWrite = 0;
+
+ itfData.SetSize(ApduCmd.Data.Length);
+ itfData.Write(ref ApduCmd.Data[0], ApduCmd.Data.Length, ref nWrite);
+ }
+
+ // Build the APDU command
+ itfCmd.BuildCmd(ApduCmd.Class, ApduCmd.Ins, ApduCmd.P1, ApduCmd.P2, itfData, ref nLe);
+
+ // Send the command
+ m_itfCard.Transaction(ref itfCmd);
+
+ // Analyse the response
+ int nRead = 0;
+ byte[] pbResp = new byte[itfCmd.ApduReplyLength];
+
+ itfCmd.ApduReply.Read(ref pbResp[0], itfCmd.ApduReplyLength, ref nRead);
+
+ return new APDUResponse(pbResp);
+ }
+
+ ///
+ /// Wraps the PSCS function
+ /// LONG SCardBeginTransaction(
+ /// SCARDHANDLE hCard
+ // );
+ /// This function is not supported in the COM implementation
+ ///
+ public override void BeginTransaction()
+ {
+ throw new NotImplementedException("BeginTransaction is not supported in the COM implementation");
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardEndTransaction(
+ /// SCARDHANDLE hCard,
+ /// DWORD dwDisposition
+ /// );
+ /// This function is not supported in the COM implementation
+ ///
+ /// A value from DISCONNECT enum
+ public override void EndTransaction(DISCONNECT Disposition)
+ {
+ throw new NotImplementedException("EndTransaction is not supported in the COM implementation");
+ }
+
+ ///
+ /// Gets the attributes of the card
+ ///
+ /// Identifier for the Attribute to get
+ /// Attribute content
+ public override byte[] GetAttribute(UInt32 AttribId)
+ {
+ throw new NotImplementedException();
+ }
+ #endregion
+
+ ///
+ /// This function must implement a card detection mechanism.
+ ///
+ /// When card insertion is detected, it must call the method CardInserted()
+ /// When card removal is detected, it must call the method CardRemoved()
+ ///
+ ///
+ protected override void RunCardDetection(object Reader)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/CardInsertedEventArgs.cs b/TBF_V2/Sources/TBF/GemCard/CardInsertedEventArgs.cs
new file mode 100644
index 00000000..affae319
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/CardInsertedEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace GemCard
+{
+ public class CardInsertedEventArgs : EventArgs
+ {
+ public CardInsertedEventArgs() { }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/CardNative.cs b/TBF_V2/Sources/TBF/GemCard/CardNative.cs
new file mode 100644
index 00000000..fc7d0212
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/CardNative.cs
@@ -0,0 +1,620 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+
+namespace GemCard
+{
+ ///
+ /// CARD_STATE enumeration, used by the PC/SC function SCardGetStatusChanged
+ ///
+ enum CARD_STATE
+ {
+ UNAWARE = 0x00000000,
+ IGNORE = 0x00000001,
+ CHANGED = 0x00000002,
+ UNKNOWN = 0x00000004,
+ UNAVAILABLE = 0x00000008,
+ EMPTY = 0x00000010,
+ PRESENT = 0x00000020,
+ ATRMATCH = 0x00000040,
+ EXCLUSIVE = 0x00000080,
+ INUSE = 0x00000100,
+ MUTE = 0x00000200,
+ UNPOWERED = 0x00000400
+ }
+
+ ///
+ /// Wraps the SCARD_IO_STRUCTURE
+ ///
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SCard_IO_Request
+ {
+ public UInt32 m_dwProtocol;
+ public UInt32 m_cbPciLength;
+ }
+
+
+ ///
+ /// Wraps theSCARD_READERSTATE structure of PC/SC
+ ///
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct SCard_ReaderState
+ {
+ public string m_szReader;
+ public IntPtr m_pvUserData;
+ public UInt32 m_dwCurrentState;
+ public UInt32 m_dwEventState;
+ public UInt32 m_cbAtr;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
+ public byte[] m_rgbAtr;
+ }
+
+ ///
+ /// Implementation of ICard using native (P/Invoke) interoperability for PC/SC
+ ///
+ public class CardNative : CardBase
+ {
+ private UInt32 m_hContext = 0;
+ private UInt32 m_hCard = 0;
+ private UInt32 m_nProtocol = (uint) PROTOCOL.T0;
+ private int m_nLastError = 0;
+
+ #region PCSC_FUNCTIONS
+ ///
+ /// Native SCardGetStatusChanged from winscard.dll
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError = true)]
+ internal static extern int SCardGetStatusChange(UInt32 hContext,
+ UInt32 dwTimeout,
+ [In,Out] SCard_ReaderState[] rgReaderStates,
+ UInt32 cReaders);
+
+ ///
+ /// Native SCardListReaders function from winscard.dll
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError=true)]
+ internal static extern int SCardListReaders(UInt32 hContext,
+ [MarshalAs(UnmanagedType.LPTStr)] string mszGroups,
+ IntPtr mszReaders,
+ out UInt32 pcchReaders);
+
+ ///
+ /// Native SCardEstablishContext function from winscard.dll
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError=true)]
+ internal static extern int SCardEstablishContext(UInt32 dwScope,
+ IntPtr pvReserved1,
+ IntPtr pvReserved2,
+ IntPtr phContext);
+
+ ///
+ /// Native SCardReleaseContext function from winscard.dll
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError=true)]
+ internal static extern int SCardReleaseContext(UInt32 hContext);
+
+ ///
+ /// Native SCardConnect function from winscard.dll
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError=true, CharSet=CharSet.Auto)]
+ internal static extern int SCardConnect(UInt32 hContext,
+ [MarshalAs(UnmanagedType.LPTStr)] string szReader,
+ UInt32 dwShareMode,
+ UInt32 dwPreferredProtocols,
+ IntPtr phCard,
+ IntPtr pdwActiveProtocol);
+
+ ///
+ /// Native SCardDisconnect function from winscard.dll
+ ///
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError=true)]
+ internal static extern int SCardDisconnect(UInt32 hCard,
+ UInt32 dwDisposition);
+
+ ///
+ /// Native SCardTransmit function from winscard.dll
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError=true)]
+ internal static extern int SCardTransmit(UInt32 hCard,
+ [In] ref SCard_IO_Request pioSendPci,
+ byte[] pbSendBuffer,
+ UInt32 cbSendLength,
+ IntPtr pioRecvPci,
+ [Out] byte[] pbRecvBuffer,
+ out UInt32 pcbRecvLength
+ );
+
+ ///
+ /// Native SCardBeginTransaction function of winscard.dll
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError = true)]
+ internal static extern int SCardBeginTransaction(UInt32 hContext);
+
+ ///
+ /// Native SCardEndTransaction function of winscard.dll
+ ///
+ ///
+ ///
+ [DllImport("winscard.dll", SetLastError = true)]
+ internal static extern int SCardEndTransaction(UInt32 hContext, UInt32 dwDisposition);
+
+ [DllImport("winscard.dll", SetLastError = true)]
+ internal static extern int SCardGetAttrib(UInt32 hCard,
+ UInt32 dwAttribId,
+ [Out] byte[] pbAttr,
+ out UInt32 pcbAttrLen);
+
+ #endregion
+
+ ///
+ /// Default constructor
+ ///
+ public CardNative()
+ {
+ }
+
+ ///
+ /// Object destruction
+ ///
+ ~CardNative()
+ {
+ Disconnect(DISCONNECT.Unpower);
+
+ ReleaseContext();
+ }
+
+ #region ICard Members
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardListReaders(SCARDCONTEXT hContext,
+ /// LPCTSTR mszGroups,
+ /// LPTSTR mszReaders,
+ /// LPDWORD pcchReaders
+ /// );
+ ///
+ /// A string array of the readers
+ public override string[] ListReaders()
+ {
+ EstablishContext(SCOPE.User);
+
+ string[] sListReaders = null;
+ UInt32 pchReaders = 0;
+ IntPtr szListReaders = IntPtr.Zero;
+
+ m_nLastError = SCardListReaders(m_hContext, null, szListReaders, out pchReaders);
+ if (m_nLastError == 0)
+ {
+ szListReaders = Marshal.AllocHGlobal((int) pchReaders);
+ m_nLastError = SCardListReaders(m_hContext, null, szListReaders, out pchReaders);
+ if (m_nLastError == 0)
+ {
+ char[] caReadersData = new char[pchReaders];
+ int nbReaders = 0;
+ for (int nI = 0; nI < pchReaders; nI++)
+ {
+ caReadersData[nI] = (char) Marshal.ReadByte(szListReaders, nI);
+
+ if (caReadersData[nI] == 0)
+ nbReaders++;
+ }
+
+ // Remove last 0
+ --nbReaders;
+
+ if (nbReaders != 0)
+ {
+ sListReaders = new string[nbReaders];
+ char[] caReader = new char[pchReaders];
+ int nIdx = 0;
+ int nIdy = 0;
+ int nIdz = 0;
+ // Get the nJ string from the multi-string
+
+ while(nIdx < pchReaders - 1)
+ {
+ caReader[nIdy] = caReadersData[nIdx];
+ if (caReader[nIdy] == 0)
+ {
+ sListReaders[nIdz] = new string(caReader, 0, nIdy);
+ ++nIdz;
+ nIdy = 0;
+ caReader = new char[pchReaders];
+ }
+ else
+ ++nIdy;
+
+ ++nIdx;
+ }
+ }
+
+ }
+
+ Marshal.FreeHGlobal(szListReaders);
+ }
+
+ ReleaseContext();
+
+ return sListReaders;
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardEstablishContext(
+ /// IN DWORD dwScope,
+ /// IN LPCVOID pvReserved1,
+ /// IN LPCVOID pvReserved2,
+ /// OUT LPSCARDCONTEXT phContext
+ /// );
+ ///
+ ///
+ public void EstablishContext(SCOPE Scope)
+ {
+ IntPtr hContext = Marshal.AllocHGlobal(Marshal.SizeOf(m_hContext));
+
+ m_nLastError = SCardEstablishContext((uint) Scope, IntPtr.Zero, IntPtr.Zero, hContext);
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardEstablishContext error: " + m_nLastError;
+
+ Marshal.FreeHGlobal(hContext);
+ throw new Exception(msg);
+ }
+
+ m_hContext = (uint) Marshal.ReadInt32(hContext);
+
+ Marshal.FreeHGlobal(hContext);
+ }
+
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardReleaseContext(
+ /// IN SCARDCONTEXT hContext
+ /// );
+ ///
+ public void ReleaseContext()
+ {
+ if (m_hContext != 0)
+ {
+ m_nLastError = SCardReleaseContext(m_hContext);
+
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardReleaseContext error: " + m_nLastError;
+ throw new Exception(msg);
+ }
+
+ m_hContext = 0;
+ }
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardConnect(
+ /// IN SCARDCONTEXT hContext,
+ /// IN LPCTSTR szReader,
+ /// IN DWORD dwShareMode,
+ /// IN DWORD dwPreferredProtocols,
+ /// OUT LPSCARDHANDLE phCard,
+ /// OUT LPDWORD pdwActiveProtocol
+ /// );
+ ///
+ ///
+ ///
+ ///
+ public override void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols)
+ {
+ EstablishContext(SCOPE.User);
+
+ IntPtr hCard = Marshal.AllocHGlobal(Marshal.SizeOf(m_hCard));
+ IntPtr pProtocol = Marshal.AllocHGlobal(Marshal.SizeOf(m_nProtocol));
+
+ m_nLastError = SCardConnect(m_hContext,
+ Reader,
+ (uint) ShareMode,
+ (uint) PreferredProtocols,
+ hCard,
+ pProtocol);
+
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardConnect error: " + m_nLastError;
+
+ Marshal.FreeHGlobal(hCard);
+ Marshal.FreeHGlobal(pProtocol);
+ throw new Exception(msg);
+ }
+
+ m_hCard = (uint) Marshal.ReadInt32(hCard);
+ m_nProtocol = (uint) Marshal.ReadInt32(pProtocol);
+
+ Marshal.FreeHGlobal(hCard);
+ Marshal.FreeHGlobal(pProtocol);
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardDisconnect(
+ /// IN SCARDHANDLE hCard,
+ /// IN DWORD dwDisposition
+ /// );
+ ///
+ ///
+ public override void Disconnect(DISCONNECT Disposition)
+ {
+ if (m_hCard != 0)
+ {
+ m_nLastError = SCardDisconnect(m_hCard, (uint) Disposition);
+ m_hCard = 0;
+
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardDisconnect error: " + m_nLastError;
+ throw new Exception(msg);
+ }
+
+ ReleaseContext();
+ }
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardTransmit(
+ /// SCARDHANDLE hCard,
+ /// LPCSCARD_I0_REQUEST pioSendPci,
+ /// LPCBYTE pbSendBuffer,
+ /// DWORD cbSendLength,
+ /// LPSCARD_IO_REQUEST pioRecvPci,
+ /// LPBYTE pbRecvBuffer,
+ /// LPDWORD pcbRecvLength
+ /// );
+ ///
+ /// APDUCommand object with the APDU to send to the card
+ /// An APDUResponse object with the response from the card
+ public override APDUResponse Transmit(APDUCommand ApduCmd)
+ {
+ uint RecvLength = (uint) (ApduCmd.Le + APDUResponse.SW_LENGTH);
+ byte[] ApduBuffer = null;
+ byte[] ApduResponse = new byte[ApduCmd.Le + APDUResponse.SW_LENGTH];
+ SCard_IO_Request ioRequest = new SCard_IO_Request();
+ ioRequest.m_dwProtocol = m_nProtocol;
+ ioRequest.m_cbPciLength = 8;
+
+ // Build the command APDU
+ if (ApduCmd.Data == null)
+ {
+ ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + ((ApduCmd.Le != 0) ? 1 : 0)];
+
+ if (ApduCmd.Le != 0)
+ ApduBuffer[4] = (byte) ApduCmd.Le;
+ }
+ else
+ {
+ ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length];
+
+ for (int nI = 0; nI < ApduCmd.Data.Length; nI++)
+ ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] = ApduCmd.Data[nI];
+
+ ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte) ApduCmd.Data.Length;
+ }
+
+ ApduBuffer[0] = ApduCmd.Class;
+ ApduBuffer[1] = ApduCmd.Ins;
+ ApduBuffer[2] = ApduCmd.P1;
+ ApduBuffer[3] = ApduCmd.P2;
+
+ m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint) ApduBuffer.Length, IntPtr.Zero, ApduResponse, out RecvLength);
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardTransmit error: " + m_nLastError;
+ throw new Exception(msg);
+ }
+
+ byte[] ApduData = new byte[RecvLength];
+
+ for (int nI = 0; nI < RecvLength; nI++)
+ ApduData[nI] = ApduResponse[nI];
+
+ return new APDUResponse(ApduData);
+ }
+
+
+ ///
+ /// Wraps the PSCS function
+ /// LONG SCardBeginTransaction(
+ /// SCARDHANDLE hCard
+ // );
+ ///
+ public override void BeginTransaction()
+ {
+ if (m_hCard != 0)
+ {
+ m_nLastError = SCardBeginTransaction(m_hCard);
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardBeginTransaction error: " + m_nLastError;
+ throw new Exception(msg);
+ }
+ }
+ }
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardEndTransaction(
+ /// SCARDHANDLE hCard,
+ /// DWORD dwDisposition
+ /// );
+ ///
+ /// A value from DISCONNECT enum
+ public override void EndTransaction(DISCONNECT Disposition)
+ {
+ if (m_hCard != 0)
+ {
+ m_nLastError = SCardEndTransaction(m_hCard, (UInt32)Disposition);
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardEndTransaction error: " + m_nLastError;
+ throw new Exception(msg);
+ }
+ }
+ }
+
+ ///
+ /// Gets the attributes of the card
+ ///
+ /// Identifier for the Attribute to get
+ /// Attribute content
+ public override byte[] GetAttribute(UInt32 AttribId)
+ {
+ byte[] attr = null;
+ UInt32 attrLen = 0;
+
+ m_nLastError = SCardGetAttrib(m_hCard, AttribId, attr, out attrLen);
+ if (m_nLastError == 0)
+ {
+ if (attrLen != 0)
+ {
+ attr = new byte[attrLen];
+ m_nLastError = SCardGetAttrib(m_hCard, AttribId, attr, out attrLen);
+ if (m_nLastError != 0)
+ {
+ string msg = "SCardGetAttr error: " + m_nLastError;
+ throw new Exception(msg);
+ }
+ }
+ }
+ else
+ {
+ string msg = "SCardGetAttr error: " + m_nLastError;
+ throw new Exception(msg);
+ }
+
+ return attr;
+ }
+ #endregion
+
+ ///
+ /// This function must implement a card detection mechanism.
+ ///
+ /// When card insertion is detected, it must call the method CardInserted()
+ /// When card removal is detected, it must call the method CardRemoved()
+ ///
+ ///
+ protected override void RunCardDetection(object Reader)
+ {
+ bool bFirstLoop = true;
+ UInt32 hContext = 0; // Local context
+ IntPtr phContext;
+
+ phContext = Marshal.AllocHGlobal(Marshal.SizeOf(hContext));
+
+ if (SCardEstablishContext((uint) SCOPE.User, IntPtr.Zero, IntPtr.Zero, phContext) == 0)
+ {
+ hContext = (uint)Marshal.ReadInt32(phContext);
+ Marshal.FreeHGlobal(phContext);
+
+ UInt32 nbReaders = 1;
+ SCard_ReaderState[] readerState = new SCard_ReaderState[nbReaders];
+
+ readerState[0].m_dwCurrentState = (UInt32) CARD_STATE.UNAWARE;
+ readerState[0].m_szReader = (string)Reader;
+
+ UInt32 eventState;
+ UInt32 currentState = readerState[0].m_dwCurrentState;
+
+ // Card detection loop
+ do
+ {
+ if (SCardGetStatusChange(hContext, WAIT_TIME
+ , readerState, nbReaders) == 0)
+ {
+ eventState = readerState[0].m_dwEventState;
+ currentState = readerState[0].m_dwCurrentState;
+
+ // Check state
+ if (((eventState & (uint) CARD_STATE.CHANGED) == (uint) CARD_STATE.CHANGED) && !bFirstLoop)
+ {
+ // State has changed
+ if ((eventState & (uint) CARD_STATE.EMPTY) == (uint) CARD_STATE.EMPTY)
+ {
+ // There is no card, card has been removed -> Fire CardRemoved event
+ CardRemoved(this, new CardRemovedEventArgs());
+ }
+
+ if (((eventState & (uint)CARD_STATE.PRESENT) == (uint)CARD_STATE.PRESENT) &&
+ ((eventState & (uint) CARD_STATE.PRESENT) != (currentState & (uint) CARD_STATE.PRESENT)))
+ {
+ // There is a card in the reader -> Fire CardInserted event
+ CardInserted(this, new CardInsertedEventArgs());
+ }
+
+ if ((eventState & (uint) CARD_STATE.ATRMATCH) == (uint) CARD_STATE.ATRMATCH)
+ {
+ // There is a card in the reader and it matches the ATR we were expecting-> Fire CardInserted event
+ CardInserted(this, new CardInsertedEventArgs());
+ }
+ }
+
+ // The current stateis now the event state
+ readerState[0].m_dwCurrentState = eventState;
+
+ bFirstLoop = false;
+ }
+
+ Thread.Sleep(100);
+
+ if (m_bRunCardDetection == false)
+ break;
+ }
+ while (true); // Exit on request
+ }
+ else
+ {
+ Marshal.FreeHGlobal(phContext);
+ throw new Exception("PC/SC error");
+ }
+
+ SCardReleaseContext(hContext);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/CardRemovedEventArgs.cs b/TBF_V2/Sources/TBF/GemCard/CardRemovedEventArgs.cs
new file mode 100644
index 00000000..df65d35c
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/CardRemovedEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace GemCard
+{
+ public class CardRemovedEventArgs : EventArgs
+ {
+ public CardRemovedEventArgs() { }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/GemCard.csproj b/TBF_V2/Sources/TBF/GemCard/GemCard.csproj
new file mode 100644
index 00000000..eefd3520
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/GemCard.csproj
@@ -0,0 +1,179 @@
+
+
+
+ Local
+ 8.0.50727
+ 2.0
+ {8B10D15A-39DE-4B56-8DD1-710C1EB3A697}
+ Debug
+ AnyCPU
+
+
+
+
+ GemCard
+
+
+ JScript
+ Grid
+ IE50
+ false
+ Library
+ GemCard
+ OnBuildSuccess
+
+
+
+
+
+
+ 3.5
+ v4.0
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+
+ bin\Debug\
+ true
+ 285212672
+ false
+
+
+ DEBUG;TRACE
+
+
+ true
+ 4096
+ false
+
+
+ false
+ false
+ false
+ false
+ 4
+
+
+ bin\Release\
+ true
+ 285212672
+ false
+
+
+ TRACE
+
+
+ false
+ 4096
+ false
+
+
+ true
+ false
+ false
+ false
+ 4
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE
+ 285212672
+ true
+ 4096
+ x86
+ true
+ true
+ false
+
+
+ bin\x86\Release\
+ TRACE
+ 285212672
+ true
+ true
+ 4096
+ x86
+ false
+ false
+
+
+
+ System
+
+
+ System.Data
+
+
+ System.XML
+
+
+ {00020430-0000-0000-C000-000000000046}
+ 2
+ 0
+ 0
+ primary
+ False
+
+
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 3.5 SP1
+ true
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GemCard/ICard.cs b/TBF_V2/Sources/TBF/GemCard/ICard.cs
new file mode 100644
index 00000000..b6b88e50
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/ICard.cs
@@ -0,0 +1,149 @@
+using System;
+
+namespace GemCard
+{
+ ///
+ /// This interface gives access to the basic card functions. It must be implemented by a class.
+ ///
+ public interface ICard
+ {
+ ///
+ /// Wraps the PCSC funciton
+ /// LONG SCardListReaders(SCARDCONTEXT hContext,
+ /// LPCTSTR mszGroups,
+ /// LPTSTR mszReaders,
+ /// LPDWORD pcchReaders
+ /// );
+ ///
+ /// A string array of the readers
+ string[] ListReaders();
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardConnect(
+ /// IN SCARDCONTEXT hContext,
+ /// IN LPCTSTR szReader,
+ /// IN DWORD dwShareMode,
+ /// IN DWORD dwPreferredProtocols,
+ /// OUT LPSCARDHANDLE phCard,
+ /// OUT LPDWORD pdwActiveProtocol
+ /// );
+ ///
+ ///
+ ///
+ ///
+ void Connect(string Reader, SHARE ShareMode, PROTOCOL PreferredProtocols);
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardDisconnect(
+ /// IN SCARDHANDLE hCard,
+ /// IN DWORD dwDisposition
+ /// );
+ ///
+ ///
+ void Disconnect(DISCONNECT Disposition);
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardTransmit(
+ /// SCARDHANDLE hCard,
+ /// LPCSCARD_I0_REQUEST pioSendPci,
+ /// LPCBYTE pbSendBuffer,
+ /// DWORD cbSendLength,
+ /// LPSCARD_IO_REQUEST pioRecvPci,
+ /// LPBYTE pbRecvBuffer,
+ /// LPDWORD pcbRecvLength
+ /// );
+ ///
+ /// APDUCommand object with the APDU to send to the card
+ /// An APDUResponse object with the response from the card
+ APDUResponse Transmit(APDUCommand ApduCmd);
+
+ ///
+ /// Wraps the PSCS function
+ /// LONG SCardBeginTransaction(
+ /// SCARDHANDLE hCard
+ // );
+ ///
+ void BeginTransaction();
+
+ ///
+ /// Wraps the PCSC function
+ /// LONG SCardEndTransaction(
+ /// SCARDHANDLE hCard,
+ /// DWORD dwDisposition
+ /// );
+ ///
+ void EndTransaction(DISCONNECT Disposition);
+
+ ///
+ /// Gets the attributes of the card
+ ///
+ /// Identifier for the Attribute to get
+ /// Attribute content
+ byte[] GetAttribute(UInt32 AttribId);
+ }
+
+ ///
+ /// SCOPE context
+ ///
+ public enum SCOPE
+ {
+ ///
+ /// The context is a user context, and any database operations are performed within the
+ /// domain of the user.
+ ///
+ User,
+
+ ///
+ /// The context is that of the current terminal, and any database operations are performed
+ /// within the domain of that terminal. (The calling application must have appropriate
+ /// access permissions for any database actions.)
+ ///
+ Terminal,
+
+ ///
+ /// The context is the system context, and any database operations are performed within the
+ /// domain of the system. (The calling application must have appropriate access
+ /// permissions for any database actions.)
+ ///
+ System
+ }
+
+ ///
+ /// SHARE mode enumeration
+ ///
+ public enum SHARE
+ {
+ Exclusive = 1, /// This app. is not willing to share this card with other applications.
+ Shared, /// This app. is willing to share this card with other applications.
+ Direct, /// This app. demands direct control of the reader, so it is not available to other applications.
+ }
+
+
+ ///
+ /// PROTOCOL enumeration
+ ///
+ public enum PROTOCOL
+ {
+ Undefined = 0x00000000, /// There is no active protocol.
+ T0 = 0x00000001, /// T=0 is the active protocol.
+ T1 = 0x00000002, /// T=1 is the active protocol.
+ T0orT1 = T0 | T1, /// T=1 or T=0 can be the active protocol
+ Raw = 0x00010000, /// Raw is the active protocol.
+ Default = unchecked ((int) 0x80000000), /// Use implicit PTS.
+ }
+
+
+ ///
+ /// DISCONNECT action enumeration
+ ///
+ public enum DISCONNECT
+ {
+ Leave, /// Don't do anything special on close
+ Reset, /// Reset the card on close
+ Unpower, /// Power down the card on close
+ Eject, /// Eject(!) the card on close
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GemCard/SmartCardException.cs b/TBF_V2/Sources/TBF/GemCard/SmartCardException.cs
new file mode 100644
index 00000000..507ea0d0
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GemCard/SmartCardException.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace GemCard
+{
+ ///
+ /// Smart card exceptions
+ ///
+ public class SmartCardException : Exception
+ {
+
+ public SmartCardException() : base("Smart card exception")
+ {
+ }
+
+ public SmartCardException(string Message) : base(Message)
+ {
+ }
+ }
+
+
+ public class ApduCommandException : Exception
+ {
+ public const string
+ NotValidDocument = "The file is not a valid APDU command document",
+ NoSuchCommand = "No such APDU command in the document",
+ ParamLeFormat = "Le parameter format is not correct",
+ ParamP3Format = "P3 parameter format is not correct",
+ NoSuchSequence = "No such APDU sequence in the document",
+ MissingApduOrCommand = "An Apdu or a Sequence is missing in this Sequence";
+
+ public ApduCommandException() : base("APDU command exception")
+ {
+ }
+
+ public ApduCommandException(string Message) : base(Message)
+ {
+ }
+
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/BackBuffer.cs b/TBF_V2/Sources/TBF/GraphLib/BackBuffer.cs
new file mode 100644
index 00000000..8af129bd
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/BackBuffer.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Drawing;
+
+
+
+/* Copyright (c) 2008-2014 DI Zimmermann Stephan (stefan.zimmermann@tele2.at)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+namespace GraphLib
+{
+ public class BackBuffer
+ {
+ private Graphics graphics;
+ private Bitmap memoryBitmap;
+ private int width;
+ private int height;
+
+ public BackBuffer()
+ {
+ width = 0;
+ height = 0;
+ }
+
+ public bool Init(Graphics g, int width, int height)
+ {
+ if (memoryBitmap != null)
+ {
+ memoryBitmap.Dispose();
+ memoryBitmap = null;
+ }
+
+ if (graphics != null)
+ {
+ graphics.Dispose();
+ graphics = null;
+ }
+
+ if (width == 0 || height == 0)
+ return false;
+
+ if ((width != this.width) || (height != this.height) || graphics == null)
+ {
+ this.width = width;
+ this.height = height;
+
+ memoryBitmap = new Bitmap(width, height);
+ graphics = Graphics.FromImage(memoryBitmap);
+ }
+
+ return true;
+ }
+
+ public void Render(Graphics g)
+ {
+ if (memoryBitmap != null)
+ {
+ g.DrawImage(memoryBitmap,
+ new Rectangle(0, 0, width, height),
+ 0, 0, width, height,
+ GraphicsUnit.Pixel);
+ }
+ }
+
+ public bool CanDoubleBuffer() { return graphics != null; }
+
+ public Graphics Graphics { get { return graphics; } }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/DataSource.cs b/TBF_V2/Sources/TBF/GraphLib/DataSource.cs
new file mode 100644
index 00000000..532c9a1a
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/DataSource.cs
@@ -0,0 +1,254 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.ComponentModel;
+using System.Drawing;
+
+/* Copyright (c) 2008-2014 DI Zimmermann Stephan (stefan.zimmermann@tele2.at)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+namespace GraphLib
+{
+ public class DataSource
+ {
+ public delegate String OnDrawXAxisLabelEvent(DataSource src, int idx);
+ public delegate String OnDrawYAxisLabelEvent(DataSource src, float value);
+
+ public OnDrawXAxisLabelEvent OnRenderXAxisLabel = null;
+ public OnDrawYAxisLabelEvent OnRenderYAxisLabel = null;
+
+ private PointF[] samples = null;
+ private int length = 0;
+
+ private String name = String.Empty;
+ private int downSample = 1;
+ private Color color = Color.Black;
+
+ public float VisibleDataRange_X = 0;
+ public float DY = 0;
+ public float YD0 = -200;
+ public float YD1 = 200;
+ public float Cur_YD0 = -200;
+ public float Cur_YD1 = 200;
+
+ public float grid_distance_y = 200; // grid distance in units ( draw a horizontal line every 200 units )
+
+ public float off_Y = 0;
+ public float grid_off_y = 0;
+
+ public bool yFlip = true;
+
+ public bool Active = true;
+
+ public float XAutoScaleOffset = 100;
+
+ public float CurGraphHeight = 1.0f;
+
+ public float CurGraphWidth = 1.0f;
+
+ private bool autoScaleY = false;
+ private bool autoScaleX = false;
+
+
+ public bool AutoScaleY
+ {
+ get { return autoScaleY; }
+ set { autoScaleY = value; }
+ }
+
+ public bool AutoScaleX
+ {
+ get { return autoScaleX; }
+ set { autoScaleX = value; }
+ }
+
+ public PointF[] Samples
+ {
+ get { return samples; }
+ set
+ {
+ samples = value;
+ length = samples.Length;
+ }
+ }
+
+ public float XMin
+ {
+ get
+ {
+ float x_min = float.MaxValue;
+ if (samples != null && samples.Length > 0)
+ {
+ foreach (PointF p in samples) if (p.X < x_min) x_min=p.X;
+ }
+ return x_min;
+ }
+ }
+
+ public float XMax
+ {
+ get
+ {
+ float x_max = float.MinValue;
+ if (samples != null && samples.Length > 0)
+ {
+ foreach (PointF p in samples) if (p.X > x_max) x_max = p.X;
+ }
+ return x_max;
+ }
+ }
+
+ public float YMin
+ {
+ get
+ {
+ float y_min = float.MaxValue;
+ if (samples != null && samples.Length > 0)
+ {
+ foreach (PointF p in samples) if (p.Y < y_min) y_min = p.Y;
+ }
+ return y_min;
+ }
+ }
+
+ public float YMax
+ {
+ get
+ {
+ float y_max = float.MinValue;
+ if (samples.Length > 0)
+ {
+ foreach (PointF p in samples) if (p.Y > y_max) y_max = p.Y;
+ }
+ return y_max;
+ }
+ }
+
+ public void SetDisplayRangeY(float y_start, float y_end)
+ {
+ YD0 = y_start;
+ YD1 = y_end;
+ }
+
+ public void SetGridDistanceY(float grid_dist_y_units)
+ {
+ grid_distance_y = grid_dist_y_units;
+ }
+
+ public void SetGridOriginY(float off_y)
+ {
+ grid_off_y = off_y;
+ }
+
+
+ ///
+ /// Load Samples from a file. Returns loaded points count.
+ ///
+ /// File pathname
+ /// Loaded points count
+ public int LoadSamples(string pathName, out float yMin, out float yMax)
+ {
+ yMin = float.MaxValue;
+ yMax = float.MinValue;
+ try
+ {
+ Int64 size = new FileInfo(pathName).Length;
+ if ((size % 8) != 0) return 0;
+ int samplesCount = (int)(size / 8L) - 1;
+ if (samplesCount <= 0) return 0;
+
+ PointF[] newSamples = new PointF[samplesCount];
+ using (BinaryReader reader = new BinaryReader(File.Open(pathName, FileMode.Open)))
+ {
+ for (int i = 0; i < samplesCount; i++)
+ {
+ newSamples[i].X = reader.ReadSingle();
+ newSamples[i].Y = reader.ReadSingle();
+ }
+ yMin = reader.ReadSingle();
+ yMax = reader.ReadSingle();
+ }
+
+ Samples = newSamples;
+ return samplesCount;
+ }
+ catch (Exception exc)
+ {
+ return 0;
+ }
+ }
+
+
+ [Category("Properties")] // Take this out, and you will soon have problems with serialization;
+ [DefaultValue(typeof(string), "")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public String Name
+ {
+ get { return name; }
+ set { name = value; }
+ }
+
+ [Category("Properties")] // Take this out, and you will soon have problems with serialization;
+ [DefaultValue(typeof(Color), "")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public Color GraphColor
+ {
+ get { return color; }
+ set { color = value; }
+ }
+
+ [Category("Properties")] // Take this out, and you will soon have problems with serialization;
+ [DefaultValue(typeof(int), "0")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public int Length
+ {
+ get { return length; }
+ set
+ {
+ length = value;
+ if (length != 0)
+ {
+ samples = new PointF[length];
+ }
+ else
+ {
+ // length is 0
+ if (samples != null)
+ {
+ samples = null;
+ }
+ }
+ }
+ }
+
+ [Category("Properties")] // Take this out, and you will soon have problems with serialization;
+ [DefaultValue(typeof(int), "1")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public int Downsampling
+ {
+ get { return downSample; }
+ set { downSample = value; }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/GraphLib.csproj b/TBF_V2/Sources/TBF/GraphLib/GraphLib.csproj
new file mode 100644
index 00000000..fd4987f4
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/GraphLib.csproj
@@ -0,0 +1,115 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.50727
+ 2.0
+ {0C0A1F4D-1363-4544-A7C5-196C76D26CCA}
+ Library
+ Properties
+ ClassLibrary1
+ GraphLib
+ v4.0
+
+
+
+
+ 2.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ UserControl
+
+
+ PlotterGraphPaneEx.cs
+
+
+ UserControl
+
+
+ PlotterDisplayEx.cs
+
+
+
+ Form
+
+
+ PlotterGraphSelectCurvesForm.cs
+
+
+
+ Form
+
+
+ PrintPreviewForm.cs
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ PlotterGraphPaneEx.cs
+ Designer
+
+
+ PlotterDisplayEx.cs
+ Designer
+
+
+ Designer
+ PlotterGraphSelectCurvesForm.cs
+
+
+ Designer
+ PrintPreviewForm.cs
+
+
+ Designer
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/GraphLib.sln b/TBF_V2/Sources/TBF/GraphLib/GraphLib.sln
new file mode 100644
index 00000000..53a616e7
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/GraphLib.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphLib", "GraphLib.csproj", "{0C0A1F4D-1363-4544-A7C5-196C76D26CCA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0C0A1F4D-1363-4544-A7C5-196C76D26CCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C0A1F4D-1363-4544-A7C5-196C76D26CCA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C0A1F4D-1363-4544-A7C5-196C76D26CCA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C0A1F4D-1363-4544-A7C5-196C76D26CCA}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.cs b/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.cs
new file mode 100644
index 00000000..3d7a11e3
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.cs
@@ -0,0 +1,298 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using System.Threading;
+using System.ComponentModel.Design;
+using System.Drawing.Drawing2D;
+
+
+/* Copyright (c) 2008-2014 DI Zimmermann Stephan (stefan.zimmermann@tele2.at)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+namespace GraphLib
+{
+ public partial class PlotterDisplayEx : UserControl
+ {
+ #region MEMBERS
+
+ delegate void InvokeVoidFuncDelegate();
+
+ PlotterGraphSelectCurvesForm GraphPropertiesForm = null;
+ PrintPreviewForm printPreviewForm = null;
+
+ private bool paused = false;
+ private bool isRunning = false;
+
+ #endregion
+
+ #region CONSTRUCTOR
+
+ public PlotterDisplayEx()
+ {
+ InitializeComponent();
+ isRunning = false;
+ }
+
+ void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
+ {
+ String text = e.ClickedItem.Text;
+ foreach (DataSource s in gPane.Sources)
+ {
+ if (s.Name == text)
+ {
+ s.Active ^= true;
+ gPane.Invalidate();
+ break;
+ }
+ }
+ }
+
+ #endregion
+
+ #region PROPERTIES
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
+ [Editor(typeof(System.ComponentModel.Design.CollectionEditor),
+ typeof(System.Drawing.Design.UITypeEditor))]
+ public IList DataSources
+ {
+ get { return gPane.Sources; }
+ }
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
+ [Editor(typeof(System.ComponentModel.Design.CollectionEditor),
+ typeof(System.Drawing.Design.UITypeEditor))]
+ public PlotterGraphPaneEx.LayoutMode PanelLayout
+ {
+ get { return gPane.layout; }
+ set { gPane.layout = value; }
+ }
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
+ [Editor(typeof(System.ComponentModel.Design.CollectionEditor),
+ typeof(System.Drawing.Design.UITypeEditor))]
+ public SmoothingMode Smoothing
+ {
+ get { return gPane.smoothing; }
+ set { gPane.smoothing = value; }
+ }
+
+ [Category("Playback")]
+ [DefaultValue(typeof(bool), "true")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public bool ShowMovingGrid
+ {
+ get { return gPane.hasMovingGrid; }
+ set { gPane.hasMovingGrid = value; }
+ }
+
+
+ [Category("Properties")]
+ [DefaultValue(typeof(Color), "")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public Color BackgroundColorTop
+ {
+ get { return gPane.BgndColorTop; }
+ set { gPane.BgndColorTop = value; }
+ }
+
+ [Category("Properties")]
+ [DefaultValue(typeof(Color), "")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public Color BackgroundColorBot
+ {
+ get { return gPane.BgndColorBot; }
+ set { gPane.BgndColorBot = value; }
+ }
+
+ [Category("Properties")]
+ [DefaultValue(typeof(Color), "")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public Color DashedGridColor
+ {
+ get { return gPane.MinorGridColor; }
+ set { gPane.MinorGridColor = value; }
+ }
+
+ [Category("Properties")]
+ [DefaultValue(typeof(Color), "")]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
+ public Color SolidGridColor
+ {
+ get { return gPane.MajorGridColor; }
+ set { gPane.MajorGridColor = value; }
+ }
+
+
+ public bool DoubleBuffering
+ {
+ get { return gPane.useDoubleBuffer; }
+ set { gPane.useDoubleBuffer = value; }
+ }
+
+ #endregion
+
+ #region PUBLIC METHODS
+
+ public void SetDisplayRangeX(float x_start, float x_end )
+ {
+ gPane.XD0 = x_start;
+ gPane.XD1 = x_end;
+ gPane.CurXD0 = gPane.XD0;
+ gPane.CurXD1 = gPane.XD1;
+ }
+
+ public void SetGridDistanceX(float grid_dist_x_samples)
+ {
+ gPane.grid_distance_x = grid_dist_x_samples;
+ }
+
+ public void SetGridOriginX(float off_x)
+ {
+ gPane.grid_off_x = off_x;
+ }
+
+
+ #endregion
+
+ #region PRIVATE METHODS
+
+ protected override void Dispose(bool disposing)
+ {
+ paused = true;
+ base.Dispose(disposing);
+ }
+
+ private void SetPlayPanelVisible()
+ {
+ panel1.Visible = true;
+ tb1.Buttons[0].Visible = true;
+ tb1.Buttons[1].Visible = true;
+ }
+
+ private void SetPlayPanelInvisible()
+ {
+ panel1.Visible = false;
+ tb1.Buttons[0].Visible = false;
+ tb1.Buttons[1].Visible = false;
+
+ }
+
+ private void UpdateControl()
+ {
+ try
+ {
+ bool AllAutoscaled = true;
+
+ foreach (DataSource s in gPane.Sources)
+ {
+ AllAutoscaled &= s.AutoScaleX;
+ }
+
+
+ if (AllAutoscaled == true)
+ {
+ if (panel1.Visible == true)
+ {
+ this.Invoke(new MethodInvoker(SetPlayPanelInvisible));
+ }
+ }
+ else
+ {
+ if (panel1.Visible == false)
+ {
+ this.Invoke(new MethodInvoker(SetPlayPanelVisible));
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ private void UpdateScrollBar()
+ {
+ if (InvokeRequired)
+ {
+ Invoke(new MethodInvoker(UpdateScrollBar));
+ }
+ else
+ {
+ if (gPane.Sources.Count > 0)
+ {
+ if (gPane.starting_idx > gPane.Sources[0].Length)
+ {
+ hScrollBar1.Value = 10000;
+ }
+ else if (gPane.starting_idx >= 0)
+ {
+ hScrollBar1.Value = 10000 * (int)gPane.starting_idx / gPane.Sources[0].Length;
+ }
+ else
+ {
+ hScrollBar1.Value = 0;
+ }
+ }
+ else
+ {
+ hScrollBar1.Value = 0;
+ }
+ }
+ }
+
+ private void OnScrollbarScroll(object sender, ScrollEventArgs e)
+ {
+ if (gPane.Sources.Count > 0)
+ {
+ int val = hScrollBar1.Value;
+
+ int maxLen = 0;
+ foreach (var s in DataSources)
+ {
+ if (s.Length > maxLen) maxLen = s.Length;
+ }
+
+ gPane.starting_idx = (int)(maxLen * (float)val / 10000.0f);
+ gPane.Invalidate();
+ }
+ }
+
+ #endregion
+
+ private void selectGraphsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (GraphPropertiesForm == null)
+ {
+ GraphPropertiesForm = new PlotterGraphSelectCurvesForm();
+ }
+
+ GraphPropertiesForm.GraphPanel = this.gPane;
+ GraphPropertiesForm.Show();
+ // GraphPropertiesForm.BringToFront();
+
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.designer.cs b/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.designer.cs
new file mode 100644
index 00000000..47412927
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.designer.cs
@@ -0,0 +1,200 @@
+namespace GraphLib
+{
+ partial class PlotterDisplayEx
+ {
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PlotterDisplayEx));
+ this.tb1 = new System.Windows.Forms.ToolBar();
+ this.tbbSave = new System.Windows.Forms.ToolBarButton();
+ this.tbbOpen = new System.Windows.Forms.ToolBarButton();
+ this.imgList1 = new System.Windows.Forms.ImageList(this.components);
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.lb_Position = new System.Windows.Forms.Label();
+ this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
+ this.gPane = new GraphLib.PlotterGraphPaneEx();
+ this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.selectGraphsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ this.panel1.SuspendLayout();
+ this.contextMenuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tb1
+ //
+ this.tb1.Appearance = System.Windows.Forms.ToolBarAppearance.Flat;
+ this.tb1.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
+ this.tbbSave,
+ this.tbbOpen});
+ this.tb1.ButtonSize = new System.Drawing.Size(16, 16);
+ this.tb1.Divider = false;
+ this.tb1.Dock = System.Windows.Forms.DockStyle.None;
+ this.tb1.DropDownArrows = true;
+ this.tb1.ImageList = this.imgList1;
+ this.tb1.Location = new System.Drawing.Point(11, 5);
+ this.tb1.Name = "tb1";
+ this.tb1.ShowToolTips = true;
+ this.tb1.Size = new System.Drawing.Size(80, 26);
+ this.tb1.TabIndex = 1;
+ this.tb1.Visible = false;
+ //
+ // tbbSave
+ //
+ this.tbbSave.ImageIndex = 0;
+ this.tbbSave.Name = "tbbSave";
+ this.tbbSave.Tag = "play";
+ //
+ // tbbOpen
+ //
+ this.tbbOpen.ImageIndex = 1;
+ this.tbbOpen.Name = "tbbOpen";
+ this.tbbOpen.Tag = "stop";
+ //
+ // imgList1
+ //
+ this.imgList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imgList1.ImageStream")));
+ this.imgList1.TransparentColor = System.Drawing.Color.Transparent;
+ this.imgList1.Images.SetKeyName(0, "media-playback-start.png");
+ this.imgList1.Images.SetKeyName(1, "media-playback-stop.png");
+ this.imgList1.Images.SetKeyName(2, "media-playback-pause.png");
+ this.imgList1.Images.SetKeyName(3, "printer.png");
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.BackColor = System.Drawing.SystemColors.Control;
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+ this.splitContainer1.IsSplitterFixed = true;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Name = "splitContainer1";
+ this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.BackColor = System.Drawing.SystemColors.ControlDarkDark;
+ this.splitContainer1.Panel1.Controls.Add(this.tb1);
+ this.splitContainer1.Panel1.Controls.Add(this.panel1);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.BackColor = System.Drawing.Color.Transparent;
+ this.splitContainer1.Panel2.Controls.Add(this.gPane);
+ this.splitContainer1.Size = new System.Drawing.Size(598, 339);
+ this.splitContainer1.SplitterDistance = 34;
+ this.splitContainer1.TabIndex = 2;
+ this.splitContainer1.TabStop = false;
+ //
+ // panel1
+ //
+ this.panel1.Controls.Add(this.lb_Position);
+ this.panel1.Controls.Add(this.hScrollBar1);
+ this.panel1.Location = new System.Drawing.Point(99, 3);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(496, 28);
+ this.panel1.TabIndex = 7;
+ //
+ // lb_Position
+ //
+ this.lb_Position.AutoSize = true;
+ this.lb_Position.ForeColor = System.Drawing.SystemColors.ControlLightLight;
+ this.lb_Position.Location = new System.Drawing.Point(6, 8);
+ this.lb_Position.Name = "lb_Position";
+ this.lb_Position.Size = new System.Drawing.Size(44, 13);
+ this.lb_Position.TabIndex = 3;
+ this.lb_Position.Text = "Position";
+ //
+ // hScrollBar1
+ //
+ this.hScrollBar1.Location = new System.Drawing.Point(57, 10);
+ this.hScrollBar1.Maximum = 10000;
+ this.hScrollBar1.Name = "hScrollBar1";
+ this.hScrollBar1.Size = new System.Drawing.Size(118, 10);
+ this.hScrollBar1.TabIndex = 4;
+ this.hScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.OnScrollbarScroll);
+ //
+ // gPane
+ //
+ this.gPane.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.gPane.Location = new System.Drawing.Point(0, 0);
+ this.gPane.Name = "gPane";
+ this.gPane.Size = new System.Drawing.Size(598, 301);
+ this.gPane.TabIndex = 1;
+ //
+ // contextMenuStrip1
+ //
+ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.selectGraphsToolStripMenuItem,
+ this.toolStripSeparator1});
+ this.contextMenuStrip1.Name = "contextMenuStrip1";
+ this.contextMenuStrip1.Size = new System.Drawing.Size(117, 32);
+ //
+ // selectGraphsToolStripMenuItem
+ //
+ this.selectGraphsToolStripMenuItem.Name = "selectGraphsToolStripMenuItem";
+ this.selectGraphsToolStripMenuItem.Size = new System.Drawing.Size(116, 22);
+ this.selectGraphsToolStripMenuItem.Text = "Options";
+ this.selectGraphsToolStripMenuItem.Click += new System.EventHandler(this.selectGraphsToolStripMenuItem_Click);
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(113, 6);
+ //
+ // PlotterDisplayEx
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.Transparent;
+ this.ContextMenuStrip = this.contextMenuStrip1;
+ this.Controls.Add(this.splitContainer1);
+ this.Name = "PlotterDisplayEx";
+ this.Size = new System.Drawing.Size(598, 339);
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel1.PerformLayout();
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+ this.splitContainer1.ResumeLayout(false);
+ this.panel1.ResumeLayout(false);
+ this.panel1.PerformLayout();
+ this.contextMenuStrip1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ToolBar tb1;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.ToolBarButton tbbSave;
+ private System.Windows.Forms.ToolBarButton tbbOpen;
+ private System.Windows.Forms.HScrollBar hScrollBar1;
+ private PlotterGraphPaneEx gPane;
+ private System.Windows.Forms.Label lb_Position;
+ public System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem selectGraphsToolStripMenuItem;
+ private System.Windows.Forms.ImageList imgList1;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.Panel panel1;
+
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.resx b/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.resx
new file mode 100644
index 00000000..35ef645d
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterDisplayEx.resx
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
+ LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+ ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACI
+ DgAAAk1TRnQBSQFMAgEBBAEAARQBAAEUAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
+ AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AKgADAQECwAABtgGV
+ AU8B/QHKAZgBWQH/AcoBlwFZAf8BygGXAVkB/wHKAZcBWQH/AcoBlwFYAf8ByQGXAVgB/wHJAZcBWAH/
+ AcoBmAFZAf8BtgGUAU8B/RQAAxQBHAMRARcDAgEDrAADTgGZA10B0gNMAf8BxwGVAVUB/wH5AfcB9gH/
+ AfkB8QHsAf8B+QHxAesB/wH4AfAB6QH/AfcB7QHmAf8B9AHqAeEB/wHyAegB3gH/AfoB+AH2Af8BxwGU
+ AVUB/wMYAf8DWAHRA0QBeggAAxUBHQFiAlgB6QM6AWEDDQESAwABASwAAxsBJgMbASYDGwEmAxsBJgMb
+ ASYDGwEmAxsBJgMbASYDGwEmAxsBJgMbASYDGwEmEAADGwEmAxsBJgMbASYDGwEmAxsBJgMbASYDGwEm
+ AxsBJgMbASYDGwEmAxsBJgMbASYIAANUAf0DpwH/A7UB/wOBAf8BrwGsAaoB/wHFAcABvQH/AcUBwAG9
+ Af8BxQHAAb0B/wHFAcABvQH/AcUBwAG9Af8BxQHAAb0B/wGtAaoBqAH/AyAB/wO1Af8DmwH/AxcB/wgA
+ AxUBHQNNAfoBOgIrAfwDXwHgAysBQgMNARIoAAMbASYDKwH8AYACgQH/AYACgQH/AYACgQH/AYACgQH/
+ AYACgQH/AYACgQH/AYACgQH/AYACgQH/AYACgQH/AxsBJhAAAxsBJgMrAfwBgAKBAf8BgAKBAf8BgAKB
+ Af8DIwE0AxsBJgMrAfwBgAKBAf8BgAKBAf8BgAKBAf8DIwE0CAADZAH/A7UB/wO1Af8DlQH/A4EB/wOB
+ Af8DbQH/A2IB/wNVAf8DRgH/AzcB/wM2Af8DYgH/A7UB/wO1Af8DGQH/CAADFQEdAV8CSgH7AfkB+gH5
+ Af8DfwH+AV8BUwFSAfsDVQGyAx0BKgMIAQsgAAMbASYDQAH9IP8DQAH9AxsBJgMAAQEMAAMbASYDQAH9
+ AfwB/QH8Bf8DQAH9AxsBJgMbASYDQAH9AfwB/QH8Bf8DQAH9AxsBJgMAAQEEAANpAf8DuwH/A7sB/wON
+ Af8D1AH/A7kB/wO5Af8DuQH/A7kB/wO5Af8DuQH/A9MB/wODAf8DuwH/A7sB/wMeAf8IAAMVAR0DKwH8
+ AfoC+wH/AfUC9gH/AfkC+gH/ATsBLgEtAfwBbQJRAfcDQgF2AxYBHgMFAQcYAAMbASYDQAH9BP8B1QHb
+ AdgB/wHUAdsB1wH/AdQB2wHYAf8B0wHbAdcB/wHRAdkB1QH/Ac8B1wHTBf8DQAH9AxsBJgMBAQIMAAMb
+ ASYDQAH9AeIB5QHkAf8B2AHfAdwB/wNAAf0DGwEmAxsBJgNAAf0D8wH/AfcB+AH3Af8DQAH9AxsBJgMB
+ AQIEAANuAf8D1wH/A9cB/wOXAf8D2AH/A78B/wO/Af8DvwH/A78B/wO/Af8DvwH/A9cB/wOOAf8D1wH/
+ A9cB/wMzAf8IAAMWAR4DKwH8A/sB/wHTAdoB1wH/AdoB3wHcAf8B9gH3AfYB/wHyAvMB/wE6AisB/AFg
+ AlkB6wMzAVMDEgEZAwQBBRAAAxsBJgNAAf0E/wHaAeAB3QH/AdsB4QHeAf8B3QHiAeAB/wHdAeIB4AH/
+ AdsB4QHeAf8B2AHeAdsF/wNAAf0DGwEmAwEBAgwAAxsBJgNAAf0B4gHmAeQB/wHcAeIB3wH/A0AB/QMb
+ ASYDGwEmA0AB/QHvAfEB8AH/AfAB8wHxAf8DQAH9AxsBJgMBAQIEAANyAf8D+QH/A/kB/wOrAf8D3wH/
+ A8sB/wPLAf8DywH/A8sB/wPLAf8DywH/A98B/wOjAf8D+QH/A/kB/wNVAf8IAAMWAR4DKwH8A/sB/wHf
+ AeQB4QH/Ad4B4wHhAf8B3gHjAeAB/wHjAecB5QH/AfQC9QH/A38B/gGRAkAB/QNWAbYDJgE5AxABFQwA
+ AxsBJgNAAf0E/wHdAeMB4AH/AeEB5gHjAf8B5AHpAecB/wHmAeoB6AH/AeUB6QHnAf8B4gHnAeQF/wNA
+ Af0DGwEmAwEBAgwAAxsBJgNAAf0B5AHoAeUB/wHeAeMB4QH/A0AB/QMbASYDGwEmA0AB/QHsAe8B7gH/
+ AecB6wHpAf8DQAH9AxsBJgMBAQIEAANqAfkD/AH/A/wB/wPLAf8D8gH/A/IB/wPyAf8D8gH/A/IB/wPy
+ Af8D8gH/A/IB/wPGAf8D/AH/A/wB/wNwAf4IAAMWAR4DKwH8A/sB/wHqAe4B7AH/AewB7wHuAf8B7AHv
+ Ae4B/wHrAe4B7QH/AekB7AHrAf8DfwH+AToCKwH8AVgCVgG7Ax0BKgMGAQgMAAMbASYDQAH9BP8B3wHk
+ AeEB/wHkAekB5gH/AeoB7QHrAf8B7gHxAe8B/wHvAfEB8AH/AewB7wHuBf8DQAH9AxsBJgMBAQIMAAMb
+ ASYDQAH9AesB7QHsAf8B3QHjAeAB/wNAAf0DGwEmAxsBJgNAAf0B7QHwAe8B/wHfAeQB4QH/A0AB/QMb
+ ASYDAQECBAADXQTSAf8D6AH/A3EB/wNxAf8DcQH/A3EB/wNxAf8DcQH/A3EB/wNxAf8DcQH/A3EB/wPo
+ Af8DxAH/A1wB3AgAAxYBHgMrAfwD+wH/AfUC9gH/AfoB+wH6Af8D+QH/Ad0C3gH/AWoCRwH5A10B7QE6
+ AjkBYAMNAREUAAMbASYDQAH9BP8B3AHiAd8B/wHkAegB5gH/AesB7gHtAf8B8gH0AfMB/wH3AvgB/wH2
+ AfgB9wX/A0AB/QMbASYDAQECDAADGwEmA0AB/QHyAfQB8wH/AdoB3wHdAf8DQAH9AxsBJgMcASgDQAH9
+ AfMB9QH0Af8B1gHdAdkB/wNAAf0DGwEmAwEBAgQAAy0BRQOaAf8DzAH/AccBiwFCAf8B+QH0Ae0B/wH+
+ AegB2AH/Af4B6AHXAf8B/QHlAdMB/wH8AeQB0QH/AfoB4AHHAf8B+QHdAcMB/wH6AfQB7QH/AccBhQE+
+ Af8DwwH/A2gB/wMtAUUIAAMWAR4DKwH8A/sB/wHwAfMB8gH/AeYC6AH/A00B+gFiAlIB9AFRAk8BpQMU
+ ARwDAAEBGAADGwEmA0AB/QT/AdgB3wHcAf8B4AHlAeMB/wHoAesB6gH/Ae8B8gHwAf8B9wH4AfcB/wP9
+ Bf8DQAH9AxsBJgMBAQIMAAMbASYDQAH9A/wB/wHVAdsB2AH/A0AB/QMbASYDHAEoA0AB/QP8Af8B0gHa
+ AdYB/wNAAf0DGwEmAwEBAggAAzsBYwNqAfMBxQGJAUAB/wH5AfQB7wH/Af4B5wHXAf8B/QHnAdUB/wH8
+ AeYB0gH/AfsB4QHMAf8B+AHcAcIB/wH2AdoBvQH/AfoB9AHvAf8BxAGDATwB/wNdAfMDOwFjDAADFgEe
+ AysB/AP7Af8BPgIyAfwDTQH6AVoCVwG9AxgBIgMCAQMgAAMbASYDQAH9IP8DQAH9AxsBJgMBAQIMAAMb
+ ASYDQAH9CP8DQAH9AxsBJgMcASgDQAH9CP8DQAH9AxsBJgMBAQIMAAMHAQkBlgF6AUcC+QH0AfAB/wH8
+ AeYB0wH/Af0B5wHTAf8B+wHjAc0B/wH6AeAByAH/AfUB1gG7Af8B8wHUAbUB/wH4AfQB8AH/AZUBagFH
+ AfkDBwEJEAADFgEeA0AB/QFbAjIB+wFgAlwB1AMjATMDBwEKKAADGwEmAysB/AEpAS0BKwH/ASkBLQEr
+ Af8BKQEtASsB/wEpAS0BKwH/ASkBLQErAf8BKQEtASsB/wEpAS0BKwH/ASkBLQErAf8BKQEtASsB/wMb
+ ASYDAQECDAADGwEmAWMBVwFVAf4BKQEtASsB/wEpAS0BKwH/ASkBLQErAf8DGwEmAxwBKAFjAVcBVQH+
+ ASkBLQErAf8BKQEtASsB/wEpAS0BKwH/AxsBJgMBAQIQAAGSAXoBUQH3AfkB9QHxAf8B/AHjAc8B/wH8
+ AeQBzwH/AfoB4QHKAf8B+QHdAcQB/wH0AekB3wH/AfcB8gHsAf8B9QHvAekB/wGZAV8BRQH7FAADFgEf
+ AV4CWgHYAygBPQMNAREwAAMbASYDGwEmAxsBJgMbASYDGwEmAxsBJgMbASYDGwEmAxsBJgMbASYDGwEm
+ AxsBJgMAAQEMAAMbASYDGwEmAxsBJgMbASYDGwEmAxsBJgMbASYDGwEmAxsBJgMbASYDGwEmAxsBJgMA
+ AQEQAAGJAWoBSQH2AfkB9QHxAf8B/AHjAc0B/wH7AeMBzQH/AfkB4AHIAf8B+AHcAcIB/wH9AfsB+AH/
+ AfwB5gHNAf8B4gG2AYQB/wJUAVIBphQAAxYBHwMRARcDAgEDuAABngF1AU0B+gH3AfIB7AH/AfgB9AHu
+ Af8B+AHzAe0B/wH4AfMB7QH/AfgB8gHsAf8B8gHmAdcB/wHiAbIBcQH/AZABcQFiAfYDBQEHFAADAwEE
+ wAADOgFgAlgBVgG7AbEBfwFPAf4ByAGMAUMB/wGSAX8BUQH3AZIBfwFRAfcBrgF/AUwB/gNOAZQUAAFC
+ AU0BPgcAAT4DAAEoAwABQAMAASADAAEBAQABAQYAAQEWAAP/gQAB3wX/AeABBwHHBf8CAAHBAf8BwAED
+ AcABAwIAAcAB/wHAAQMBwAEDAgABwAE/AcABAQHAAQECAAHAAQ8BwAEBAcABAQIAAcABAwHAAQEBwAEB
+ AgABwAEBAcABAQHAAQECAAHAAQEBwAEBAcABAQIAAcABBwHAAQEBwAEBAgABwAEPAcABAQHAAQEBgAEB
+ AcABPwHAAQEBwAEBAcABAwHAAf8BwAEBAcABAQHgAQcBwwH/AcABAQHAAQEB4AEHAccF/wHgAQcB3wX/
+ AeABHws=
+
+
+
+ 84, 17
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.Designer.cs b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.Designer.cs
new file mode 100644
index 00000000..9c05883d
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.Designer.cs
@@ -0,0 +1,46 @@
+namespace GraphLib
+{
+ partial class PlotterGraphPaneEx
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // PlotterGraphPane
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Name = "PlotterGraphPane";
+ this.Size = new System.Drawing.Size(409, 150);
+ this.Load += new System.EventHandler(this.OnLoadControl);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.cs b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.cs
new file mode 100644
index 00000000..57fade46
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.cs
@@ -0,0 +1,1052 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using System.Drawing.Drawing2D;
+
+ /* Copyright (c) 2008-2014 DI Zimmermann Stephan (stefan.zimmermann@tele2.at)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+namespace GraphLib
+{
+ public partial class PlotterGraphPaneEx : UserControl
+ {
+ #region MEMBERS
+
+ public enum LayoutMode
+ {
+ NORMAL,
+ STACKED,
+ VERTICAL_ARRANGED,
+ TILES_VER,
+ TILES_HOR,
+ }
+
+ private BackBuffer backBuffer;
+ private int ActiveSources = 0;
+
+ public LayoutMode layout = LayoutMode.NORMAL;
+
+ public Color MajorGridColor = Color.DarkGray;
+ public Color MinorGridColor = Color.DarkGray;
+ public Color GraphColor = Color.DarkGreen;
+ public Color BgndColorTop = Color.White;
+ public Color BgndColorBot = Color.White;
+ public Color LabelColor = Color.White;
+ public Color GraphBoxColor = Color.White;
+ public bool useDoubleBuffer = false;
+ public Font legendFont = new Font(FontFamily.GenericSansSerif, 8.25f);
+
+ private IList sources = new List();
+
+ public SmoothingMode smoothing = SmoothingMode.None;
+
+ public bool hasMovingGrid = true;
+ public bool hasBoundingBox = true;
+
+ private Point mousePos = new Point();
+ private bool mouseDown = false;
+
+
+ public float starting_idx = 0;
+
+
+ public float XD0 = -50;
+
+ public float XD1 = 100;
+
+ public float DX = 0;
+
+ public float off_X = 0;
+
+ public float CurXD0 = 0;
+
+ public float CurXD1 = 0;
+
+ public float grid_distance_x = 60; // grid distance in samples ( draw a vertical line every 60 samples )
+ public float grid_off_x = 0;
+ public float GraphCaptionLineHeight = 28;
+
+ public float pad_inter = 4; // padding between graphs
+ public float pad_left = 10; // left padding
+ public float pad_right = 10; // right padding
+ public float pad_top = 10; // top
+ public float pad_bot = 10; // bottom padding
+
+ public float graph_distance_x = 10; // distance between graphs, x direction
+ public float graph_distance_y = 10; // distance between graphs, y direction
+
+ public float yLabelAreaWidth = 40; // y-label area width
+
+ public float xLabelAreaheight = 8; // x-label padding ( bottom area left and right were x labels are still visible )
+
+ PointF graphCaptionOffset = new PointF(12, 2);
+
+ public float[] MinorGridPattern = new float[] { 2,4 };
+ public float[] MajorGridPattern = new float[] { 2,2 };
+
+ DashStyle MinorGridDashStyle = DashStyle.Custom;
+ DashStyle MajorGridDashStyle = DashStyle.Custom;
+ public bool MoveMinorGrid = true;
+
+ #endregion
+
+ #region CONSTRUCTOR
+
+ public PlotterGraphPaneEx()
+ {
+ backBuffer = new BackBuffer();
+
+ InitializeComponent();
+
+ this.Resize += new System.EventHandler(this.OnResizeForm);
+ this.MouseDown += new MouseEventHandler(OnMouseDown);
+ this.MouseUp += new MouseEventHandler(OnMouseUp);
+ this.MouseMove += new MouseEventHandler(OnMouseMove);
+ }
+
+ #endregion
+
+ public IList Sources { get { return sources; } }
+
+ private void OnLoadControl(object sender, EventArgs e)
+ {
+ backBuffer.Init(this.CreateGraphics(), this.ClientRectangle.Width, this.ClientRectangle.Height);
+ }
+
+ protected override void OnPaintBackground(PaintEventArgs e)
+ {
+ if (ParentForm == null)
+ {
+ // paint background when control is used in editor
+ base.OnPaintBackground(e);
+
+ }
+ else
+ {
+ // do not repaint background to avoid flickering
+ }
+ }
+
+ private void OnResizeForm(object sender, System.EventArgs e)
+ {
+ backBuffer.Init(this.CreateGraphics(), ClientRectangle.Width, ClientRectangle.Height);
+ Invalidate();
+ }
+
+ private void OnMouseUp(object sender, MouseEventArgs e)
+ {
+ if (mouseDown == true)
+ {
+ mouseDown = false;
+ Cursor = Cursors.Default;
+ }
+ }
+
+ private void OnMouseDown(object sender, MouseEventArgs e)
+ {
+ if (mouseDown == false)
+ {
+ mouseDown = true;
+ mousePos = e.Location;
+ Cursor = Cursors.Hand;
+ }
+ }
+
+ private void OnMouseMove(object sender, MouseEventArgs e)
+ {
+ if (mouseDown)
+ {
+ float dx = mousePos.X - e.Location.X;
+
+ mousePos = e.Location;
+
+ float DX = CurXD1 - CurXD0;
+
+ float off_X = dx * DX / this.Width;
+
+ if (Math.Abs(off_X) > 0)
+ {
+ starting_idx += off_X;
+ }
+
+ Invalidate();
+ }
+ }
+
+ public void PaintGraphs(Graphics CurGraphics, float CurWidth, float CurHeight, float OFFX, float OFFY)
+ {
+ int CurGraphIdx = 0;
+ int VertTileCount = 1;
+ int HorTileCount = 1;
+
+ float curOffY = 0;
+ float CurOffX = 0;
+
+ if ((layout == LayoutMode.TILES_VER || layout == LayoutMode.TILES_HOR) && ActiveSources >= 1)
+ {
+ // calculate number of tiles
+ if (layout == LayoutMode.TILES_VER)
+ {
+ VertTileCount = 1;
+ HorTileCount = 1;
+ while (true)
+ {
+ if (VertTileCount * HorTileCount >= ActiveSources) break;
+ VertTileCount++;
+ if (VertTileCount * HorTileCount >= ActiveSources) break;
+ HorTileCount++;
+ }
+ }
+ else if (layout == LayoutMode.TILES_HOR)
+ {
+ VertTileCount = 1;
+ HorTileCount = 1;
+ while (true)
+ {
+ if (VertTileCount * HorTileCount >= ActiveSources) break;
+ HorTileCount++;
+ if (VertTileCount * HorTileCount >= ActiveSources) break;
+ VertTileCount++;
+ }
+ }
+ }
+
+ foreach (DataSource source in sources)
+ {
+ source.Cur_YD0 = source.YD0;
+ source.Cur_YD1 = source.YD1;
+
+ source.CurGraphHeight = CurHeight;
+ source.CurGraphWidth = CurWidth - pad_left - yLabelAreaWidth - pad_right;
+
+ if (source.yFlip)
+ {
+ DX = XD1 - XD0;
+ }
+ else
+ {
+ DX = XD1 - XD0;
+ }
+
+ CurXD0 = XD0;
+ CurXD1 = XD1;
+
+ if (source.AutoScaleX && source.Samples.Length > 0)
+ {
+ CurXD0 = source.XMin - source.XAutoScaleOffset;
+ CurXD1 = source.XMax + source.XAutoScaleOffset;
+ DX = CurXD1 - CurXD0;
+ }
+
+ if (source.Active)
+ {
+ if (source.AutoScaleY == true)
+ {
+ int idx_start = -1;
+ int idx_stop = -1;
+ float ymin = 0.0f;
+ float ymax = 0.0f;
+ float ymin_range = 0;
+ float ymax_range = 0;
+
+ int DownSample = source.Downsampling;
+ PointF[] data = source.Samples;
+ float mult_y = source.CurGraphHeight / source.DY;
+ float mult_x = source.CurGraphWidth / DX;
+ float coff_x = off_X - starting_idx * mult_x;
+
+ if (source.AutoScaleX)
+ {
+ coff_x = off_X ;
+ }
+
+ for (int i = 0; i < data.Length - 1; i += DownSample)
+ {
+ float x = data[i].X * mult_x + coff_x;
+
+ if (data[i].Y > ymax) ymax = data[i].Y;
+ if (data[i].Y < ymin) ymin = data[i].Y;
+
+ if (x > 0 && x < (source.CurGraphWidth))
+ {
+ if (idx_start == -1) idx_start = i;
+ idx_stop = i;
+
+ if (data[i].Y > ymax_range) ymax_range = data[i].Y;
+ if (data[i].Y < ymin_range) ymin_range = data[i].Y;
+ }
+ }
+
+ if (idx_start >= 0 && idx_stop >= 0)
+ {
+ float data_range = ymax - ymin; // this is range in the data
+ float delta_range = ymax_range - ymin_range; // this is the visible data range -> might be smaller
+
+ source.Cur_YD0 = ymin_range;
+ source.Cur_YD1 = ymax_range;
+ }
+ }
+
+ if (layout == LayoutMode.VERTICAL_ARRANGED && ActiveSources >= 1)
+ {
+ if (ActiveSources > 1)
+ {
+ source.CurGraphHeight = (float)(CurHeight - pad_top - pad_bot) / ActiveSources - GraphCaptionLineHeight;
+ float Diff = ((ActiveSources - 1) * pad_inter) / ActiveSources;
+ source.CurGraphHeight -= Diff;
+ }
+ else
+ {
+ source.CurGraphHeight = (float)(CurHeight - pad_top - pad_bot) - GraphCaptionLineHeight;
+ }
+ }
+ else if (layout == LayoutMode.STACKED && ActiveSources >= 1)
+ {
+ if (ActiveSources > 1)
+ {
+ source.CurGraphHeight = (float)(CurHeight - pad_top - pad_bot) / ActiveSources - GraphCaptionLineHeight;
+ }
+ else
+ {
+ source.CurGraphHeight = (float)(CurHeight - pad_top - pad_bot) - GraphCaptionLineHeight;
+ }
+ }
+ else if ((layout == LayoutMode.TILES_VER || layout == LayoutMode.TILES_HOR) && ActiveSources >= 1)
+ {
+ if (ActiveSources > 1)
+ {
+ source.CurGraphHeight = (float)(CurHeight - pad_top - pad_bot) / VertTileCount - GraphCaptionLineHeight;
+ float Diff = ((ActiveSources - 1) * pad_inter) / VertTileCount;
+ source.CurGraphHeight -= Diff;
+ source.CurGraphWidth = (float)(CurWidth - pad_left - pad_right) / HorTileCount - yLabelAreaWidth;
+ }
+ else
+ {
+ source.CurGraphHeight = (float)(CurHeight - pad_top - pad_bot) - GraphCaptionLineHeight;
+ }
+ }
+ else
+ {
+ source.CurGraphHeight = (float)(CurHeight - pad_top - pad_bot) - GraphCaptionLineHeight;
+ source.CurGraphWidth = CurWidth - pad_left - yLabelAreaWidth * ActiveSources - pad_right;
+
+ }
+
+ if (source.yFlip)
+ {
+ source.DY = source.Cur_YD0 - source.Cur_YD1;
+
+ if (DX != 0 && source.DY != 0)
+ {
+ source.off_Y = -source.Cur_YD1 * source.CurGraphHeight / source.DY;
+ off_X = -CurXD0 * source.CurGraphWidth / DX;
+ }
+ }
+ else
+ {
+ source.DY = source.Cur_YD1 - source.Cur_YD0;
+
+ if (DX != 0 && source.DY != 0)
+ {
+ source.off_Y = -source.Cur_YD0 * source.CurGraphHeight / source.DY;
+ off_X = -CurXD0 * source.CurGraphWidth / DX;
+ }
+ }
+
+ if ((layout == LayoutMode.TILES_VER || layout == LayoutMode.TILES_HOR))
+ {
+ if (ActiveSources > 1)
+ {
+ if (layout == LayoutMode.TILES_VER)
+ {
+ // TODO: calc curOffX and CurrOffY for CurGraphIdx!!
+ int CurIdxY = CurGraphIdx % VertTileCount;
+ int CurIdxX = CurGraphIdx / VertTileCount;
+
+ curOffY = OFFY + pad_top + CurIdxY * (source.CurGraphHeight + GraphCaptionLineHeight);
+ CurOffX = OFFX + yLabelAreaWidth + pad_left + CurIdxX * (yLabelAreaWidth + source.CurGraphWidth);
+ }
+ else
+ {
+ int CurIdxX = CurGraphIdx % HorTileCount;
+ int CurIdxY = CurGraphIdx / HorTileCount;
+
+ curOffY = OFFY + pad_top + CurIdxY * (source.CurGraphHeight + GraphCaptionLineHeight);
+ CurOffX = OFFX + yLabelAreaWidth + pad_left + CurIdxX * (yLabelAreaWidth + source.CurGraphWidth);
+ }
+
+ }
+ else
+ {
+ // one active source
+ curOffY = OFFY + pad_top + CurGraphIdx * (source.CurGraphHeight + GraphCaptionLineHeight);
+ CurOffX = OFFX + pad_left + yLabelAreaWidth;
+ }
+ }
+ else if (layout == LayoutMode.VERTICAL_ARRANGED)
+ {
+ if (ActiveSources > 1)
+ {
+ curOffY = OFFY + pad_top + CurGraphIdx * (source.CurGraphHeight + GraphCaptionLineHeight + pad_inter);
+ }
+ else
+ {
+ curOffY = OFFY + pad_top + CurGraphIdx * (source.CurGraphHeight + GraphCaptionLineHeight);
+ }
+
+ CurOffX = OFFX + pad_left + yLabelAreaWidth;
+ }
+ else if (layout == LayoutMode.STACKED)
+ {
+ if (ActiveSources > 1)
+ {
+ curOffY = OFFY + pad_top + CurGraphIdx * (source.CurGraphHeight);
+ }
+ else
+ {
+ curOffY = OFFY + pad_top + CurGraphIdx * (source.CurGraphHeight);
+ }
+
+ CurOffX = OFFX + pad_left + yLabelAreaWidth;
+ }
+ else
+ {
+ CurOffX = OFFX + pad_left + yLabelAreaWidth * ActiveSources;
+ curOffY = OFFY + pad_top;
+ }
+
+ DrawGrid(CurGraphics, source, CurOffX, curOffY + GraphCaptionLineHeight / 2);
+
+ if (hasBoundingBox)
+ {
+ float w = source.CurGraphWidth;
+ float h = source.CurGraphHeight + GraphCaptionLineHeight / 2;
+
+ DrawGraphBox(CurGraphics, CurOffX, curOffY, w, h);
+
+ }
+
+ List marker_pos = DrawGraphCurve(CurGraphics, source, CurOffX, curOffY + GraphCaptionLineHeight / 2);
+
+ if (layout == LayoutMode.NORMAL)
+ {
+ DrawGraphCaption(CurGraphics, source, marker_pos, CurOffX + CurGraphIdx * (50 + yLabelAreaWidth) + (CurGraphIdx==0 ? 0 : 50), curOffY);
+
+ if (CurGraphIdx == 0)
+ {
+ DrawXLabels(CurGraphics, source, marker_pos, CurOffX, curOffY);
+ }
+
+ DrawYLabels(CurGraphics, source, marker_pos, CurOffX + yLabelAreaWidth * (CurGraphIdx - ActiveSources + 1), curOffY);
+ }
+ else
+ {
+ DrawGraphCaption(CurGraphics, source, marker_pos, CurOffX, curOffY);
+
+ DrawXLabels(CurGraphics, source, marker_pos, CurOffX, curOffY);
+
+ DrawYLabels(CurGraphics, source, marker_pos, CurOffX, curOffY);
+ }
+
+
+
+ CurGraphIdx++;
+ }
+ }
+ }
+
+ private void PaintStackedGraphs(Graphics CurGraphics,float CurWidth,float CurHeigth, float OFFX, float OFFY)
+ {
+ int CurGraphIdx = 0;
+ float curOffY = 0;
+ float CurOffX = 0;
+
+ foreach (DataSource source in sources)
+ {
+ source.Cur_YD0 = source.YD0;
+ source.Cur_YD1 = source.YD1;
+
+ source.CurGraphHeight = CurHeigth;
+ source.CurGraphWidth = CurWidth - pad_left - yLabelAreaWidth - pad_right;
+
+ DX = XD1 - XD0;
+
+ if (source.AutoScaleX && source.Samples.Length > 0)
+ {
+ DX = source.Samples[source.Samples.Length - 1].X;
+ }
+
+ CurXD0 = XD0;
+ CurXD1 = XD1;
+
+ if (source.Active)
+ {
+ if (source.AutoScaleY == true)
+ {
+ int idx_start = -1;
+ int idx_stop = -1;
+ float ymin = 0.0f;
+ float ymax = 0.0f;
+ float ymin_range = 0;
+ float ymax_range = 0;
+
+ int DownSample = source.Downsampling;
+ PointF[] data = source.Samples;
+ float mult_y = source.CurGraphHeight / source.DY;
+ float mult_x = source.CurGraphWidth / DX;
+ float coff_x = off_X - starting_idx * mult_x;
+
+ if (source.AutoScaleX)
+ {
+ coff_x = off_X; // avoid dragging in x-autoscale mode
+ }
+
+ for (int i = 0; i < data.Length - 1; i += DownSample)
+ {
+ float x = data[i].X * mult_x + coff_x;
+
+ if (data[i].Y > ymax) ymax = data[i].Y;
+ if (data[i].Y < ymin) ymin = data[i].Y;
+
+ if (x > 0 && x < (source.CurGraphWidth))
+ {
+ if (idx_start == -1) idx_start = i;
+ idx_stop = i;
+
+ if (data[i].Y > ymax_range) ymax_range = data[i].Y;
+ if (data[i].Y < ymin_range) ymin_range = data[i].Y;
+ }
+ }
+
+ if (idx_start >= 0 && idx_stop >= 0)
+ {
+ float data_range = ymax - ymin; // this is range in the data
+ float delta_range = ymax_range - ymin_range; // this is the visible data range -> might be smaller
+
+ source.Cur_YD0 = ymin_range;
+ source.Cur_YD1 = ymax_range;
+ }
+ }
+
+ if (ActiveSources > 1)
+ {
+ source.CurGraphHeight = (float)(CurHeigth - GraphCaptionLineHeight - pad_top - pad_bot) / ActiveSources;
+ }
+ else
+ {
+ source.CurGraphHeight = (float)(CurHeigth - GraphCaptionLineHeight - pad_top - pad_bot);
+ }
+
+ if (source.yFlip)
+ {
+ source.DY = source.Cur_YD0 - source.Cur_YD1;
+
+ if (DX != 0 && source.DY != 0)
+ {
+ source.off_Y = -source.Cur_YD1 * source.CurGraphHeight / source.DY;
+ off_X = -CurXD0 * source.CurGraphWidth / DX;
+ }
+ }
+ else
+ {
+ source.DY = source.Cur_YD1 - source.Cur_YD0;
+
+ if (DX != 0 && source.DY != 0)
+ {
+ source.off_Y = -source.Cur_YD0 * source.CurGraphHeight / source.DY;
+ off_X = -CurXD0 * source.CurGraphWidth / DX;
+ }
+ }
+
+ if (ActiveSources > 1)
+ {
+ curOffY = OFFY + pad_top + CurGraphIdx * (source.CurGraphHeight);
+ }
+ else
+ {
+ curOffY = OFFY + pad_top + CurGraphIdx * (source.CurGraphHeight);
+ }
+
+ CurOffX = OFFX + pad_left + yLabelAreaWidth;
+
+ DrawGrid(CurGraphics, source, CurOffX, curOffY + GraphCaptionLineHeight / 2);
+
+ if (hasBoundingBox && CurGraphIdx == ActiveSources - 1)
+ {
+ DrawGraphBox(CurGraphics, pad_left + yLabelAreaWidth, pad_top, source.CurGraphWidth, CurHeigth - pad_top - GraphCaptionLineHeight);
+ }
+
+ List marker_pos = DrawGraphCurve(CurGraphics, source, CurOffX, curOffY + GraphCaptionLineHeight / 2);
+
+ DrawGraphCaption(CurGraphics, source, marker_pos, CurOffX + CurGraphIdx * (50 + yLabelAreaWidth) + (CurGraphIdx == 0 ? 0 : 50), pad_top);
+
+ DrawYLabels(CurGraphics, source, marker_pos, CurOffX, curOffY);
+
+ if (CurGraphIdx == ActiveSources - 1)
+ {
+ DrawXLabels(CurGraphics, source, marker_pos, pad_left, Height - pad_top - GraphCaptionLineHeight - source.CurGraphHeight);
+ }
+
+ /*
+ if (hasBoundingBox && CurGraphIdx == ActiveSources - 1)
+ {
+ DrawGraphBox(CurGraphics, pad_left + yLabelAreaWidth, pad_top, source.CurGraphWidth, CurHeigth - pad_top - GraphCaptionLineHeight);
+ }
+ * */
+
+ CurGraphIdx++;
+ }
+ }
+ }
+
+ public void PaintControl(Graphics CurGraphics, float CurWidth, float CurHeight, float OffX, float OffY, bool PaintBgnd)
+ {
+ if (PaintBgnd)
+ {
+ DrawBackground(CurGraphics,CurWidth,CurHeight,OffX,OffY);
+ }
+
+ ActiveSources = 0;
+
+ foreach (DataSource source in sources)
+ {
+ if (source.Samples != null &&
+ source.Samples.Length > 0 &&
+ source.Active == true)
+ {
+ ActiveSources++;
+ }
+ }
+
+ switch (layout)
+ {
+ case LayoutMode.NORMAL:
+
+ case LayoutMode.TILES_HOR:
+ case LayoutMode.TILES_VER:
+ case LayoutMode.VERTICAL_ARRANGED:
+
+ PaintGraphs(CurGraphics, CurWidth, CurHeight, OffX, OffY);
+
+ break;
+
+ case LayoutMode.STACKED:
+
+ PaintStackedGraphs(CurGraphics, CurWidth, CurHeight, OffX, OffY);
+
+ break;
+ }
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ try
+ {
+ if (ParentForm != null)
+ {
+ Graphics CurGraphics = e.Graphics;
+
+ if (backBuffer.Graphics != null && useDoubleBuffer == true)
+ {
+ CurGraphics = backBuffer.Graphics;
+ }
+
+ CurGraphics.SmoothingMode = smoothing;
+
+ PaintControl(CurGraphics,this.Width,this.Height,0,0,true);
+
+ if (backBuffer.Graphics != null && useDoubleBuffer == true)
+ {
+ backBuffer.Render(e.Graphics);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.Write("exception : " + ex.Message);
+ }
+
+ base.OnPaint(e);
+ }
+
+
+ private void DrawBackground(Graphics g,float CurWidth, float CurHeight, float CurOFFX, float CurOFFY)
+ {
+ Rectangle rbgn = new Rectangle((int)CurOFFX, (int)CurOFFY, (int)CurWidth, (int)CurHeight);
+
+ if (BgndColorTop != BgndColorBot)
+ {
+ using (LinearGradientBrush lb1 = new LinearGradientBrush(new Point((int)0, (int)0),
+ new Point((int)0, (int)(CurHeight)),
+ BgndColorTop,
+ BgndColorBot))
+ {
+ g.FillRectangle(lb1, rbgn);
+ }
+ }
+ else
+ {
+ using (SolidBrush sb1 = new SolidBrush(BgndColorTop))
+ {
+ g.FillRectangle(sb1, rbgn);
+ }
+ }
+ }
+
+
+ private void DrawGrid( Graphics g, DataSource source, float CurrOffX, float CurOffY )
+ {
+ int Idx = 0;
+ float mult_x = source.CurGraphWidth / DX;
+ float coff_x = off_X - starting_idx * mult_x;
+
+ if (source.AutoScaleX)
+ {
+ coff_x = off_X; // avoid dragging in x-autoscale mode
+ }
+
+ Color CurGridColor = MajorGridColor;
+ Color CurMinGridClor = MinorGridColor;
+
+ if (layout == LayoutMode.NORMAL && source.AutoScaleY)
+ {
+ CurGridColor = source.GraphColor;
+ CurMinGridClor = source.GraphColor;
+ }
+
+ using (Pen minorGridPen = new Pen(CurMinGridClor))
+ {
+ minorGridPen.DashPattern = MinorGridPattern;
+ minorGridPen.DashStyle = MinorGridDashStyle;
+
+ using (Pen p2 = new Pen(CurGridColor))
+ {
+ p2.DashPattern = MajorGridPattern;
+ p2.DashStyle = MajorGridDashStyle;
+
+ if (DX != 0)
+ {
+ while (true)
+ {
+ float x = Idx * grid_distance_x * source.CurGraphWidth / DX + grid_off_x * source.CurGraphWidth / DX;
+
+ if (MoveMinorGrid)
+ {
+ x += coff_x;
+ }
+
+ if (x > 0 && x < source.CurGraphWidth)
+ {
+ g.DrawLine(minorGridPen, new Point((int)(x + CurrOffX - 0.5f), (int)(CurOffY)),
+ new Point((int)(x + CurrOffX - 0.5f), (int)(CurOffY + source.CurGraphHeight)));
+ }
+ if (x > source.CurGraphWidth)
+ {
+ break;
+ }
+
+ Idx++;
+ }
+ }
+
+ if (source.DY != 0)
+ {
+ float y0 = (float)(source.grid_off_y * source.CurGraphHeight / source.DY + source.off_Y);
+
+ // draw horizontal zero grid lines
+ if (0 >= source.YD0 && 0 <= source.YD1)
+ {
+ g.DrawLine(p2, new Point((int)CurrOffX, (int)(CurOffY + y0 + 0.5f)), new Point((int)(CurrOffX + source.CurGraphWidth + 0.5f), (int)(CurOffY + y0 + 0.5f)));
+ }
+
+ // draw horizontal grid lines
+ for (float idy = source.grid_off_y; idy > source.YD0; idy -= source.grid_distance_y)
+ {
+ float y = (idy * source.CurGraphHeight) / source.DY + source.off_Y;
+
+ if (y >= 0 && y < source.CurGraphHeight)
+ {
+ g.DrawLine(minorGridPen,
+ new Point((int)CurrOffX, (int)(CurOffY + y + 0.5f)),
+ new Point((int)(CurrOffX + source.CurGraphWidth + 0.5f), (int)(0.5f + CurOffY + y)));
+ }
+ }
+
+ // draw horizontal grid lines
+ for (float idy = source.grid_off_y; idy < source.YD1; idy += source.grid_distance_y)
+ {
+ float y = (idy * source.CurGraphHeight) / source.DY + source.off_Y;
+
+ if (y >= 0 && y < source.CurGraphHeight)
+ {
+ g.DrawLine(minorGridPen,
+ new Point((int)CurrOffX, (int)(CurOffY + y + 0.5f)),
+ new Point((int)(CurrOffX + source.CurGraphWidth + 0.5f), (int)(0.5f + CurOffY + y)));
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ private List DrawGraphCurve(Graphics g, DataSource source, float offset_x, float offset_y)
+ {
+ List marker_positions = new List();
+
+ if (DX != 0 && source.DY != 0)
+ {
+ List ps = new List();
+
+ if (source.Samples != null && source.Samples.Length > 1)
+ {
+
+ int DownSample = source.Downsampling;
+ PointF[] data = source.Samples;
+ float mult_y = source.CurGraphHeight / source.DY;
+ float mult_x = source.CurGraphWidth / DX;
+ float coff_x = off_X - starting_idx * mult_x;
+
+ if (source.AutoScaleX)
+ {
+ coff_x = off_X; // avoid dragging in x-autoscale mode
+ }
+
+ for (int i = 0; i < data.Length - 1; i += DownSample)
+ {
+ float x = data[i].X * mult_x + coff_x;
+ float y = data[i].Y * mult_y + source.off_Y;
+
+ int xi = (int)(data[i].X);
+
+ if (xi % grid_distance_x == 0)
+ {
+ if (x >= (0 - xLabelAreaheight) && x <= (source.CurGraphWidth + xLabelAreaheight))
+ {
+ marker_positions.Add(i);
+ }
+ }
+
+ if (x > 0 && x < (source.CurGraphWidth))
+ {
+ ps.Add(new Point((int)(x + offset_x+0.5f), (int)(y + offset_y + 0.5f)));
+ }
+ else if (x > source.CurGraphWidth)
+ {
+ break;
+ }
+ }
+
+ using (Pen p = new Pen(source.GraphColor))
+ {
+ if (ps.Count > 0)
+ {
+ g.DrawLines(p, ps.ToArray());
+ }
+ }
+ }
+ }
+ return marker_positions;
+ }
+
+
+ private void DrawGraphCaption(Graphics g, DataSource source, IList marker_pos, float offset_x, float offset_y)
+ {
+ using (Brush brush = new SolidBrush(source.GraphColor))
+ {
+ using (Pen pen = new Pen(brush))
+ {
+ pen.DashPattern = MajorGridPattern;
+
+ g.DrawString(source.Name, legendFont, brush, new PointF(offset_x + graphCaptionOffset.X + 12, offset_y +graphCaptionOffset.Y+ 2));
+
+ }
+ }
+ }
+
+
+ private void DrawXLabels(Graphics g, DataSource source, IList marker_pos, float offset_x, float offset_y)
+ {
+ Color XLabColor = source.GraphColor;
+
+ if (layout == LayoutMode.NORMAL || layout == LayoutMode.STACKED)
+ {
+ XLabColor = GraphBoxColor;
+ }
+
+ using (Brush brush = new SolidBrush(XLabColor))
+ {
+ using (Pen pen = new Pen(brush))
+ {
+ pen.DashPattern = MajorGridPattern;
+
+ if (DX != 0 && source.DY != 0)
+ {
+ if (source.Samples != null && source.Samples.Length > 1)
+ {
+ PointF[] data = source.Samples;
+
+ float mult_y = source.CurGraphHeight / source.DY;
+ float mult_x = source.CurGraphWidth / DX;
+
+ float coff_x = off_X - starting_idx * mult_x;
+
+ if (source.AutoScaleX)
+ {
+ coff_x = off_X; // avoid dragging in x-autoscale mode
+ }
+
+ foreach (int i in marker_pos)
+ {
+ int xi = (int)(data[i].X);
+
+ if (xi % grid_distance_x == 0)
+ {
+ float x = data[i].X * mult_x + coff_x;
+
+ String value = "" + data[i].X;
+
+ if (source.OnRenderXAxisLabel != null)
+ {
+ value = source.OnRenderXAxisLabel(source, i);
+ }
+
+ /// TODO: find out how to calculate this offset. Must be padding + something else
+ float unknownOffset = -14;// -14;
+
+ if (MoveMinorGrid == false)
+ {
+ g.DrawLine(pen, x, offset_y + GraphCaptionLineHeight + source.CurGraphHeight + unknownOffset,
+ x, offset_y + GraphCaptionLineHeight + source.CurGraphHeight);
+
+ g.DrawString(value, legendFont, brush,
+ new PointF((int)(0.5f + x + offset_x + 4),
+ GraphCaptionLineHeight + offset_y + source.CurGraphHeight + unknownOffset));
+ }
+ else
+ {
+ SizeF dim = g.MeasureString(value, legendFont);
+ g.DrawString(value, legendFont, brush,
+ new PointF((int)(0.5f + x + offset_x + 4 - dim.Width / 2),
+ GraphCaptionLineHeight + offset_y + source.CurGraphHeight + unknownOffset));
+
+ }
+ }
+ }
+ }
+ }
+
+
+ }
+ }
+ }
+
+
+ private void DrawYLabels(Graphics g, DataSource source, IList marker_pos, float offset_x, float offset_y )
+ {
+ using (Brush b = new SolidBrush(source.GraphColor))
+ {
+ using (Pen pen = new Pen(b))
+ {
+ pen.DashPattern = new float[] { 2, 2 };
+
+ float GridDistY = source.grid_distance_y;
+ ///
+ if (source.AutoScaleY)
+ {
+ // calculate a matching grid distance
+ GridDistY = -Utilities.MostSignificantDigit(source.DY);
+
+ if (GridDistY == 0)
+ {
+ GridDistY = source.grid_distance_y;
+ }
+ }
+
+ // draw labels for horizontal lines
+ if (source.DY != 0)
+ {
+ float y0 = (float)(source.grid_off_y * source.CurGraphHeight / source.DY + source.off_Y);
+ if (y0 >= 0 && y0 < source.CurGraphHeight)
+ {
+ String value = (source.OnRenderYAxisLabel == null) ? "0" : source.OnRenderYAxisLabel(source, 0);
+ SizeF dim = g.MeasureString(value, legendFont);
+ g.DrawString(value, legendFont, b, new PointF((int)offset_x - dim.Width, (int)(offset_y + y0 + 0.5f + dim.Height / 2)));
+ }
+
+ for (float Idx = source.grid_off_y; Idx > source.YD0; Idx -= GridDistY)
+ {
+ if (Idx != 0)
+ {
+ float y1 = (float)(Idx * source.CurGraphHeight) / source.DY + source.off_Y;
+
+ if (y1 >= 0 && y1 < source.CurGraphHeight)
+ {
+ string value = (source.OnRenderYAxisLabel == null) ? Idx.ToString() : source.OnRenderYAxisLabel(source, Idx);
+ SizeF dim = g.MeasureString(value, legendFont);
+ g.DrawString(value, legendFont, b, new PointF((int)offset_x - dim.Width, (int)(offset_y + y1 + 0.5f + dim.Height / 2)));
+ }
+ }
+ }
+
+ for (float Idx = source.grid_off_y; Idx < source.YD1; Idx += GridDistY)
+ {
+ if (Idx != 0)
+ {
+ float y2 = (float)(Idx * source.CurGraphHeight) / source.DY + source.off_Y;
+
+ if (y2 >= 0 && y2 < source.CurGraphHeight)
+ {
+ string value = (source.OnRenderYAxisLabel == null) ? Idx.ToString() : source.OnRenderYAxisLabel(source, Idx);
+ SizeF dim = g.MeasureString(value, legendFont);
+ g.DrawString(value, legendFont, b, new PointF((int)offset_x - dim.Width, (int)(offset_y + y2 + 0.5f + dim.Height / 2)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ private void DrawGraphBox(Graphics g, float offset_x, float offset_y, float w, float h )
+ {
+ using (Pen p2 = new Pen(GraphBoxColor))
+ {
+ g.DrawLine(p2, new Point((int)(offset_x + 0.5f), (int)(offset_y + 0.5f)),
+ new Point((int)(offset_x + w - 0.5f), (int)(offset_y + 0.5f)));
+
+ g.DrawLine(p2, new Point((int)(offset_x + w - 0.5f), (int)(offset_y + 0.5f)),
+ new Point((int)(offset_x + w - 0.5f), (int)(offset_y + h + 0.5f)));
+
+ g.DrawLine(p2, new Point((int)(offset_x + w - 0.5f), (int)(offset_y + h + 0.5f)),
+ new Point((int)(offset_x + 0.5f), (int)(offset_y + h + 0.5f)));
+
+ g.DrawLine(p2, new Point((int)(offset_x + 0.5f), (int)(offset_y + h + 0.5f)),
+ new Point((int)(offset_x + 0.5f), (int)(offset_y + 0.5f)));
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.resx b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.resx
new file mode 100644
index 00000000..19dc0dd8
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphPaneEx.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.Designer.cs b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.Designer.cs
new file mode 100644
index 00000000..331db07e
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.Designer.cs
@@ -0,0 +1,365 @@
+namespace GraphLib
+{
+ partial class PlotterGraphSelectCurvesForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.lb_Graphs = new System.Windows.Forms.CheckedListBox();
+ this.gB_SelectedGraph = new System.Windows.Forms.GroupBox();
+ this.cb_X_AutoScale = new System.Windows.Forms.CheckBox();
+ this.tb_GraphName = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.cbDownSampling = new System.Windows.Forms.ComboBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.btn_GraphColor = new System.Windows.Forms.Button();
+ this.cb_Y_AutoScale = new System.Windows.Forms.CheckBox();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.label7 = new System.Windows.Forms.Label();
+ this.label5 = new System.Windows.Forms.Label();
+ this.bt_MinorGridColor = new System.Windows.Forms.Button();
+ this.bt_bg_col_bot = new System.Windows.Forms.Button();
+ this.label6 = new System.Windows.Forms.Label();
+ this.bt_MajorGridColor = new System.Windows.Forms.Button();
+ this.label4 = new System.Windows.Forms.Label();
+ this.bt_bg_col_top = new System.Windows.Forms.Button();
+ this.btn_AutoScaleAll = new System.Windows.Forms.Button();
+ this.label1 = new System.Windows.Forms.Label();
+ this.cb_Layout = new System.Windows.Forms.ComboBox();
+ this.button1 = new System.Windows.Forms.Button();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ this.gB_SelectedGraph.SuspendLayout();
+ this.groupBox1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Name = "splitContainer1";
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.lb_Graphs);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.gB_SelectedGraph);
+ this.splitContainer1.Panel2.Controls.Add(this.groupBox1);
+ this.splitContainer1.Panel2.Controls.Add(this.button1);
+ this.splitContainer1.Size = new System.Drawing.Size(395, 431);
+ this.splitContainer1.SplitterDistance = 171;
+ this.splitContainer1.TabIndex = 0;
+ //
+ // lb_Graphs
+ //
+ this.lb_Graphs.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.lb_Graphs.FormattingEnabled = true;
+ this.lb_Graphs.Location = new System.Drawing.Point(0, 0);
+ this.lb_Graphs.Name = "lb_Graphs";
+ this.lb_Graphs.Size = new System.Drawing.Size(171, 424);
+ this.lb_Graphs.TabIndex = 0;
+ this.lb_Graphs.SelectedIndexChanged += new System.EventHandler(this.checkedListBox1_SelectedIndexChanged_1);
+ //
+ // gB_SelectedGraph
+ //
+ this.gB_SelectedGraph.Controls.Add(this.cb_X_AutoScale);
+ this.gB_SelectedGraph.Controls.Add(this.tb_GraphName);
+ this.gB_SelectedGraph.Controls.Add(this.label3);
+ this.gB_SelectedGraph.Controls.Add(this.cbDownSampling);
+ this.gB_SelectedGraph.Controls.Add(this.label2);
+ this.gB_SelectedGraph.Controls.Add(this.btn_GraphColor);
+ this.gB_SelectedGraph.Controls.Add(this.cb_Y_AutoScale);
+ this.gB_SelectedGraph.Location = new System.Drawing.Point(6, 232);
+ this.gB_SelectedGraph.Name = "gB_SelectedGraph";
+ this.gB_SelectedGraph.Size = new System.Drawing.Size(206, 158);
+ this.gB_SelectedGraph.TabIndex = 6;
+ this.gB_SelectedGraph.TabStop = false;
+ this.gB_SelectedGraph.Text = "Selected Graph Options";
+ this.gB_SelectedGraph.Visible = false;
+ //
+ // cb_X_AutoScale
+ //
+ this.cb_X_AutoScale.AutoSize = true;
+ this.cb_X_AutoScale.Location = new System.Drawing.Point(12, 102);
+ this.cb_X_AutoScale.Name = "cb_X_AutoScale";
+ this.cb_X_AutoScale.Size = new System.Drawing.Size(93, 17);
+ this.cb_X_AutoScale.TabIndex = 8;
+ this.cb_X_AutoScale.Text = "X AutoScaling";
+ this.cb_X_AutoScale.UseVisualStyleBackColor = true;
+ this.cb_X_AutoScale.CheckedChanged += new System.EventHandler(this.cb_X_AutoScale_CheckedChanged);
+ //
+ // tb_GraphName
+ //
+ this.tb_GraphName.Location = new System.Drawing.Point(12, 24);
+ this.tb_GraphName.Name = "tb_GraphName";
+ this.tb_GraphName.Size = new System.Drawing.Size(167, 20);
+ this.tb_GraphName.TabIndex = 7;
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(52, 133);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(76, 13);
+ this.label3.TabIndex = 6;
+ this.label3.Text = "Downsampling";
+ //
+ // cbDownSampling
+ //
+ this.cbDownSampling.FormattingEnabled = true;
+ this.cbDownSampling.Items.AddRange(new object[] {
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6"});
+ this.cbDownSampling.Location = new System.Drawing.Point(7, 130);
+ this.cbDownSampling.Name = "cbDownSampling";
+ this.cbDownSampling.Size = new System.Drawing.Size(39, 21);
+ this.cbDownSampling.TabIndex = 5;
+ this.cbDownSampling.Text = "1";
+ this.cbDownSampling.SelectedIndexChanged += new System.EventHandler(this.OnDownsamplingChanged);
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(57, 55);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(63, 13);
+ this.label2.TabIndex = 4;
+ this.label2.Text = "Graph Color";
+ //
+ // btn_GraphColor
+ //
+ this.btn_GraphColor.Location = new System.Drawing.Point(11, 50);
+ this.btn_GraphColor.Name = "btn_GraphColor";
+ this.btn_GraphColor.Size = new System.Drawing.Size(26, 23);
+ this.btn_GraphColor.TabIndex = 3;
+ this.btn_GraphColor.UseVisualStyleBackColor = true;
+ this.btn_GraphColor.Click += new System.EventHandler(this.btn_GraphColor_Click);
+ //
+ // cb_Y_AutoScale
+ //
+ this.cb_Y_AutoScale.AutoSize = true;
+ this.cb_Y_AutoScale.Location = new System.Drawing.Point(12, 79);
+ this.cb_Y_AutoScale.Name = "cb_Y_AutoScale";
+ this.cb_Y_AutoScale.Size = new System.Drawing.Size(93, 17);
+ this.cb_Y_AutoScale.TabIndex = 2;
+ this.cb_Y_AutoScale.Text = "Y AutoScaling";
+ this.cb_Y_AutoScale.UseVisualStyleBackColor = true;
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.label7);
+ this.groupBox1.Controls.Add(this.label5);
+ this.groupBox1.Controls.Add(this.bt_MinorGridColor);
+ this.groupBox1.Controls.Add(this.bt_bg_col_bot);
+ this.groupBox1.Controls.Add(this.label6);
+ this.groupBox1.Controls.Add(this.bt_MajorGridColor);
+ this.groupBox1.Controls.Add(this.label4);
+ this.groupBox1.Controls.Add(this.bt_bg_col_top);
+ this.groupBox1.Controls.Add(this.btn_AutoScaleAll);
+ this.groupBox1.Controls.Add(this.label1);
+ this.groupBox1.Controls.Add(this.cb_Layout);
+ this.groupBox1.Location = new System.Drawing.Point(6, 5);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(206, 221);
+ this.groupBox1.TabIndex = 4;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "General Options";
+ //
+ // label7
+ //
+ this.label7.AutoSize = true;
+ this.label7.Location = new System.Drawing.Point(57, 194);
+ this.label7.Name = "label7";
+ this.label7.Size = new System.Drawing.Size(82, 13);
+ this.label7.TabIndex = 10;
+ this.label7.Text = "Minor Grid Color";
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(57, 136);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(128, 13);
+ this.label5.TabIndex = 8;
+ this.label5.Text = "Background Color Bottom";
+ //
+ // bt_MinorGridColor
+ //
+ this.bt_MinorGridColor.Location = new System.Drawing.Point(11, 189);
+ this.bt_MinorGridColor.Name = "bt_MinorGridColor";
+ this.bt_MinorGridColor.Size = new System.Drawing.Size(26, 23);
+ this.bt_MinorGridColor.TabIndex = 9;
+ this.bt_MinorGridColor.UseVisualStyleBackColor = true;
+ this.bt_MinorGridColor.Click += new System.EventHandler(this.bt_MinorGridColor_Click);
+ //
+ // bt_bg_col_bot
+ //
+ this.bt_bg_col_bot.Location = new System.Drawing.Point(11, 131);
+ this.bt_bg_col_bot.Name = "bt_bg_col_bot";
+ this.bt_bg_col_bot.Size = new System.Drawing.Size(26, 23);
+ this.bt_bg_col_bot.TabIndex = 7;
+ this.bt_bg_col_bot.UseVisualStyleBackColor = true;
+ this.bt_bg_col_bot.Click += new System.EventHandler(this.bt_bg_col_bot_Click);
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(57, 165);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(82, 13);
+ this.label6.TabIndex = 8;
+ this.label6.Text = "Major Grid Color";
+ //
+ // bt_MajorGridColor
+ //
+ this.bt_MajorGridColor.Location = new System.Drawing.Point(11, 160);
+ this.bt_MajorGridColor.Name = "bt_MajorGridColor";
+ this.bt_MajorGridColor.Size = new System.Drawing.Size(26, 23);
+ this.bt_MajorGridColor.TabIndex = 7;
+ this.bt_MajorGridColor.UseVisualStyleBackColor = true;
+ this.bt_MajorGridColor.Click += new System.EventHandler(this.bt_MajorGridColor_Click);
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(57, 107);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(114, 13);
+ this.label4.TabIndex = 6;
+ this.label4.Text = "Background Color Top";
+ //
+ // bt_bg_col_top
+ //
+ this.bt_bg_col_top.Location = new System.Drawing.Point(11, 102);
+ this.bt_bg_col_top.Name = "bt_bg_col_top";
+ this.bt_bg_col_top.Size = new System.Drawing.Size(26, 23);
+ this.bt_bg_col_top.TabIndex = 5;
+ this.bt_bg_col_top.UseVisualStyleBackColor = true;
+ this.bt_bg_col_top.Click += new System.EventHandler(this.bt_bg_col_top_Click);
+ //
+ // btn_AutoScaleAll
+ //
+ this.btn_AutoScaleAll.Location = new System.Drawing.Point(11, 69);
+ this.btn_AutoScaleAll.Name = "btn_AutoScaleAll";
+ this.btn_AutoScaleAll.Size = new System.Drawing.Size(167, 25);
+ this.btn_AutoScaleAll.TabIndex = 4;
+ this.btn_AutoScaleAll.Text = "Auto Scale All";
+ this.btn_AutoScaleAll.UseVisualStyleBackColor = true;
+ this.btn_AutoScaleAll.Click += new System.EventHandler(this.OnButtonAutoScallOnClicked);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(9, 26);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(39, 13);
+ this.label1.TabIndex = 3;
+ this.label1.Text = "Layout";
+ //
+ // cb_Layout
+ //
+ this.cb_Layout.FormattingEnabled = true;
+ this.cb_Layout.Items.AddRange(new object[] {
+ "Normal",
+ "Stacked",
+ "Tiles - Fill Vertical",
+ "Tiles - Fill Horizontal",
+ "Vertically"});
+ this.cb_Layout.Location = new System.Drawing.Point(11, 42);
+ this.cb_Layout.Name = "cb_Layout";
+ this.cb_Layout.Size = new System.Drawing.Size(168, 21);
+ this.cb_Layout.TabIndex = 2;
+ this.cb_Layout.Text = "Select";
+ this.cb_Layout.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(66, 396);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(68, 23);
+ this.button1.TabIndex = 0;
+ this.button1.Text = "Exit";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // PlotterGraphSelectCurvesForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(395, 431);
+ this.Controls.Add(this.splitContainer1);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.MinimumSize = new System.Drawing.Size(16, 246);
+ this.Name = "PlotterGraphSelectCurvesForm";
+ this.Text = "Graph Properties";
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ this.splitContainer1.ResumeLayout(false);
+ this.gB_SelectedGraph.ResumeLayout(false);
+ this.gB_SelectedGraph.PerformLayout();
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.CheckedListBox lb_Graphs;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.ComboBox cb_Layout;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Button btn_GraphColor;
+ private System.Windows.Forms.CheckBox cb_Y_AutoScale;
+ private System.Windows.Forms.Button btn_AutoScaleAll;
+ private System.Windows.Forms.GroupBox gB_SelectedGraph;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.ComboBox cbDownSampling;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Button bt_bg_col_top;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Button bt_bg_col_bot;
+ private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.Button bt_MinorGridColor;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.Button bt_MajorGridColor;
+ private System.Windows.Forms.TextBox tb_GraphName;
+ private System.Windows.Forms.CheckBox cb_X_AutoScale;
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.cs b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.cs
new file mode 100644
index 00000000..115e44dc
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.cs
@@ -0,0 +1,369 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+
+/* Copyright (c) 2008-2014 DI Zimmermann Stephan (stefan.zimmermann@tele2.at)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+namespace GraphLib
+{
+ public partial class PlotterGraphSelectCurvesForm : Form
+ {
+ private int selectetGraphIndex = -1;
+
+ private PlotterGraphPaneEx gpane = null;
+
+ public PlotterGraphSelectCurvesForm()
+ {
+ InitializeComponent();
+ FormClosing += new FormClosingEventHandler(OnFormClosing);
+ lb_Graphs.SelectedIndexChanged += new EventHandler(OnSelectedGraphIndexChanged);
+ VisibleChanged += new EventHandler(OnVisibleChanged);
+ tb_GraphName.TextChanged += new EventHandler(tb_GraphName_TextChanged);
+ }
+
+ void tb_GraphName_TextChanged(object sender, EventArgs e)
+ {
+ if (selectetGraphIndex >= 0 && selectetGraphIndex < gpane.Sources.Count)
+ {
+ DataSource src = gpane.Sources[selectetGraphIndex];
+ String Text = tb_GraphName.Text;
+
+ if (String.IsNullOrEmpty(Text) == false)
+ {
+ src.Name = Text;
+ gpane.Invalidate();
+ }
+ }
+ }
+
+ public PlotterGraphPaneEx GraphPanel
+ {
+ set
+ {
+ gpane = value;
+ if (gpane != null)
+ {
+ this.lb_Graphs.Items.Clear();
+
+ foreach (DataSource s in gpane.Sources)
+ {
+ if (s.Active)
+ {
+ this.lb_Graphs.Items.Add(s.Name, CheckState.Checked);
+ }
+ else
+ {
+ this.lb_Graphs.Items.Add(s.Name, CheckState.Unchecked);
+ }
+ }
+
+ UpdateAllCheckedState();
+ }
+ }
+ }
+
+ void UpdateAllCheckedState()
+ {
+ int AutoScaleOn = 0;
+
+ foreach (DataSource src in gpane.Sources)
+ {
+ if (src.AutoScaleY)
+ {
+ AutoScaleOn++;
+ }
+ }
+
+ if (AutoScaleOn == 0)
+ {
+ btn_AutoScaleAll.Visible = true;
+ btn_AutoScaleAll.Text = "Auto Y-Scale all Graphs";
+ }
+ else
+ {
+ btn_AutoScaleAll.Visible = true;
+ btn_AutoScaleAll.Text = "Normal Y-Scale all Graphs";
+ }
+ }
+
+ void OnVisibleChanged(object sender, EventArgs e)
+ {
+ if (this.Visible == true)
+ {
+ selectetGraphIndex = -1;
+ gB_SelectedGraph.Visible = false;
+
+ if (gpane != null)
+ {
+ UpdateAllCheckedState();
+
+ if (gpane.layout == PlotterGraphPaneEx.LayoutMode.NORMAL)
+ {
+ cb_Layout.SelectedIndex = 0;
+ }
+ else if (gpane.layout == PlotterGraphPaneEx.LayoutMode.STACKED)
+ {
+ cb_Layout.SelectedIndex = 1;
+ }
+ else if (gpane.layout == PlotterGraphPaneEx.LayoutMode.TILES_HOR)
+ {
+ cb_Layout.SelectedIndex = 2;
+ }
+ else if (gpane.layout == PlotterGraphPaneEx.LayoutMode.TILES_VER)
+ {
+ cb_Layout.SelectedIndex = 3;
+ }
+ else if (gpane.layout == PlotterGraphPaneEx.LayoutMode.VERTICAL_ARRANGED)
+ {
+ cb_Layout.SelectedIndex = 4;
+ }
+
+ bt_bg_col_top.BackColor = gpane.BgndColorTop;
+ bt_bg_col_bot.BackColor = gpane.BgndColorBot;
+ bt_MajorGridColor.BackColor = gpane.MajorGridColor;
+ bt_MinorGridColor.BackColor = gpane.MinorGridColor;
+
+ }
+ }
+ }
+
+
+ void OnSelectedGraphIndexChanged(object sender, EventArgs e)
+ {
+ if (gpane != null)
+ {
+ for (int i = 0; i < gpane.Sources.Count; i++)
+ {
+ if (lb_Graphs.CheckedIndices.Contains(i))
+ {
+ gpane.Sources[i].Active = true;
+ }
+ else
+ {
+ gpane.Sources[i].Active = false;
+ }
+ }
+ gpane.Invalidate();
+ }
+ }
+
+ void OnFormClosing(object sender, FormClosingEventArgs e)
+ {
+ this.Hide();
+ e.Cancel = true;
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ this.Hide();
+ }
+
+ private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (cb_Layout.SelectedIndex == 0)
+ {
+ gpane.layout = PlotterGraphPaneEx.LayoutMode.NORMAL;
+ }
+ if (cb_Layout.SelectedIndex == 1)
+ {
+ gpane.layout = PlotterGraphPaneEx.LayoutMode.STACKED;
+ }
+
+ if (cb_Layout.SelectedIndex == 2)
+ {
+ gpane.layout = PlotterGraphPaneEx.LayoutMode.TILES_VER;
+ }
+ if (cb_Layout.SelectedIndex == 3)
+ {
+ gpane.layout = PlotterGraphPaneEx.LayoutMode.TILES_HOR;
+ }
+ if (cb_Layout.SelectedIndex == 4)
+ {
+ gpane.layout = PlotterGraphPaneEx.LayoutMode.VERTICAL_ARRANGED;
+ }
+ gpane.Invalidate();
+ }
+
+ private void checkedListBox1_SelectedIndexChanged_1(object sender, EventArgs e)
+ {
+ selectetGraphIndex = lb_Graphs.SelectedIndex;
+
+ UpdateSelectedGraphInfo();
+ gB_SelectedGraph.Visible = true;
+ }
+
+ private void UpdateSelectedGraphInfo()
+ {
+ if (selectetGraphIndex >= 0 && selectetGraphIndex < gpane.Sources.Count)
+ {
+ DataSource src = gpane.Sources[selectetGraphIndex];
+ btn_GraphColor.BackColor = src.GraphColor;
+
+ cb_Y_AutoScale.Checked = src.AutoScaleY;
+ cb_X_AutoScale.Checked = src.AutoScaleX;
+
+ cbDownSampling.SelectedIndex = (src.Downsampling - 1);
+ tb_GraphName.Text = src.Name;
+ }
+ }
+
+ private void btn_GraphColor_Click(object sender, EventArgs e)
+ {
+ if (selectetGraphIndex >= 0 && selectetGraphIndex < gpane.Sources.Count)
+ {
+ DataSource src = gpane.Sources[selectetGraphIndex];
+ ColorDialog d = new ColorDialog();
+ if (d.ShowDialog() == DialogResult.OK)
+ {
+ btn_GraphColor.BackColor = d.Color;
+ src.GraphColor = d.Color;
+ gpane.Invalidate();
+ }
+ }
+ }
+
+
+ private void OnButtonAutoScallOnClicked(object sender, EventArgs e)
+ {
+ int AutoScaleOn = 0;
+
+ foreach (DataSource src in gpane.Sources)
+ {
+ if (src.AutoScaleY)
+ {
+ AutoScaleOn++;
+ }
+ }
+
+ if (AutoScaleOn == 0)
+ {
+ btn_AutoScaleAll.Text = "Normal scale for all graphs";
+ foreach (DataSource src in gpane.Sources)
+ {
+ src.AutoScaleY = true;
+ }
+ }
+ else
+ {
+ btn_AutoScaleAll.Text = "Auto scale for all graphs";
+ foreach (DataSource src in gpane.Sources)
+ {
+ src.AutoScaleY = false;
+ }
+ }
+
+ UpdateSelectedGraphInfo();
+ gpane.Invalidate();
+ }
+
+ private void OnDownsamplingChanged(object sender, EventArgs e)
+ {
+ if (selectetGraphIndex >= 0 && selectetGraphIndex < gpane.Sources.Count)
+ {
+ DataSource src = gpane.Sources[selectetGraphIndex];
+
+ src.Downsampling = (cbDownSampling.SelectedIndex + 1);
+ }
+
+ gpane.Invalidate();
+ }
+
+ private void bt_bg_col_top_Click(object sender, EventArgs e)
+ {
+ ColorDialog d = new ColorDialog();
+ if (d.ShowDialog() == DialogResult.OK)
+ {
+ bt_bg_col_top.BackColor = d.Color;
+ gpane.BgndColorTop = d.Color;
+
+ gpane.Invalidate();
+ }
+ }
+
+ private void bt_bg_col_bot_Click(object sender, EventArgs e)
+ {
+ ColorDialog d = new ColorDialog();
+ if (d.ShowDialog() == DialogResult.OK)
+ {
+ bt_bg_col_bot.BackColor = d.Color;
+ gpane.BgndColorBot = d.Color;
+ gpane.Invalidate();
+ }
+ }
+
+ private void bt_MajorGridColor_Click(object sender, EventArgs e)
+ {
+ ColorDialog d = new ColorDialog();
+ if (d.ShowDialog() == DialogResult.OK)
+ {
+ bt_MajorGridColor.BackColor = d.Color;
+ gpane.MajorGridColor = d.Color;
+ gpane.Invalidate();
+ }
+ }
+
+ private void bt_MinorGridColor_Click(object sender, EventArgs e)
+ {
+ ColorDialog d = new ColorDialog();
+ if (d.ShowDialog() == DialogResult.OK)
+ {
+ bt_MinorGridColor.BackColor = d.Color;
+ gpane.MinorGridColor = d.Color;
+ gpane.Invalidate();
+ }
+ }
+
+ private void cb_Y_AutoScale_CheckedChanged(object sender, EventArgs e)
+ {
+ if (selectetGraphIndex >= 0 && selectetGraphIndex < gpane.Sources.Count)
+ {
+ DataSource src = gpane.Sources[selectetGraphIndex];
+
+ src.AutoScaleY = cb_Y_AutoScale.Checked;
+
+ UpdateAllCheckedState();
+
+ gpane.Invalidate();
+ }
+ }
+
+ private void cb_X_AutoScale_CheckedChanged(object sender, EventArgs e)
+ {
+ if (selectetGraphIndex >= 0 && selectetGraphIndex < gpane.Sources.Count)
+ {
+ DataSource src = gpane.Sources[selectetGraphIndex];
+
+ src.AutoScaleX = cb_X_AutoScale.Checked;
+
+ UpdateAllCheckedState();
+
+ gpane.Invalidate();
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.resx b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.resx
new file mode 100644
index 00000000..19dc0dd8
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PlotterGraphSelectCurvesForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/PrecisionTimer.cs b/TBF_V2/Sources/TBF/GraphLib/PrecisionTimer.cs
new file mode 100644
index 00000000..5480f2e1
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PrecisionTimer.cs
@@ -0,0 +1,490 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+#region License
+
+/*
+ * Based on the work of Leslie Sanford
+ */
+
+#endregion
+
+
+namespace PrecisionTimer
+{
+ public enum Mode
+ {
+ OneShot,
+ Periodic
+ };
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TimerCaps
+ {
+ public int periodMin;
+ public int periodMax;
+ }
+
+
+ public sealed class Timer : IComponent
+ {
+ private delegate void TimeProc(int id, int msg, int user, int param1, int param2);
+
+ private delegate void EventRaiser(EventArgs e);
+
+ [DllImport("winmm.dll")]
+ private static extern int timeGetDevCaps(ref TimerCaps caps,
+ int sizeOfTimerCaps);
+
+ [DllImport("winmm.dll")]
+ private static extern int timeSetEvent(int delay,
+ int resolution,
+ TimeProc proc,
+ int user,
+ int mode);
+
+ [DllImport("winmm.dll")]
+ private static extern int timeKillEvent(int id);
+
+ private const int TIMERR_NOERROR = 0;
+
+ private int timerID;
+
+ private volatile Mode mode;
+
+ private volatile int period;
+
+ private volatile int resolution;
+
+ private TimeProc timeProcPeriodic;
+
+ private TimeProc timeProcOneShot;
+
+ private EventRaiser tickRaiser;
+
+ private bool running = false;
+
+ private volatile bool disposed = false;
+
+ private ISynchronizeInvoke synchronizingObject = null;
+
+ private ISite site = null;
+
+ private static TimerCaps caps;
+
+ public event EventHandler Started;
+
+ public event EventHandler Stopped;
+
+ public event EventHandler Tick;
+
+ static Timer()
+ {
+ // Get multimedia timer capabilities.
+ timeGetDevCaps(ref caps, Marshal.SizeOf(caps));
+ }
+
+
+ public Timer(IContainer container)
+ {
+
+ container.Add(this);
+
+ Initialize();
+ }
+
+
+ public Timer()
+ {
+ Initialize();
+ }
+
+ ~Timer()
+ {
+ if(IsRunning)
+ {
+ // Stop and destroy timer.
+ timeKillEvent(timerID);
+ }
+ }
+
+ private void Initialize()
+ {
+ this.mode = Mode.Periodic;
+ this.period = Capabilities.periodMin;
+ this.resolution = 1;
+
+ running = false;
+
+ timeProcPeriodic = new TimeProc(TimerPeriodicEventCallback);
+ timeProcOneShot = new TimeProc(TimerOneShotEventCallback);
+ tickRaiser = new EventRaiser(OnTick);
+ }
+
+
+ public void Start()
+ {
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+ if(IsRunning)
+ {
+ return;
+ }
+
+ if(Mode == Mode.Periodic)
+ {
+ timerID = timeSetEvent(Period, Resolution, timeProcPeriodic, 0, (int)Mode);
+ }
+ else
+ {
+ timerID = timeSetEvent(Period, Resolution, timeProcOneShot, 0, (int)Mode);
+ }
+
+ if(timerID != 0)
+ {
+ running = true;
+
+ if(SynchronizingObject != null && SynchronizingObject.InvokeRequired)
+ {
+ SynchronizingObject.BeginInvoke(
+ new EventRaiser(OnStarted),
+ new object[] { EventArgs.Empty });
+ }
+ else
+ {
+ OnStarted(EventArgs.Empty);
+ }
+ }
+ else
+ {
+ throw new TimerException("Unable to start timer.");
+ }
+ }
+
+
+ public void Stop()
+ {
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+ if(!running)
+ {
+ return;
+ }
+
+
+ int result = timeKillEvent(timerID);
+
+ Debug.Assert(result == TIMERR_NOERROR);
+
+ running = false;
+
+ if(SynchronizingObject != null && SynchronizingObject.InvokeRequired)
+ {
+ SynchronizingObject.BeginInvoke(
+ new EventRaiser(OnStopped),
+ new object[] { EventArgs.Empty });
+ }
+ else
+ {
+ OnStopped(EventArgs.Empty);
+ }
+ }
+
+
+ private void TimerPeriodicEventCallback(int id, int msg, int user, int param1, int param2)
+ {
+ if(synchronizingObject != null)
+ {
+ synchronizingObject.BeginInvoke(tickRaiser, new object[] { EventArgs.Empty });
+ }
+ else
+ {
+ OnTick(EventArgs.Empty);
+ }
+ }
+
+ private void TimerOneShotEventCallback(int id, int msg, int user, int param1, int param2)
+ {
+ if(synchronizingObject != null)
+ {
+ synchronizingObject.BeginInvoke(tickRaiser, new object[] { EventArgs.Empty });
+ Stop();
+ }
+ else
+ {
+ OnTick(EventArgs.Empty);
+ Stop();
+ }
+ }
+
+
+
+ // Raises the Disposed event.
+ private void OnDisposed(EventArgs e)
+ {
+ EventHandler handler = Disposed;
+
+ if(handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ // Raises the Started event.
+ private void OnStarted(EventArgs e)
+ {
+ EventHandler handler = Started;
+
+ if(handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ // Raises the Stopped event.
+ private void OnStopped(EventArgs e)
+ {
+ EventHandler handler = Stopped;
+
+ if(handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ // Raises the Tick event.
+ private void OnTick(EventArgs e)
+ {
+ EventHandler handler = Tick;
+
+ if(handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+
+
+
+
+ ///
+ /// Gets or sets the object used to marshal event-handler calls.
+ ///
+ public ISynchronizeInvoke SynchronizingObject
+ {
+ get
+ {
+ #region Require
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+ #endregion
+
+ return synchronizingObject;
+ }
+ set
+ {
+ #region Require
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+ #endregion
+
+ synchronizingObject = value;
+ }
+ }
+
+
+ public int Period
+ {
+ get
+ {
+ #region Require
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+ #endregion
+
+ return period;
+ }
+ set
+ {
+ #region Require
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+ else if(value < Capabilities.periodMin || value > Capabilities.periodMax)
+ {
+ throw new ArgumentOutOfRangeException("Period", value,
+ "Multimedia Timer period out of range.");
+ }
+
+ #endregion
+
+ period = value;
+
+ if(IsRunning)
+ {
+ Stop();
+ Start();
+ }
+ }
+ }
+
+
+ public int Resolution
+ {
+ get
+ {
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+ return resolution;
+ }
+ set
+ {
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+ else if(value < 0)
+ {
+ throw new ArgumentOutOfRangeException("Resolution", value,
+ "timer resolution out of range.");
+ }
+
+ resolution = value;
+
+ if(IsRunning)
+ {
+ Stop();
+ Start();
+ }
+ }
+ }
+
+ public Mode Mode
+ {
+ get
+ {
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+
+ return mode;
+ }
+ set
+ {
+
+ if(disposed)
+ {
+ throw new ObjectDisposedException("Timer");
+ }
+
+
+ mode = value;
+
+ if(IsRunning)
+ {
+ Stop();
+ Start();
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the Timer is running.
+ ///
+ public bool IsRunning
+ {
+ get
+ {
+ return running;
+ }
+ }
+
+ ///
+ /// Gets the timer capabilities.
+ ///
+ public static TimerCaps Capabilities
+ {
+ get
+ {
+ return caps;
+ }
+ }
+
+
+
+
+ public event System.EventHandler Disposed;
+
+ public ISite Site
+ {
+ get
+ {
+ return site;
+ }
+ set
+ {
+ site = value;
+ }
+ }
+
+
+ public void Dispose()
+ {
+
+ if(disposed)
+ {
+ return;
+ }
+
+ if(IsRunning)
+ {
+ Stop();
+ }
+
+ disposed = true;
+
+ OnDisposed(EventArgs.Empty);
+ }
+
+
+ }
+
+
+ public class TimerException : ApplicationException
+ {
+ public TimerException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.Designer.cs b/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.Designer.cs
new file mode 100644
index 00000000..fd880fb8
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.Designer.cs
@@ -0,0 +1,264 @@
+namespace GraphLib
+{
+ partial class PrintPreviewForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.printPreviewCtrl = new System.Windows.Forms.PrintPreviewControl();
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.rb_Unscaled = new System.Windows.Forms.RadioButton();
+ this.rb_BestFit = new System.Windows.Forms.RadioButton();
+ this.rb_Scale = new System.Windows.Forms.RadioButton();
+ this.cb_PrintBackground = new System.Windows.Forms.CheckBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.cb_Printer = new System.Windows.Forms.ComboBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.cb_Orientation = new System.Windows.Forms.ComboBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.cb_PaperSize = new System.Windows.Forms.ComboBox();
+ this.bt_Cancel = new System.Windows.Forms.Button();
+ this.bt_print = new System.Windows.Forms.Button();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ this.groupBox1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // printPreviewCtrl
+ //
+ this.printPreviewCtrl.BackColor = System.Drawing.SystemColors.ControlLight;
+ this.printPreviewCtrl.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.printPreviewCtrl.Location = new System.Drawing.Point(0, 0);
+ this.printPreviewCtrl.Name = "printPreviewCtrl";
+ this.printPreviewCtrl.Size = new System.Drawing.Size(453, 501);
+ this.printPreviewCtrl.TabIndex = 1;
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+ this.splitContainer1.IsSplitterFixed = true;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Name = "splitContainer1";
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.printPreviewCtrl);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.groupBox1);
+ this.splitContainer1.Panel2.Controls.Add(this.cb_PrintBackground);
+ this.splitContainer1.Panel2.Controls.Add(this.label3);
+ this.splitContainer1.Panel2.Controls.Add(this.cb_Printer);
+ this.splitContainer1.Panel2.Controls.Add(this.label2);
+ this.splitContainer1.Panel2.Controls.Add(this.cb_Orientation);
+ this.splitContainer1.Panel2.Controls.Add(this.label1);
+ this.splitContainer1.Panel2.Controls.Add(this.cb_PaperSize);
+ this.splitContainer1.Panel2.Controls.Add(this.bt_Cancel);
+ this.splitContainer1.Panel2.Controls.Add(this.bt_print);
+ this.splitContainer1.Size = new System.Drawing.Size(681, 501);
+ this.splitContainer1.SplitterDistance = 453;
+ this.splitContainer1.TabIndex = 2;
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.rb_Unscaled);
+ this.groupBox1.Controls.Add(this.rb_BestFit);
+ this.groupBox1.Controls.Add(this.rb_Scale);
+ this.groupBox1.Location = new System.Drawing.Point(18, 188);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(93, 93);
+ this.groupBox1.TabIndex = 12;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Scaling";
+ //
+ // rb_Unscaled
+ //
+ this.rb_Unscaled.AutoSize = true;
+ this.rb_Unscaled.Location = new System.Drawing.Point(13, 19);
+ this.rb_Unscaled.Name = "rb_Unscaled";
+ this.rb_Unscaled.Size = new System.Drawing.Size(70, 17);
+ this.rb_Unscaled.TabIndex = 8;
+ this.rb_Unscaled.TabStop = true;
+ this.rb_Unscaled.Text = "Unscaled";
+ this.rb_Unscaled.UseVisualStyleBackColor = true;
+ this.rb_Unscaled.CheckedChanged += new System.EventHandler(this.rb_Unscaled_CheckedChanged);
+ //
+ // rb_BestFit
+ //
+ this.rb_BestFit.AutoSize = true;
+ this.rb_BestFit.Location = new System.Drawing.Point(13, 65);
+ this.rb_BestFit.Name = "rb_BestFit";
+ this.rb_BestFit.Size = new System.Drawing.Size(60, 17);
+ this.rb_BestFit.TabIndex = 6;
+ this.rb_BestFit.TabStop = true;
+ this.rb_BestFit.Text = "Best Fit";
+ this.rb_BestFit.UseVisualStyleBackColor = true;
+ this.rb_BestFit.CheckedChanged += new System.EventHandler(this.rb_BestFit_CheckedChanged);
+ //
+ // rb_Scale
+ //
+ this.rb_Scale.AutoSize = true;
+ this.rb_Scale.Location = new System.Drawing.Point(13, 42);
+ this.rb_Scale.Name = "rb_Scale";
+ this.rb_Scale.Size = new System.Drawing.Size(52, 17);
+ this.rb_Scale.TabIndex = 7;
+ this.rb_Scale.TabStop = true;
+ this.rb_Scale.Text = "Scale";
+ this.rb_Scale.UseVisualStyleBackColor = true;
+ this.rb_Scale.CheckedChanged += new System.EventHandler(this.rb_Scale_CheckedChanged);
+ //
+ // cb_PrintBackground
+ //
+ this.cb_PrintBackground.AutoSize = true;
+ this.cb_PrintBackground.Location = new System.Drawing.Point(22, 321);
+ this.cb_PrintBackground.Name = "cb_PrintBackground";
+ this.cb_PrintBackground.Size = new System.Drawing.Size(108, 17);
+ this.cb_PrintBackground.TabIndex = 11;
+ this.cb_PrintBackground.Text = "Print Background";
+ this.cb_PrintBackground.UseVisualStyleBackColor = true;
+ this.cb_PrintBackground.Visible = false;
+ this.cb_PrintBackground.CheckedChanged += new System.EventHandler(this.cb_PrintBackground_CheckedChanged);
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(19, 29);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(37, 13);
+ this.label3.TabIndex = 10;
+ this.label3.Text = "Printer";
+ //
+ // cb_Printer
+ //
+ this.cb_Printer.FormattingEnabled = true;
+ this.cb_Printer.Location = new System.Drawing.Point(18, 45);
+ this.cb_Printer.Name = "cb_Printer";
+ this.cb_Printer.Size = new System.Drawing.Size(195, 21);
+ this.cb_Printer.TabIndex = 9;
+ this.cb_Printer.SelectedIndexChanged += new System.EventHandler(this.cb_Printer_SelectedIndexChanged);
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(19, 134);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(58, 13);
+ this.label2.TabIndex = 5;
+ this.label2.Text = "Orientation";
+ //
+ // cb_Orientation
+ //
+ this.cb_Orientation.FormattingEnabled = true;
+ this.cb_Orientation.Items.AddRange(new object[] {
+ "Portrait",
+ "Landscape"});
+ this.cb_Orientation.Location = new System.Drawing.Point(18, 150);
+ this.cb_Orientation.Name = "cb_Orientation";
+ this.cb_Orientation.Size = new System.Drawing.Size(93, 21);
+ this.cb_Orientation.TabIndex = 4;
+ this.cb_Orientation.SelectedIndexChanged += new System.EventHandler(this.cb_Orientation_SelectedIndexChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(19, 81);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(58, 13);
+ this.label1.TabIndex = 3;
+ this.label1.Text = "Paper Size";
+ //
+ // cb_PaperSize
+ //
+ this.cb_PaperSize.FormattingEnabled = true;
+ this.cb_PaperSize.Location = new System.Drawing.Point(18, 97);
+ this.cb_PaperSize.Name = "cb_PaperSize";
+ this.cb_PaperSize.Size = new System.Drawing.Size(93, 21);
+ this.cb_PaperSize.TabIndex = 2;
+ this.cb_PaperSize.SelectedIndexChanged += new System.EventHandler(this.cb_PaperSize_SelectedIndexChanged);
+ //
+ // bt_Cancel
+ //
+ this.bt_Cancel.Location = new System.Drawing.Point(118, 450);
+ this.bt_Cancel.Name = "bt_Cancel";
+ this.bt_Cancel.Size = new System.Drawing.Size(69, 26);
+ this.bt_Cancel.TabIndex = 1;
+ this.bt_Cancel.Text = "Cancel";
+ this.bt_Cancel.UseVisualStyleBackColor = true;
+ this.bt_Cancel.Click += new System.EventHandler(this.bt_Cancel_Click);
+ //
+ // bt_print
+ //
+ this.bt_print.Location = new System.Drawing.Point(22, 450);
+ this.bt_print.Name = "bt_print";
+ this.bt_print.Size = new System.Drawing.Size(69, 26);
+ this.bt_print.TabIndex = 0;
+ this.bt_print.Text = "Print";
+ this.bt_print.UseVisualStyleBackColor = true;
+ this.bt_print.Click += new System.EventHandler(this.bt_print_Click);
+ //
+ // PrintPreviewForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(681, 501);
+ this.Controls.Add(this.splitContainer1);
+ this.MaximumSize = new System.Drawing.Size(697, 537);
+ this.MinimumSize = new System.Drawing.Size(697, 537);
+ this.Name = "PrintPreviewForm";
+ this.Text = "PrintPreviewForm";
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ this.splitContainer1.Panel2.PerformLayout();
+ this.splitContainer1.ResumeLayout(false);
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PrintPreviewControl printPreviewCtrl;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private System.Windows.Forms.Button bt_Cancel;
+ private System.Windows.Forms.Button bt_print;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.ComboBox cb_PaperSize;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.ComboBox cb_Orientation;
+ private System.Windows.Forms.RadioButton rb_Scale;
+ private System.Windows.Forms.RadioButton rb_BestFit;
+ private System.Windows.Forms.RadioButton rb_Unscaled;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.ComboBox cb_Printer;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.CheckBox cb_PrintBackground;
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.cs b/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.cs
new file mode 100644
index 00000000..bb6ece57
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.cs
@@ -0,0 +1,336 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Drawing.Printing;
+
+namespace GraphLib
+{
+ public partial class PrintPreviewForm : Form
+ {
+ private PrintDocument printDoc = new PrintDocument();
+ private PlotterGraphPaneEx gpane = null;
+ private String strDefaultPrinter = String.Empty;
+
+ private bool bBestScale = false;
+ private bool bPageScale = false;
+ private bool bUnscaled = false;
+ private bool bLandscape = false;
+ private int selPrinterIndex = -1;
+
+ public PrintPreviewForm()
+ {
+ InitializeComponent();
+
+ printPreviewCtrl.Zoom = 1;
+ rb_BestFit.Checked = true;
+ rb_Scale.Checked = false;
+ rb_Unscaled.Checked = false;
+ cb_Orientation.SelectedIndex = 0;
+ printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);
+ this.VisibleChanged += new EventHandler(OnVisibleChanged);
+ FormClosing += new FormClosingEventHandler(OnFormClosing);
+ }
+
+ void FillInInstalledPrinters()
+ {
+ strDefaultPrinter = printDoc.PrinterSettings.PrinterName;
+ cb_Printer.Items.Clear();
+ foreach (String strPrinter in PrinterSettings.InstalledPrinters)
+ {
+ cb_Printer.Items.Add(strPrinter);
+
+ if (strPrinter == strDefaultPrinter)
+ {
+ cb_Printer.SelectedIndex = cb_Printer.Items.IndexOf(strPrinter);
+ }
+ }
+ }
+
+ void OnVisibleChanged(object sender, EventArgs e)
+ {
+ if (this.Visible)
+ {
+ bLandscape = cb_Orientation.SelectedIndex == 1;
+
+ FillInInstalledPrinters();
+
+ FillInPaperSizes();
+
+ UpdateScaleRadioButtons();
+
+ InvalidatePrintPreview();
+ }
+ else
+ {
+
+ }
+ }
+
+ void OnFormClosing(object sender, FormClosingEventArgs e)
+ {
+ this.Hide();
+ e.Cancel = true;
+ }
+
+ void UpdateScaleRadioButtons()
+ {
+ bBestScale = rb_BestFit.Checked;
+ bPageScale = rb_Scale.Checked;
+ bUnscaled = rb_Unscaled.Checked;
+ }
+
+ double AutoZoomPreview()
+ {
+ float zoom = 1.0f;
+ float step = 0.05f;
+
+ float PaperWidth = printDoc.DefaultPageSettings.PaperSize.Width;
+ float PaperHeight = printDoc.DefaultPageSettings.PaperSize.Height;
+
+ if (bLandscape)
+ {
+ PaperHeight = printDoc.DefaultPageSettings.PaperSize.Width * zoom;
+ PaperWidth = printDoc.DefaultPageSettings.PaperSize.Height * zoom;
+ }
+
+ while (zoom > 0.1f)
+ {
+ double CurW = PaperWidth * zoom;
+ double CurH = PaperHeight * zoom;
+
+ if (splitContainer1.Panel1.Width < (CurW+10) || splitContainer1.Panel1.Height < (CurH+10))
+ {
+ zoom -= step;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return zoom;
+ }
+
+ void FillInPaperSizes()
+ {
+ cb_PaperSize.Items.Clear();
+
+ foreach (PaperSize s in printDoc.PrinterSettings.PaperSizes)
+ {
+ cb_PaperSize.Items.Add(s.PaperName.ToString());
+ }
+
+ if (cb_PaperSize.SelectedIndex == -1 || cb_PaperSize.SelectedIndex >= cb_PaperSize.Items.Count)
+ {
+ int idx = cb_PaperSize.Items.IndexOf(printDoc.DefaultPageSettings.PaperSize.PaperName);
+
+ if (idx >= 0 && idx < cb_PaperSize.Items.Count)
+ {
+ cb_PaperSize.SelectedIndex = idx;
+ }
+ else
+ {
+ cb_PaperSize.SelectedIndex = 0;
+ }
+ }
+ }
+
+ void InvalidatePrintPreview()
+ {
+ printDoc.DefaultPageSettings.Landscape = bLandscape;
+ printPreviewCtrl.Document = printDoc;
+ printPreviewCtrl.Document.DocumentName = "Preview";
+ printPreviewCtrl.Zoom = AutoZoomPreview();
+ printPreviewCtrl.InvalidatePreview();
+ }
+
+
+ public PlotterGraphPaneEx GraphPanel
+ {
+ set
+ {
+ gpane = value;
+ }
+ }
+
+ private void AutoScaleDocument(ref float w, ref float h, ref float x, ref float y)
+ {
+ float CurGraphWidth = gpane.Width;
+ float CurGraphHeight = gpane.Height;
+ float CurPaperWidth = printDoc.DefaultPageSettings.PaperSize.Width;
+ float CurPaperHeight = printDoc.DefaultPageSettings.PaperSize.Height;
+
+ if (bLandscape)
+ {
+ CurPaperWidth = printDoc.DefaultPageSettings.PaperSize.Height;
+ CurPaperHeight = printDoc.DefaultPageSettings.PaperSize.Width;
+ }
+
+ if (bUnscaled)
+ {
+ // do nothing
+ }
+
+ if (bPageScale) // scale to page
+ {
+ CurGraphWidth = CurPaperWidth;
+ CurGraphHeight = CurPaperHeight;
+ }
+
+ if (bBestScale) // scale to best fit
+ {
+ float zoom = 1.0f;
+ float step = 0.05f;
+
+ if (CurGraphWidth > (CurPaperWidth ) || CurGraphHeight > (CurPaperHeight ))
+ {
+ // scale down
+ while ((zoom * gpane.Width > CurPaperWidth || zoom * gpane.Height > CurPaperHeight) && zoom > step)
+ {
+ zoom -= step;
+ }
+ zoom -= step;
+
+ }
+ else if (CurGraphWidth < CurPaperWidth && CurGraphHeight < CurPaperHeight)
+ {
+ // scale up
+ while (((zoom+step) * gpane.Width < CurPaperWidth && (zoom+step) * gpane.Height < CurPaperHeight) && zoom > step)
+ {
+ zoom += step;
+ }
+
+ }
+ CurGraphWidth = zoom * gpane.Width;
+ CurGraphHeight = zoom * gpane.Height;
+ }
+
+ w = CurGraphWidth;
+ h = CurGraphHeight;
+
+ // center print
+ x = (CurPaperWidth - w) / 2.0f;
+ y = (CurPaperHeight - h) / 2.0f;
+ }
+
+ private void printDoc_PrintPage(object sender, PrintPageEventArgs e)
+ {
+ if (gpane != null)
+ {
+ float x=0, y=0, w=gpane.Width, h=gpane.Height;
+
+ AutoScaleDocument(ref w, ref h, ref x, ref y);
+ e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
+ //gpane.PaintControl(e.Graphics, w, h,x,y,cb_PrintBackground.Checked);
+ gpane.PaintControl(e.Graphics, w, h, x, y, false);
+ }
+ }
+
+ private void bt_print_Click(object sender, EventArgs e)
+ {
+ if (printDoc != null)
+ {
+ printDoc.Print();
+ this.Hide();
+ }
+ }
+
+ private void bt_Cancel_Click(object sender, EventArgs e)
+ {
+ this.Hide();
+ }
+
+ private void cb_PaperSize_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (cb_PaperSize.SelectedIndex >= 0 && cb_PaperSize.SelectedIndex < cb_PaperSize.Items.Count)
+ {
+
+ foreach (PaperSize s in printDoc.PrinterSettings.PaperSizes)
+ {
+ if (s.PaperName == (string)cb_PaperSize.Items[cb_PaperSize.SelectedIndex])
+ {
+ printDoc.DefaultPageSettings.PaperSize = s;
+ InvalidatePrintPreview();
+ }
+ }
+ }
+ }
+
+
+ private void rb_BestFit_CheckedChanged(object sender, EventArgs e)
+ {
+ if (rb_BestFit.Checked)
+ {
+ rb_Scale.Checked = !rb_BestFit.Checked;
+ rb_Unscaled.Checked = !rb_BestFit.Checked;
+ }
+
+ UpdateScaleRadioButtons();
+ InvalidatePrintPreview();
+ }
+
+ private void rb_Scale_CheckedChanged(object sender, EventArgs e)
+ {
+ if (rb_Scale.Checked)
+ {
+ rb_BestFit.Checked = !rb_Scale.Checked;
+ rb_Unscaled.Checked = !rb_Scale.Checked;
+ }
+
+ UpdateScaleRadioButtons();
+ InvalidatePrintPreview();
+ }
+
+ private void rb_Unscaled_CheckedChanged(object sender, EventArgs e)
+ {
+ if (rb_Unscaled.Checked)
+ {
+ rb_Scale.Checked = !rb_Unscaled.Checked;
+ rb_BestFit.Checked = !rb_Unscaled.Checked;
+ }
+
+ UpdateScaleRadioButtons();
+ InvalidatePrintPreview();
+ }
+
+ private void cb_Printer_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ selPrinterIndex = cb_Printer.SelectedIndex;
+
+ if (selPrinterIndex >= 0 && selPrinterIndex < cb_Printer.Items.Count)
+ {
+ printDoc.PrinterSettings.PrinterName = (string)cb_Printer.Items[selPrinterIndex];
+ this.Text = "Print Preview - " + printDoc.PrinterSettings.PrinterName;
+ }
+
+ FillInPaperSizes();
+
+ InvalidatePrintPreview();
+ }
+
+ private void cb_Orientation_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (cb_Orientation.SelectedIndex == 0)
+ {
+ bLandscape = false;
+ }
+ else
+ {
+ bLandscape = true;
+ }
+
+ InvalidatePrintPreview();
+ }
+
+ private void cb_PrintBackground_CheckedChanged(object sender, EventArgs e)
+ {
+ InvalidatePrintPreview();
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.resx b/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.resx
new file mode 100644
index 00000000..19dc0dd8
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/PrintPreviewForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/Properties/AssemblyInfo.cs b/TBF_V2/Sources/TBF/GraphLib/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..42e2343e
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("GraphLibrary")]
+[assembly: AssemblyDescription("Library for easy and simple graph drawing")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("GraphLibrary")]
+[assembly: AssemblyCopyright("Copyright © 2008-2014 ZIMMERMANN STEPHAN")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b23e30ac-c4b8-4863-90d0-cf0ad837c050")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.1")]
+[assembly: AssemblyFileVersion("1.0.0.1")]
diff --git a/TBF_V2/Sources/TBF/GraphLib/Properties/Resources.Designer.cs b/TBF_V2/Sources/TBF/GraphLib/Properties/Resources.Designer.cs
new file mode 100644
index 00000000..00cd8089
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.18408
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace ClassLibrary1.Properties {
+ using System;
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
+ // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClassLibrary1.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/GraphLib/Properties/Resources.resx b/TBF_V2/Sources/TBF/GraphLib/Properties/Resources.resx
new file mode 100644
index 00000000..7080a7d1
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/Properties/Resources.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/GraphLib/Utils.cs b/TBF_V2/Sources/TBF/GraphLib/Utils.cs
new file mode 100644
index 00000000..d260a98d
--- /dev/null
+++ b/TBF_V2/Sources/TBF/GraphLib/Utils.cs
@@ -0,0 +1,45 @@
+using System;
+
+namespace GraphLib
+{
+ public class Utilities
+ {
+ ///
+ /// returns the most significant decimal digit
+ /// 250 -> 100
+ /// 350 -> 100
+ /// 12 -> 10
+ /// 5 -> 1
+ /// 0.5 .> 0.1
+ /// .....
+ ///
+ ///
+ ///
+ static public float MostSignificantDigit(float Value)
+ {
+ float n = 1;
+
+ float val_abs = Math.Abs(Value);
+ float sig = 1.0f * Math.Sign(Value);
+
+ if (val_abs > 1)
+ {
+ while (n < val_abs)
+ {
+ n *= 10.0f;
+ }
+
+ return (float)((int)(sig * n / 10));
+ }
+ else // n <= 1
+ {
+ while (n > val_abs)
+ {
+ n /= 10.0f;
+ }
+
+ return sig * n;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/BatteryInfo.cs b/TBF_V2/Sources/TBF/MonitoringDB/BatteryInfo.cs
new file mode 100644
index 00000000..f2bdff51
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/BatteryInfo.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using log4net;
+using MonitoringDB.Entities;
+
+namespace MonitoringDB
+{
+ public class BatteryInfo
+ {
+ static readonly ILog log = LogManager.GetLogger(typeof(BatteryInfo));
+
+ /// Constants
+ public const string VitzrocellBatteryPartNr = "68118221";
+ public const string TadiranBatteryPartNr = "68117469";
+
+ public string PcbNumber; /// Unique PCB number of the water meter
+ public string BattSapPartNr; /// Battery SAP part number
+ public int BattBatchNr; /// Batch number (purchase order)
+ public string BattMMYY; /// Production date
+ public string BattSupplier; /// Supplier
+ public string PrintedBatteryInfo; /// 'T', 'Vi' or '-'
+ public DateTime TimeStamp; /// Record creation time
+
+ bool complete { get { return (PcbNumber != null) && (BattSapPartNr != null) && (BattBatchNr != 0) && (BattMMYY != null) && (BattSupplier != null); } }
+
+
+ public BatteryInfo()
+ {
+ TimeStamp = DateTime.Now;
+ PrintedBatteryInfo = "-";
+ }
+
+
+ ///
+ /// Search MySQL DB and get battery info, add it into the record.
+ ///
+ /// true when successful
+ public static BatteryInfo GetBatteryInfo(string pcbNumber, IList records)
+ {
+ if (string.IsNullOrEmpty(pcbNumber))
+ {
+ log.ErrorFormat("Invalid PcbBr, no battery info.");
+ return null;
+ }
+
+ BatteryInfo info = new BatteryInfo() { PcbNumber = pcbNumber };
+
+ try
+ {
+ bool error = false;
+
+ foreach (var rec in records)
+ {
+ if (rec.Part.CodeLocation == CodeLocation.OnPallet)
+ {
+ if (rec.Part.Name == VitzrocellBatteryPartNr)
+ {
+ if (info.BattSapPartNr != null) { error = true; break; }
+ info.BattSapPartNr = VitzrocellBatteryPartNr;
+ int battBatchNr;
+ info.BattBatchNr = int.TryParse(rec.Code, out battBatchNr) ? battBatchNr : 1;
+ info.BattSupplier = "VITZROCELL";
+ }
+ else if (rec.Part.Name == TadiranBatteryPartNr)
+ {
+ if (info.BattSapPartNr != null) { error = true; break; }
+ info.BattSapPartNr = TadiranBatteryPartNr;
+ int battBatchNr;
+ info.BattBatchNr = int.TryParse(rec.Code, out battBatchNr) ? battBatchNr : 1;
+ info.BattSupplier = "TADIRAN";
+ }
+ }
+
+ if (rec.Part.CodeType == CodeType.DateMMYY)
+ {
+ if (info.BattMMYY != null) { error = true; break; }
+ info.BattMMYY = rec.Code;
+ }
+ }
+
+ if (error || !info.complete)
+ {
+ log.ErrorFormat("Battery info. for PcbNr={0} wasn't found in MySQL database", info.PcbNumber);
+ return null;
+ }
+
+ ///
+ /// Set battery information printed on labels
+ ///
+ if (info.BattSupplier == "VITZROCELL")
+ {
+ info.PrintedBatteryInfo = "Vi";
+ }
+ else if (info.BattSupplier == "TADIRAN")
+ {
+ info.PrintedBatteryInfo = "T";
+ }
+
+ return info;
+ }
+ catch (Exception exc)
+ {
+ log.ErrorFormat("Battery info. for PcbNr={0} wasn't found in MySQL database: {1}",
+ info.PcbNumber, exc.Message);
+ return null;
+ }
+ }
+
+
+ public override string ToString()
+ {
+ return string.Format("PcbNr={0}, Battery={1}/{2}/{3}, Time={4}", PcbNumber, BattBatchNr, BattMMYY, BattSupplier, TimeStamp);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Entities/Option1.cs b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Option1.cs
new file mode 100644
index 00000000..fc0f91a2
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Option1.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Entities
+{
+ public class Option1 : Interfaces.IOption
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OraDBType { get; set; }
+ public virtual string Description { get; set; }
+ public virtual CodeType CodeType { get; set; }
+ public virtual CodeForm CodeForm { get; set; }
+ public virtual CodeLocation CodeLocation { get; set; }
+ public virtual LifetimeManagement LifetimeManagement { get; set; }
+ public virtual bool Enabled { get; set; }
+
+ public Option1()
+ {
+ Name = string.Empty;
+ Description = string.Empty;
+ }
+
+ ///
+ /// Create a copy of a part (1) belongig to another process, (2) not assigned to any workstep yet.
+ ///
+ /// Process owning the cloned part
+ /// Cloned part
+ public virtual Part GetPart(Process owningProcess)
+ {
+ Part rslt = new Part();
+
+ rslt.Name = Name;
+ rslt.OraDBType = OraDBType;
+ rslt.Description = Description;
+ rslt.CodeType = CodeType;
+ rslt.CodeForm = CodeForm;
+ rslt.CodeLocation = CodeLocation;
+ rslt.LifetimeManagement = LifetimeManagement;
+
+ rslt.StepNumber = 0;
+ rslt.Process = owningProcess;
+ rslt.Workstep = null;
+
+ return rslt;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}. {1} ({2})", ItemNr, Name, Description);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Entities/Option2.cs b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Option2.cs
new file mode 100644
index 00000000..1cddd27b
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Option2.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Entities
+{
+ public class Option2 : Interfaces.IOption
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string OraDBType { get; set; }
+ public virtual string Description { get; set; }
+ public virtual CodeType CodeType { get; set; }
+ public virtual CodeForm CodeForm { get; set; }
+ public virtual CodeLocation CodeLocation { get; set; }
+ public virtual LifetimeManagement LifetimeManagement { get; set; }
+ public virtual bool Enabled { get; set; }
+
+ public Option2()
+ {
+ Name = string.Empty;
+ Description = string.Empty;
+ }
+
+ ///
+ /// Create a copy of a part (1) belongig to another process, (2) not assigned to any workstep yet.
+ ///
+ /// Process owning the cloned part
+ /// Cloned part
+ public virtual Part GetPart(Process owningProcess)
+ {
+ Part rslt = new Part();
+
+ rslt.Name = Name;
+ rslt.OraDBType = OraDBType;
+ rslt.Description = Description;
+ rslt.CodeType = CodeType;
+ rslt.CodeForm = CodeForm;
+ rslt.CodeLocation = CodeLocation;
+ rslt.LifetimeManagement = LifetimeManagement;
+
+ rslt.StepNumber = 0;
+ rslt.Process = owningProcess;
+ rslt.Workstep = null;
+
+ return rslt;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}. {1} ({2})", ItemNr, Name, Description);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Entities/Part.cs b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Part.cs
new file mode 100644
index 00000000..6368f4bd
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Part.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Entities
+{
+ public class Part
+ {
+ public virtual int Id { get; protected set; }
+ public virtual string Name { get; set; }
+ public virtual string OraDBType { get; set; }
+ public virtual string Description { get; set; }
+ public virtual CodeType CodeType { get; set; }
+ public virtual CodeForm CodeForm { get; set; }
+ public virtual CodeLocation CodeLocation { get; set; }
+ public virtual LifetimeManagement LifetimeManagement { get; set; }
+ public virtual int StepNumber { get; set; }
+
+ public virtual Process Process { get; set; }
+ public virtual Workstep Workstep { get; set; }
+
+
+ public Part()
+ {
+ Name = string.Empty;
+ Description = string.Empty;
+ }
+
+ ///
+ /// Constructor used when the part is added to a process
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Part(string name, Process process, CodeType codeType, CodeForm codeForm, CodeLocation codeLocation)
+ {
+ Name = name;
+ OraDBType = string.Empty;
+ Description = string.Empty;
+ CodeType = codeType;
+ CodeForm = codeForm;
+ CodeLocation = codeLocation;
+ StepNumber = 0;
+
+ Process = process;
+ Workstep = null;
+ }
+
+ ///
+ /// Create a copy of a part (1) belongig to another process, (2) not assigned to any workstep yet.
+ ///
+ /// Process owning the cloned part
+ /// Cloned part
+ public virtual Part Clone(Process owningProcess)
+ {
+ Part rslt = new Part();
+
+ rslt.Name = Name;
+ rslt.OraDBType = OraDBType;
+ rslt.Description = Description;
+ rslt.CodeType = CodeType;
+ rslt.CodeForm = CodeForm;
+ rslt.CodeLocation = CodeLocation;
+ rslt.LifetimeManagement = LifetimeManagement;
+
+ rslt.StepNumber = 0;
+ rslt.Process = owningProcess;
+ rslt.Workstep = null;
+
+ return rslt;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0} step={1} ({2})", Name, StepNumber, Description);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Entities/Process.cs b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Process.cs
new file mode 100644
index 00000000..121e82cb
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Process.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Entities
+{
+ public class Process
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int ItemNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string Description { get; set; }
+ public virtual ReleaseStatus ReleaseStatus { get; set; }
+ public virtual DateTime TimeStamp { get; set; }
+ public virtual string UserName { get; set; }
+
+ public virtual IList Parts { get; set; }
+ public virtual IList Worksteps { get; set; }
+
+ ///
+ /// Default (private) constructor inicializing lists
+ ///
+ protected Process()
+ {
+ Parts = new List();
+ Worksteps = new List();
+ }
+
+ ///
+ /// Constructor used when this process is created
+ ///
+ ///
+ public Process(string name)
+ : this()
+ {
+ Name = name;
+ Description = string.Empty;
+ ReleaseStatus = ReleaseStatus.In_preparation;
+ TimeStamp = DateTime.Now;
+ UserName = "admin";
+ }
+
+ ///
+ /// Create a copy of a process with a new name
+ ///
+ ///
+ ///
+ public virtual Process Clone(string name)
+ {
+ Process rslt = new Process(name);
+ rslt.Description = Description;
+
+ foreach (var part in Parts) rslt.Parts.Add(part.Clone(rslt));
+ foreach (var workstep in Worksteps) rslt.Worksteps.Add(workstep.Clone(rslt));
+
+ return rslt;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0} '{1}' ({2}) {3} {4}",
+ ItemNr,
+ Name,
+ TimeStamp.Date.ToShortDateString(),
+ (Description == null) ? string.Empty : Description,
+ ReleaseStatus);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Entities/Record.cs b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Record.cs
new file mode 100644
index 00000000..2880e28e
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Record.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Entities
+{
+ public class Record
+ {
+ public virtual int Id { get; protected set; }
+ public virtual string Code { get; set; }
+ public virtual DateTime TimeStamp { get; set; }
+
+ public virtual Part Part { get; set; }
+ public virtual ReferenceRecord ReferenceRecord { get; set; }
+
+
+ protected Record()
+ {
+ }
+
+ ///
+ /// Constructor used when a part barcode is scanned
+ ///
+ /// Part
+ /// Reference record
+ /// Scanned barcode
+ public Record(Part part, ReferenceRecord referenceRecord, string code)
+ {
+ Part = part;
+ ReferenceRecord = referenceRecord;
+ Code = code;
+ TimeStamp = DateTime.Now;
+ }
+
+ ///
+ /// Create a copy of a process with a new name
+ ///
+ ///
+ ///
+ public virtual Record Clone(Process newProcess, ReferenceRecord newRR)
+ {
+ Part newPart = null;
+ foreach (var pt in newProcess.Parts)
+ {
+ if (Part.Name == pt.Name)
+ {
+ newPart = pt;
+ break;
+ }
+ }
+ Record rslt = new Record(newPart, newRR, Code);
+ rslt.TimeStamp = TimeStamp;
+
+ return rslt;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("code={0} part={1} description='{2}'", Code, Part.Name, Part.Description);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Entities/ReferenceRecord.cs b/TBF_V2/Sources/TBF/MonitoringDB/Entities/ReferenceRecord.cs
new file mode 100644
index 00000000..00b65eb5
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Entities/ReferenceRecord.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Entities
+{
+ public class ReferenceRecord
+ {
+ public virtual int Id { get; protected set; }
+ public virtual string Code { get; set; }
+ public virtual DateTime TimeStamp { get; set; }
+ public virtual string UserName { get; set; }
+ public virtual string Workplace { get; set; }
+ public virtual int Result { get; set; } /// 0 = No error (OK), >0 = Error code
+
+ public virtual Process Process { get; set; }
+ public virtual Workstep Workstep { get; set; }
+ public virtual IList Records { get; set; }
+
+
+ ///
+ /// Default (private) constructor inicializing lists
+ ///
+ protected ReferenceRecord()
+ {
+ Records = new List();
+ }
+
+ ///
+ /// Constructor used when reference barcode is scanned
+ ///
+ /// Process
+ /// Workstep
+ /// Scanned barcode
+ public ReferenceRecord(Process process, Workstep workstep, string code,
+ string userName, string workplace, int result)
+ {
+ Process = process;
+ Workstep = workstep;
+ Code = code;
+ TimeStamp = DateTime.Now;
+ UserName = userName;
+ Workplace = workplace;
+ Result = result;
+ }
+
+ ///
+ /// Create a copy of a process with a new name
+ ///
+ ///
+ ///
+ public virtual ReferenceRecord Clone(Process newProcess)
+ {
+ Workstep newWorkstep = null;
+ foreach (var ws in newProcess.Worksteps)
+ {
+ if (Workstep.Name == ws.Name)
+ {
+ newWorkstep = ws;
+ break;
+ }
+ }
+
+ ReferenceRecord rslt = new ReferenceRecord(newProcess, newWorkstep,
+ Code, UserName, Workplace, Result);
+ rslt.TimeStamp = TimeStamp;
+
+ rslt.Records = new List();
+ foreach (var record in Records)
+ {
+ rslt.Records.Add(record.Clone(newProcess, rslt));
+ }
+
+ return rslt;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("code={0} part={1} description='{2}' step='{3}' workplace='{4}' user={5} time={6:dd.MM.yyyy HH:mm:ss}",
+ (Code != null) ? Code : "",
+ Workstep.ReferencePart.Name,
+ Workstep.ReferencePart.Description,
+ Workstep.Name,
+ Workplace,
+ UserName,
+ TimeStamp);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Entities/Workstep.cs b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Workstep.cs
new file mode 100644
index 00000000..fb883253
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Entities/Workstep.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Entities
+{
+ public class Workstep
+ {
+ public virtual int Id { get; protected set; }
+ public virtual int WorkstepNr { get; set; }
+ public virtual string Name { get; set; }
+ public virtual string Description { get; set; }
+ public virtual int CheckPartNr { get; set; }
+ public virtual bool AllowRepairs { get; set; }
+
+ public virtual Process Process { get; set; }
+ public virtual Part ReferencePart { get; set; }
+ public virtual IList Parts { get; set; }
+
+
+ ///
+ /// Default (private) constructor inicializing a list
+ ///
+ protected Workstep()
+ {
+ Parts = new List();
+ }
+
+ ///
+ /// Constructor used when this workstep is added to a process
+ ///
+ /// Workstep name
+ /// Process to be referenced
+ public Workstep(int workstepNr, string name, Process process)
+ : this()
+ {
+ WorkstepNr = workstepNr;
+ Name = name;
+ Description = string.Empty;
+ CheckPartNr = 0;
+ AllowRepairs = false;
+ Process = process;
+ ReferencePart = null;
+ }
+
+ public virtual Workstep Clone(Process owningProcess)
+ {
+ Workstep rslt = new Workstep(WorkstepNr, Name, owningProcess);
+ rslt.Description = Description;
+ rslt.CheckPartNr = CheckPartNr;
+ rslt.AllowRepairs = AllowRepairs;
+
+ if (ReferencePart != null)
+ {
+ foreach (var p in owningProcess.Parts)
+ {
+ if (p.Name == ReferencePart.Name) rslt.ReferencePart = p;
+ }
+ }
+
+ foreach (var srcP in Parts)
+ {
+ foreach (var p in owningProcess.Parts)
+ {
+ if (p.Name == srcP.Name)
+ {
+ rslt.Parts.Add(p);
+ p.StepNumber = srcP.StepNumber;
+ p.Workstep = rslt;
+ }
+ }
+ }
+
+ return rslt;
+ }
+
+ public override string ToString()
+ {
+ //return string.Format("{0} {1} ({2}) Ref: {3}", WorkstepNr, Name, Description, (ReferencePart != null) ? ReferencePart.Name : "none");
+ return string.Format("{0}: {1}", WorkstepNr, Name);
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Enums.cs b/TBF_V2/Sources/TBF/MonitoringDB/Enums.cs
new file mode 100644
index 00000000..3a4092ec
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Enums.cs
@@ -0,0 +1,97 @@
+namespace MonitoringDB
+{
+ public enum CodeType
+ {
+ UniqueNr,
+ FlowtubeNr, /// prvé 3 znaky sa zhodujú s poslednými 3 znakmi názvu
+ FlowtubeNrLU, /// začiatok kódu sa zhoduje s názvom
+ BatchNr,
+ BatchNrContainingPartName,
+ DateMMYY,
+ QualityCheck,
+ Count
+ }
+
+ public enum CodeForm
+ {
+ Barcode,
+ QRCode,
+ Keyboard,
+ OkNok,
+ Count
+ }
+
+ public enum CodeLocation
+ {
+ OnPart,
+ OnPallet,
+ Count
+ }
+
+ public enum LifetimeManagement
+ {
+ None,
+ OneYear,
+ Count,
+ }
+
+ public enum ReleaseStatus
+ {
+ In_preparation,
+ Released,
+ ReleasedActive,
+ Deactivated,
+ Count,
+ }
+
+ public enum Mode
+ {
+ Debug, // Debug mode - no Oracle database used
+ Test, // Test database used
+ Production, // Production database used
+ Count,
+ }
+
+ public enum LoginLevel
+ {
+ None,
+ TeamLeader,
+ Administrator,
+ MH,
+ Count,
+ }
+
+ public enum ItemSpecID
+ {
+ RefRecordID = 0,
+
+ TimeStamp,
+ Workstep,
+ Workplace,
+ UserName,
+ Barcode,
+ PartBarcode,
+
+ TimeStamp2,
+ Workstep2,
+ Workplace2,
+ UserName2,
+ Barcode2,
+ PartBarcode2,
+
+ SerialNr,
+ PurchaseOrder,
+ TestResult,
+ MaxPruefindex,
+
+ Process,
+ }
+
+ public enum ItemSpecCaps
+ {
+ None = 0,
+ ReferenceRecord = 1,
+ AssociatedRecord = 2,
+ OracleQuery = 4,
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/FluentNH.cs b/TBF_V2/Sources/TBF/MonitoringDB/FluentNH.cs
new file mode 100644
index 00000000..bc798be6
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/FluentNH.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Collections.Generic;
+using FluentNHibernate.Cfg;
+using FluentNHibernate.Cfg.Db;
+using NHibernate;
+using NHibernate.Cfg;
+using NHibernate.Tool.hbm2ddl;
+
+namespace MonitoringDB
+{
+ public static class FluentNH
+ {
+ ///
+ /// Current session factory for the last used connection string or null
+ ///
+ public static ISessionFactory SessionFactory;
+
+
+ /// Connection string for all sessions
+ static string connectionString;
+ ///
+ public static string ConnectionString
+ {
+ get { return connectionString; }
+ set
+ {
+ if (value != connectionString)
+ {
+ connectionString = value;
+ SessionFactory = null; /// Clear SessionFactory on connection string change
+ }
+ }
+ }
+
+
+ ///
+ /// NHibernate session factory (to create the database session 'SessionFactory')
+ ///
+ /// A database session
+ static ISessionFactory CreateSessionFactory()
+ {
+ return CreateSessionFactory(false);
+ }
+
+ ///
+ /// NHibernate session factory (to create the database session 'SessionFactory')
+ ///
+ /// A database session
+ public static ISessionFactory CreateSessionFactory(bool createDB)
+ {
+ FluentConfiguration cfg = Fluently
+ .Configure()
+ .Database(MySQLConfiguration.Standard.ConnectionString(connectionString))
+ .Mappings(m => m.FluentMappings.AddFromAssemblyOf());
+
+ if (createDB)
+ {
+ return cfg.ExposeConfiguration(BuildSchemaCreate).BuildSessionFactory();
+ }
+ else
+ {
+ return cfg.ExposeConfiguration(BuildSchema).BuildSessionFactory();
+ }
+ }
+
+ public delegate void BuildSchemaDlgt(Configuration config);
+
+ public static void BuildSchema(Configuration config)
+ {
+ /// This NHibernate tool takes a configuration (with mapping info in)
+ /// and exports a database schema from it
+ new SchemaExport(config).SetOutputFile("db_schema");
+ }
+
+ static void BuildSchemaCreate(Configuration config)
+ {
+ /// This NHibernate tool takes a configuration (with mapping info in)
+ /// and exports a database schema from it
+ new SchemaExport(config).Create(true, true);
+ }
+
+ /// Create a NHibernate session for the given database
+ public static ISession CreateSession(string connectionString)
+ {
+ ConnectionString = connectionString; /// Clears session factory on connction string change
+
+ if (SessionFactory == null)
+ SessionFactory = CreateSessionFactory();
+
+ return SessionFactory.OpenSession();
+ }
+
+
+ ///
+ /// Create an empty database.
+ /// Database contains only the user 'admin' and the control board component 'CB'.
+ ///
+ /// DBType.SQLite or DBType.MySql
+ /// Connection string
+ /// true=success, false=error
+ public static bool CreateEmptyDB(string connectionString)
+ {
+ ConnectionString = connectionString;
+
+ ISessionFactory sessionFactory = CreateSessionFactory(true);
+ if (sessionFactory == null) return false;
+
+ /// Populate the database
+ using (var session = sessionFactory.OpenSession())
+ {
+ //using (var transaction = session.BeginTransaction())
+ //{
+ // var part1 = new MonitoringDB.Entities.Part("flow tube", CodeType.UniqueNr, CodeForm.QRCode, 0);
+ // session.SaveOrUpdate(part1);
+ // transaction.Commit();
+ //}
+ }
+
+ return true;
+ }
+
+
+ public static IList FindWMParts(ISession session, string pcbNumber)
+ {
+ IList foundParts = new List(); /// initially empty
+
+ if (string.IsNullOrEmpty(pcbNumber)) return foundParts; /// return an empty list
+
+ try
+ {
+ /// Get all already existing reference records with Code == pcbNumber, referenceRecords[0] will be the most recent one
+ var referenceRecords = session.QueryOver()
+ .Where(rr => (rr.Code == pcbNumber))
+ .OrderBy(rr => rr.TimeStamp).Desc
+ .List();
+
+ if (referenceRecords.Count == 0) return foundParts; /// Returns an empty list if no such ref. record found
+
+ foundParts.Add(new WMPart(referenceRecords[0]));
+ Entities.Process process = referenceRecords[0].Process;
+ ///
+ foreach (var refR in referenceRecords)
+ {
+ if (process != refR.Process)
+ {
+ continue; /// skip records obtained by another process
+ }
+
+ IList relatedRecords = session
+ .QueryOver()
+ .Where(x => (x.ReferenceRecord == refR))
+ .List();
+
+
+ foreach (var relR in relatedRecords)
+ {
+ foundParts.Add(new WMPart(relR));
+ foreach (var ws in process.Worksteps)
+ {
+ if (ws.ReferencePart == relR.Part)
+ {
+ FindWMPartsRecursively(process, ws.ReferencePart, relR.Code, session, ref foundParts);
+ }
+ }
+ }
+ }
+ }
+ catch
+ {
+ }
+
+ return foundParts;
+ }
+
+
+ static void FindWMPartsRecursively(Entities.Process process, Entities.Part refPart, string code, ISession session, ref IList foundParts)
+ {
+ IList referenceRecords = session
+ .QueryOver()
+ .Where(x => (x.Workstep.ReferencePart == refPart))
+ .Where(x => (x.Code == code))
+ .OrderBy(x => x.TimeStamp).Desc
+ .List();
+
+ if (referenceRecords.Count == 0) return;
+
+ foreach (var refR in referenceRecords)
+ {
+ IList relatedRecords = session
+ .QueryOver()
+ .Where(x => (x.ReferenceRecord == refR))
+ .List();
+
+
+ foreach (var relR in relatedRecords)
+ {
+ foundParts.Add(new WMPart(relR));
+
+ foreach (var ws in process.Worksteps)
+ {
+ if (ws.ReferencePart == relR.Part)
+ {
+ FindWMPartsRecursively(process, ws.ReferencePart, relR.Code, session, ref foundParts);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ListViewEx.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ListViewEx.cs
new file mode 100644
index 00000000..f2417628
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ListViewEx.cs
@@ -0,0 +1,456 @@
+///
+/// Copyright (c) 2016 Sensus Metering Systems
+///
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+
+namespace MonitoringDB.Forms
+{
+ ///
+ /// Event Handler for SubItem events
+ ///
+ public delegate void SubItemEventHandler(object sender, SubItemEventArgs e);
+ ///
+ /// Event Handler for SubItemEndEditing events
+ ///
+ public delegate void SubItemEndEditingEventHandler(object sender, SubItemEndEditingEventArgs e);
+
+
+ ///
+ /// Inherited ListView to allow in-place editing of subitems
+ ///
+ public class ListViewEx : System.Windows.Forms.ListView
+ {
+ #region Interop structs, imports and constants
+ ///
+ /// MessageHeader for WM_NOTIFY
+ ///
+ private struct NMHDR
+ {
+#pragma warning disable
+ public IntPtr hwndFrom;
+ public Int32 idFrom;
+ public Int32 code;
+#pragma warning restore
+ }
+
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wPar, IntPtr lPar);
+ [DllImport("user32.dll", CharSet=CharSet.Ansi)]
+ private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int len, ref int [] order);
+
+ // ListView messages
+ private const int LVM_FIRST = 0x1000;
+ private const int LVM_GETCOLUMNORDERARRAY = (LVM_FIRST + 59);
+
+ // Windows Messages that will abort editing
+ private const int WM_HSCROLL = 0x114;
+ private const int WM_VSCROLL = 0x115;
+ private const int WM_SIZE = 0x05;
+ private const int WM_NOTIFY = 0x4E;
+
+ private const int HDN_FIRST = -300;
+ private const int HDN_BEGINDRAG = (HDN_FIRST-10);
+ private const int HDN_ITEMCHANGINGA = (HDN_FIRST-0);
+ private const int HDN_ITEMCHANGINGW = (HDN_FIRST-20);
+ #endregion
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.Container components = null;
+
+ public event SubItemEventHandler SubItemClicked;
+ public event SubItemEventHandler SubItemBeginEditing;
+ public event SubItemEndEditingEventHandler SubItemEndEditing;
+
+ public ListViewEx()
+ {
+ // This call is required by the Windows.Forms Form Designer.
+ InitializeComponent();
+
+ base.FullRowSelect = true;
+ base.View = View.Details;
+ base.AllowColumnReorder = true;
+ }
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ protected override void Dispose( bool disposing )
+ {
+ if( disposing )
+ {
+ if( components != null )
+ components.Dispose();
+ }
+ base.Dispose( disposing );
+ }
+
+ #region Component Designer generated code
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+ #endregion
+
+ private bool _doubleClickActivation = false;
+ ///
+ /// Is a double click required to start editing a cell?
+ ///
+ public bool DoubleClickActivation
+ {
+ get { return _doubleClickActivation; }
+ set { _doubleClickActivation = value; }
+ }
+
+
+ ///
+ /// Retrieve the order in which columns appear
+ ///
+ /// Current display order of column indices
+ public int[] GetColumnOrder()
+ {
+ IntPtr lPar = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)) * Columns.Count);
+
+ IntPtr res = SendMessage(Handle, LVM_GETCOLUMNORDERARRAY, new IntPtr(Columns.Count), lPar);
+ if (res.ToInt32() == 0) // Something went wrong
+ {
+ Marshal.FreeHGlobal(lPar);
+ return null;
+ }
+
+ int [] order = new int[Columns.Count];
+ Marshal.Copy(lPar, order, 0, Columns.Count);
+
+ Marshal.FreeHGlobal(lPar);
+
+ return order;
+ }
+
+
+ ///
+ /// Find ListViewItem and SubItem Index at position (x,y)
+ ///
+ /// relative to ListView
+ /// relative to ListView
+ /// Item at position (x,y)
+ /// SubItem index
+ public int GetSubItemAt(int x, int y, out ListViewItem item)
+ {
+ item = this.GetItemAt(x, y);
+
+ if (item != null)
+ {
+ int[] order = GetColumnOrder();
+ Rectangle lviBounds;
+ int subItemX;
+
+ lviBounds = item.GetBounds(ItemBoundsPortion.Entire);
+ subItemX = lviBounds.Left;
+ for (int i=0; i
+ /// Get bounds for a SubItem
+ ///
+ /// Target ListViewItem
+ /// Target SubItem index
+ /// Bounds of SubItem (relative to ListView)
+ public Rectangle GetSubItemBounds(ListViewItem Item, int SubItem)
+ {
+ int[] order = GetColumnOrder();
+
+ Rectangle subItemRect = Rectangle.Empty;
+ if (SubItem >= order.Length)
+ throw new IndexOutOfRangeException("SubItem "+SubItem+" out of range");
+
+ if (Item == null)
+ throw new ArgumentNullException("Item");
+
+ Rectangle lviBounds = Item.GetBounds(ItemBoundsPortion.Entire);
+ int subItemX = lviBounds.Left;
+
+ ColumnHeader col;
+ int i;
+ for (i=0; i
+ /// Fire SubItemClicked
+ ///
+ ///Point of click/doubleclick
+ private void EditSubitemAt(Point p)
+ {
+ ListViewItem item;
+ int idx = GetSubItemAt(p.X, p.Y, out item);
+ if (idx >= 0)
+ {
+ OnSubItemClicked(new SubItemEventArgs(item, idx));
+ }
+ }
+
+ #endregion
+
+ #region In-place editing functions
+ // The control performing the actual editing
+ private Control _editingControl;
+ // The LVI being edited
+ private ListViewItem _editItem;
+ // The SubItem being edited
+ private int _editSubItem;
+
+ protected void OnSubItemBeginEditing(SubItemEventArgs e)
+ {
+ if (SubItemBeginEditing != null) SubItemBeginEditing(this, e);
+ }
+
+ protected void OnSubItemEndEditing(SubItemEndEditingEventArgs e)
+ {
+ if (SubItemEndEditing != null) SubItemEndEditing(this, e);
+ }
+
+ protected void OnSubItemClicked(SubItemEventArgs e)
+ {
+ if (SubItemClicked != null) SubItemClicked(this, e);
+ }
+
+
+ ///
+ /// Begin in-place editing of given cell
+ ///
+ /// Control used as cell editor
+ /// ListViewItem to edit
+ /// SubItem index to edit
+ public void StartEditing(Control c, ListViewItem Item, int SubItem)
+ {
+ OnSubItemBeginEditing(new SubItemEventArgs(Item, SubItem));
+
+ Rectangle rcSubItem = GetSubItemBounds(Item, SubItem);
+
+ if (rcSubItem.X < 0)
+ {
+ // Left edge of SubItem not visible - adjust rectangle position and width
+ rcSubItem.Width += rcSubItem.X;
+ rcSubItem.X=0;
+ }
+ if (rcSubItem.X+rcSubItem.Width > this.Width)
+ {
+ // Right edge of SubItem not visible - adjust rectangle width
+ rcSubItem.Width = this.Width-rcSubItem.Left;
+ }
+
+ // Subitem bounds are relative to the location of the ListView!
+ rcSubItem.Offset(Left, Top);
+
+ // In case the editing control and the listview are on different parents,
+ // account for different origins
+ Point origin = new Point(0,0);
+ Point lvOrigin = this.Parent.PointToScreen(origin);
+ Point ctlOrigin = c.Parent.PointToScreen(origin);
+
+ rcSubItem.Offset(lvOrigin.X-ctlOrigin.X, lvOrigin.Y-ctlOrigin.Y);
+
+ // Position and show editor
+ c.Bounds = rcSubItem;
+ c.Text = Item.SubItems[SubItem].Text;
+ c.Visible = true;
+ c.BringToFront();
+ c.Focus();
+
+ _editingControl = c;
+ _editingControl.Leave += new EventHandler(_editControl_Leave);
+ _editingControl.KeyPress += new KeyPressEventHandler(_editControl_KeyPress);
+
+ _editItem = Item;
+ _editSubItem = SubItem;
+ }
+
+
+ private void _editControl_Leave(object sender, EventArgs e)
+ {
+ // cell editor losing focus
+ EndEditing(true);
+ }
+
+ private void _editControl_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
+ {
+ switch (e.KeyChar)
+ {
+ case (char)(int)Keys.Escape:
+ {
+ EndEditing(false);
+ break;
+ }
+
+ case (char)(int)Keys.Enter:
+ {
+ EndEditing(true);
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Accept or discard current value of cell editor control
+ ///
+ /// Use the _editingControl's Text as new SubItem text or discard changes?
+ public void EndEditing(bool AcceptChanges)
+ {
+ if (_editingControl == null)
+ return;
+
+ SubItemEndEditingEventArgs e = new SubItemEndEditingEventArgs(
+ _editItem, // The item being edited
+ _editSubItem, // The subitem index being edited
+ AcceptChanges ?
+ _editingControl.Text : // Use editControl text if changes are accepted
+ _editItem.SubItems[_editSubItem].Text, // or the original subitem's text, if changes are discarded
+ !AcceptChanges // Cancel?
+ );
+
+ OnSubItemEndEditing(e);
+
+ _editItem.SubItems[_editSubItem].Text = e.DisplayText;
+
+ _editingControl.Leave -= new EventHandler(_editControl_Leave);
+ _editingControl.KeyPress -= new KeyPressEventHandler(_editControl_KeyPress);
+
+ _editingControl.Visible = false;
+
+ _editingControl = null;
+ _editItem = null;
+ _editSubItem = -1;
+ }
+ #endregion
+ }
+
+
+ ///
+ /// Event Args for SubItemClicked event
+ ///
+ public class SubItemEventArgs : EventArgs
+ {
+ int subItem = -1; /// Sub-item index
+ ListViewItem item = null;
+
+ public int SubItem { get { return subItem; } }
+ public ListViewItem Item { get { return item; } }
+
+ public SubItemEventArgs(ListViewItem item, int subItem)
+ {
+ this.subItem = subItem;
+ this.item = item;
+ }
+ }
+
+
+ ///
+ /// Event Args for SubItemEndEditingClicked event
+ ///
+ public class SubItemEndEditingEventArgs : SubItemEventArgs
+ {
+ string displayText = string.Empty;
+ bool cancel = true;
+
+ public SubItemEndEditingEventArgs(ListViewItem item, int subItem, string displayText, bool cancel) :
+ base(item, subItem)
+ {
+ this.displayText = displayText;
+ this.cancel = cancel;
+ }
+ public string DisplayText
+ {
+ get { return displayText; }
+ set { displayText = value; }
+ }
+ public bool Cancel
+ {
+ get { return cancel; }
+ set { cancel = value; }
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ListViewEx.resx b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ListViewEx.resx
new file mode 100644
index 00000000..7e323966
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ListViewEx.resx
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.0.0.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.Designer.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.Designer.cs
new file mode 100644
index 00000000..2e5ae7b7
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.Designer.cs
@@ -0,0 +1,64 @@
+namespace MonitoringDB.Forms
+{
+ partial class ModelessForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.label1 = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(47, 29);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(35, 13);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "label1";
+ //
+ // ModelessForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(191, 56);
+ this.Controls.Add(this.label1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Name = "ModelessForm";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "ModelessForm";
+ this.Load += new System.EventHandler(this.ModelessForm_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.cs
new file mode 100644
index 00000000..1f6186e3
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace MonitoringDB.Forms
+{
+ public partial class ModelessForm : Form
+ {
+ ///
+ /// Called from the state machine when an operation forces a modeless dialog close.
+ ///
+ public static void CloseForm()
+ {
+ if (CloseFormHandler == null) return;
+ try { CloseFormHandler(null, null); }
+ catch (Exception) { }
+ }
+ public static event EventHandler CloseFormHandler;
+
+ void OnCloseForm(object sender, EventArgs args)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+
+ public string Title;
+ public string Message;
+ public Color BackgroundColor;
+ public Color TextColor;
+ public Font TextFont;
+ public string FontFamily;
+ public int FontSize;
+ public FontStyle FontStyle;
+
+
+ ///
+ /// Constructor to be used by the application
+ ///
+ /// Window title
+ /// Displayed message
+ public ModelessForm()
+ {
+ InitializeComponent();
+ ControlBox = false;
+
+ CloseFormHandler += delegate(object sender, EventArgs args)
+ {
+ if (InvokeRequired) { Invoke(new EventHandler(OnCloseForm), sender, args); }
+ else OnCloseForm(sender, args);
+ };
+ }
+
+ private void ModelessForm_Load(object sender, EventArgs e)
+ {
+ if (Title != null) Text = Title;
+ if (Message != null) label1.Text = Message;
+ if (BackgroundColor != null) BackColor = BackgroundColor;
+ if (TextColor != null) ForeColor = TextColor;
+ if (FontFamily != null) label1.Font = new Font(FontFamily, FontSize, FontStyle);
+
+ float textWidth = Graphics.FromImage(new Bitmap(1, 1)).MeasureString(label1.Text, label1.Font).Width;
+ float textHeight = Graphics.FromImage(new Bitmap(1, 1)).MeasureString(label1.Text, label1.Font).Height;
+ Width = (int)textWidth + 120; /// Form width calculated from the text width
+ Height += (int)textHeight; /// Form height calculated from the text height
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.resx b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ModelessForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.cs
new file mode 100644
index 00000000..ed5b6781
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.cs
@@ -0,0 +1,299 @@
+///
+/// Copyright (c) 2016 Sensus Metering Systems
+///
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using log4net;
+using MonitoringDB.Entities;
+using MonitoringDB.Resources;
+
+namespace MonitoringDB.Forms
+{
+ public partial class ResultsConfigDlg : Form
+ {
+ ///
+ /// ListViewEx columns
+ ///
+ enum Column
+ {
+ Item,
+ Caption,
+ Format,
+ Precision,
+ Width,
+ Count,
+ }
+ Control[] editors;
+
+
+ public IList AvailableItems;
+ public IList SelectedItems;
+
+
+ public bool Compound; /// false = single meter items, true = combined meter items
+
+ public ResultsConfigDlg()
+ {
+ InitializeComponent();
+ }
+
+ void Localize()
+ {
+ Text = Strings.Configuration;
+ availableResultsLabel.Text = Strings.Available_results;
+ selectedResultsLabel.Text = Strings.Selected_results;
+ addButton.Text = Strings.Add;
+ removeButton.Text = Strings.Remove;
+ removeAllButton.Text = Strings.Remove_all;
+ okButton.Text = Strings.OkBtnText;
+ cancelButton.Text = Strings.CancelBtnText;
+ upButton.Text = Strings.UpBtnText;
+ downButton.Text = Strings.DownBtnText;
+ }
+
+ void ResultsConfig_Load(object sender, EventArgs e)
+ {
+ Localize();
+
+ /// Add columns to ListViewEx
+ selectedResultsListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Item, Width = 120 });
+ selectedResultsListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Caption });
+ selectedResultsListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Format });
+ selectedResultsListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Precision });
+ selectedResultsListViewEx.Columns.Add(new ColumnHeader { Text = Strings.Width });
+
+ editors = new Control[]
+ {
+ null,
+ new TextBox(),
+ new TextBox(),
+ new TextBox(),
+ new TextBox(),
+ };
+ foreach (var edi in editors)
+ {
+ if (edi != null)
+ {
+ edi.Visible = false;
+ Controls.Add(edi);
+ }
+ }
+
+ selectedResultsListViewEx.SubItemClicked += new SubItemEventHandler(selectedResultsListViewEx_SubItemClicked);
+ selectedResultsListViewEx.SubItemEndEditing += new SubItemEndEditingEventHandler(selectedResultsListViewEx_SubItemEndEditing);
+
+ RedrawAvailable();
+ RedrawSelected();
+ }
+
+ void selectedResultsListViewEx_SubItemClicked(object sender, SubItemEventArgs e)
+ {
+ if ((e.SubItem > 0) && (e.SubItem < (int)Column.Count))
+ {
+ selectedResultsListViewEx.StartEditing(editors[e.SubItem], e.Item, e.SubItem);
+ }
+ }
+
+ void selectedResultsListViewEx_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e)
+ {
+ ListViewItem lvi = e.Item;
+ ItemSpec item = lvi.Tag as ItemSpec;
+
+ switch ((Column)e.SubItem)
+ {
+ case Column.Caption: item.Caption = e.DisplayText; return;
+ case Column.Format: item.Format = e.DisplayText; return;
+ case Column.Precision: item.Precision = e.DisplayText; return;
+
+ case Column.Width:
+ {
+ int width;
+ if (Int32.TryParse(editors[e.SubItem].Text, out width) && width >= 0)
+ {
+ item.Width = width;
+ return; /// OK
+ }
+ break; /// Error
+ }
+ default:
+ return; /// OK
+ }
+
+ e.DisplayText = e.Item.SubItems[e.SubItem].Text;
+ e.Cancel = true;
+ return;
+ }
+
+ ///
+ /// Redraw selected items (right hand side)
+ ///
+ void RedrawAvailable()
+ {
+ availableResultsListBox.Items.Clear();
+ AvailableItems = new List();
+ foreach (var item in ItemSpec.AllItems)
+ {
+ AvailableItems.Add(item);
+ availableResultsListBox.Items.Add(item.Name);
+ }
+ }
+
+ ///
+ /// Redraw selected items (right hand side)
+ ///
+ void RedrawSelected()
+ {
+ selectedResultsListViewEx.Items.Clear();
+ foreach (var item in SelectedItems)
+ {
+ ListViewItem lvi = new ListViewItem(item.Name); /// Item
+ lvi.Tag = item;
+ lvi.SubItems.Add(item.Caption); /// Header
+ lvi.SubItems.Add(item.Format); /// Format
+ lvi.SubItems.Add(item.Precision); /// Precision
+ lvi.SubItems.Add(item.Width.ToString()); /// Width
+
+ selectedResultsListViewEx.Items.Add(lvi);
+ }
+ }
+
+ void UpdateSelectedFromView()
+ {
+ }
+
+ void availableResultsListBox_DoubleClick(object sender, EventArgs e)
+ {
+ /// Double click works when just one item is selected
+ if (availableResultsListBox.SelectedIndices.Count == 1)
+ {
+ var oriItem = AvailableItems[availableResultsListBox.SelectedIndices[0]];
+ SelectedItems.Add(oriItem.Clone());
+ RedrawAvailable();
+ RedrawSelected();
+
+ /// Select the last item
+ selectedResultsListViewEx.Focus();
+ selectedResultsListViewEx.Items[SelectedItems.Count - 1].Selected = true;
+ selectedResultsListViewEx.Items[SelectedItems.Count - 1].EnsureVisible();
+ }
+ }
+
+ void addButton_Click(object sender, EventArgs e)
+ {
+ /// Append at the end, this code supports multiple selected items,
+ /// although ListBox control settings may limit the max.number of selected items to one.
+
+ for (int i = availableResultsListBox.SelectedIndices.Count - 1; i >= 0; i--)
+ {
+ var oriItem = AvailableItems[availableResultsListBox.SelectedIndices[i]];
+ SelectedItems.Add(oriItem.Clone());
+ }
+ RedrawAvailable();
+ RedrawSelected();
+
+ /// Select the last item
+ selectedResultsListViewEx.Focus();
+ selectedResultsListViewEx.Items[SelectedItems.Count - 1].Selected = true;
+ selectedResultsListViewEx.Items[SelectedItems.Count - 1].EnsureVisible();
+ }
+
+ private void selectedResultsListBox_DoubleClick(object sender, EventArgs e)
+ {
+ /// Double click works when just one item is selected
+
+ if (selectedResultsListViewEx.SelectedIndices.Count == 1)
+ {
+ SelectedItems.RemoveAt(selectedResultsListViewEx.SelectedIndices[0]);
+ RedrawAvailable();
+ RedrawSelected();
+ }
+ }
+
+ void removeButton_Click(object sender, EventArgs e)
+ {
+ /// Remove from the list (the last selected item first so that the indexes are not affected)
+
+ for (int i = selectedResultsListViewEx.SelectedIndices.Count - 1; i >= 0; i--)
+ {
+ SelectedItems.RemoveAt(selectedResultsListViewEx.SelectedIndices[i]);
+ }
+ RedrawAvailable();
+ RedrawSelected();
+ }
+
+ void removeAllButton_Click(object sender, EventArgs e)
+ {
+ /// Remove all items from 'Selected' list
+
+ SelectedItems.Clear();
+ RedrawAvailable();
+ RedrawSelected();
+ }
+
+ void okButton_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ private void ResultsConfigDlg_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ e.Handled = true;
+ }
+
+ private void upButton_Click(object sender, EventArgs e)
+ {
+ if (selectedResultsListViewEx.SelectedIndices.Count != 1) return;
+
+ int selIdx = selectedResultsListViewEx.SelectedIndices[0];
+ if (selIdx == 0)
+ {
+ /// Cannot move up
+ selectedResultsListViewEx.Focus();
+ selectedResultsListViewEx.Items[0].Selected = true;
+ return;
+ }
+
+ ItemSpec tmp = SelectedItems[selIdx - 1];
+ SelectedItems[selIdx - 1] = SelectedItems[selIdx];
+ SelectedItems[selIdx] = tmp;
+
+ RedrawSelected();
+
+ selectedResultsListViewEx.Focus();
+ selectedResultsListViewEx.Items[selIdx - 1].Selected = true;
+ selectedResultsListViewEx.Items[selIdx - 1].EnsureVisible();
+ }
+
+ private void downButton_Click(object sender, EventArgs e)
+ {
+ if (selectedResultsListViewEx.SelectedIndices.Count != 1) return;
+
+ int selIdx = selectedResultsListViewEx.SelectedIndices[0];
+ if (selIdx == SelectedItems.Count - 1)
+ {
+ /// Cannot move down
+ selectedResultsListViewEx.Focus();
+ selectedResultsListViewEx.Items[SelectedItems.Count - 1].Selected = true;
+ return;
+ }
+
+ ItemSpec tmp = SelectedItems[selIdx + 1];
+ SelectedItems[selIdx + 1] = SelectedItems[selIdx];
+ SelectedItems[selIdx] = tmp;
+
+ RedrawSelected();
+
+ selectedResultsListViewEx.Focus();
+ selectedResultsListViewEx.Items[selIdx + 1].Selected = true;
+ selectedResultsListViewEx.Items[selIdx + 1].EnsureVisible();
+ }
+
+ private void cancelButton_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.designer.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.designer.cs
new file mode 100644
index 00000000..e99d463b
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.designer.cs
@@ -0,0 +1,201 @@
+///
+/// Copyright (c) 2016 Sensus Metering Systems
+///
+namespace MonitoringDB.Forms
+{
+ partial class ResultsConfigDlg
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.okButton = new System.Windows.Forms.Button();
+ this.cancelButton = new System.Windows.Forms.Button();
+ this.availableResultsListBox = new System.Windows.Forms.ListBox();
+ this.availableResultsLabel = new System.Windows.Forms.Label();
+ this.selectedResultsLabel = new System.Windows.Forms.Label();
+ this.removeAllButton = new System.Windows.Forms.Button();
+ this.removeButton = new System.Windows.Forms.Button();
+ this.addButton = new System.Windows.Forms.Button();
+ this.selectedResultsListViewEx = new MonitoringDB.Forms.ListViewEx();
+ this.upButton = new System.Windows.Forms.Button();
+ this.downButton = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // okButton
+ //
+ this.okButton.Location = new System.Drawing.Point(344, 401);
+ this.okButton.Name = "okButton";
+ this.okButton.Size = new System.Drawing.Size(104, 30);
+ this.okButton.TabIndex = 4;
+ this.okButton.Text = "OK";
+ this.okButton.UseVisualStyleBackColor = true;
+ this.okButton.Click += new System.EventHandler(this.okButton_Click);
+ //
+ // cancelButton
+ //
+ this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.cancelButton.Location = new System.Drawing.Point(465, 401);
+ this.cancelButton.Name = "cancelButton";
+ this.cancelButton.Size = new System.Drawing.Size(104, 30);
+ this.cancelButton.TabIndex = 5;
+ this.cancelButton.Text = "Cancel";
+ this.cancelButton.UseVisualStyleBackColor = true;
+ this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
+ //
+ // availableResultsListBox
+ //
+ this.availableResultsListBox.FormattingEnabled = true;
+ this.availableResultsListBox.Location = new System.Drawing.Point(12, 31);
+ this.availableResultsListBox.Name = "availableResultsListBox";
+ this.availableResultsListBox.Size = new System.Drawing.Size(162, 355);
+ this.availableResultsListBox.TabIndex = 6;
+ this.availableResultsListBox.DoubleClick += new System.EventHandler(this.availableResultsListBox_DoubleClick);
+ //
+ // availableResultsLabel
+ //
+ this.availableResultsLabel.AutoSize = true;
+ this.availableResultsLabel.Location = new System.Drawing.Point(12, 9);
+ this.availableResultsLabel.Name = "availableResultsLabel";
+ this.availableResultsLabel.Size = new System.Drawing.Size(86, 13);
+ this.availableResultsLabel.TabIndex = 8;
+ this.availableResultsLabel.Text = "Available results:";
+ //
+ // selectedResultsLabel
+ //
+ this.selectedResultsLabel.AutoSize = true;
+ this.selectedResultsLabel.Location = new System.Drawing.Point(284, 9);
+ this.selectedResultsLabel.Name = "selectedResultsLabel";
+ this.selectedResultsLabel.Size = new System.Drawing.Size(85, 13);
+ this.selectedResultsLabel.TabIndex = 9;
+ this.selectedResultsLabel.Text = "Selected results:";
+ //
+ // removeAllButton
+ //
+ this.removeAllButton.Location = new System.Drawing.Point(184, 144);
+ this.removeAllButton.Name = "removeAllButton";
+ this.removeAllButton.Size = new System.Drawing.Size(94, 30);
+ this.removeAllButton.TabIndex = 46;
+ this.removeAllButton.Text = "<< R&emove all";
+ this.removeAllButton.UseVisualStyleBackColor = true;
+ this.removeAllButton.Click += new System.EventHandler(this.removeAllButton_Click);
+ //
+ // removeButton
+ //
+ this.removeButton.Location = new System.Drawing.Point(184, 109);
+ this.removeButton.Name = "removeButton";
+ this.removeButton.Size = new System.Drawing.Size(93, 30);
+ this.removeButton.TabIndex = 45;
+ this.removeButton.Text = "< &Remove";
+ this.removeButton.UseVisualStyleBackColor = true;
+ this.removeButton.Click += new System.EventHandler(this.removeButton_Click);
+ //
+ // addButton
+ //
+ this.addButton.Location = new System.Drawing.Point(184, 74);
+ this.addButton.Name = "addButton";
+ this.addButton.Size = new System.Drawing.Size(93, 30);
+ this.addButton.TabIndex = 44;
+ this.addButton.Text = "&Add >";
+ this.addButton.UseVisualStyleBackColor = true;
+ this.addButton.Click += new System.EventHandler(this.addButton_Click);
+ //
+ // selectedResultsListViewEx
+ //
+ this.selectedResultsListViewEx.AllowColumnReorder = true;
+ this.selectedResultsListViewEx.DoubleClickActivation = false;
+ this.selectedResultsListViewEx.FullRowSelect = true;
+ this.selectedResultsListViewEx.Location = new System.Drawing.Point(287, 31);
+ this.selectedResultsListViewEx.Name = "selectedResultsListViewEx";
+ this.selectedResultsListViewEx.Size = new System.Drawing.Size(594, 355);
+ this.selectedResultsListViewEx.TabIndex = 47;
+ this.selectedResultsListViewEx.UseCompatibleStateImageBehavior = false;
+ this.selectedResultsListViewEx.View = System.Windows.Forms.View.Details;
+ this.selectedResultsListViewEx.SubItemClicked += new MonitoringDB.Forms.SubItemEventHandler(this.selectedResultsListViewEx_SubItemClicked);
+ this.selectedResultsListViewEx.SubItemEndEditing += new MonitoringDB.Forms.SubItemEndEditingEventHandler(this.selectedResultsListViewEx_SubItemEndEditing);
+ //
+ // upButton
+ //
+ this.upButton.Location = new System.Drawing.Point(184, 236);
+ this.upButton.Name = "upButton";
+ this.upButton.Size = new System.Drawing.Size(93, 30);
+ this.upButton.TabIndex = 48;
+ this.upButton.Text = "Up";
+ this.upButton.UseVisualStyleBackColor = true;
+ this.upButton.Click += new System.EventHandler(this.upButton_Click);
+ //
+ // downButton
+ //
+ this.downButton.Location = new System.Drawing.Point(184, 272);
+ this.downButton.Name = "downButton";
+ this.downButton.Size = new System.Drawing.Size(93, 30);
+ this.downButton.TabIndex = 49;
+ this.downButton.Text = "Down";
+ this.downButton.UseVisualStyleBackColor = true;
+ this.downButton.Click += new System.EventHandler(this.downButton_Click);
+ //
+ // ResultsConfigDlg
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(893, 445);
+ this.Controls.Add(this.downButton);
+ this.Controls.Add(this.upButton);
+ this.Controls.Add(this.selectedResultsListViewEx);
+ this.Controls.Add(this.removeAllButton);
+ this.Controls.Add(this.removeButton);
+ this.Controls.Add(this.addButton);
+ this.Controls.Add(this.selectedResultsLabel);
+ this.Controls.Add(this.availableResultsLabel);
+ this.Controls.Add(this.availableResultsListBox);
+ this.Controls.Add(this.cancelButton);
+ this.Controls.Add(this.okButton);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Name = "ResultsConfigDlg";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "ResultsConfig";
+ this.Load += new System.EventHandler(this.ResultsConfig_Load);
+ this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ResultsConfigDlg_KeyPress);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button okButton;
+ private System.Windows.Forms.Button cancelButton;
+ private System.Windows.Forms.ListBox availableResultsListBox;
+ private System.Windows.Forms.Label availableResultsLabel;
+ private System.Windows.Forms.Label selectedResultsLabel;
+ private System.Windows.Forms.Button removeAllButton;
+ private System.Windows.Forms.Button removeButton;
+ private System.Windows.Forms.Button addButton;
+ private ListViewEx selectedResultsListViewEx;
+ private System.Windows.Forms.Button upButton;
+ private System.Windows.Forms.Button downButton;
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.resx b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/ResultsConfigDlg.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.Designer.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.Designer.cs
new file mode 100644
index 00000000..a4e69e33
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.Designer.cs
@@ -0,0 +1,325 @@
+namespace MonitoringDB.Forms
+{
+ partial class SettingsDlg
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.connectionStringTextBox = new System.Windows.Forms.TextBox();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.radioButton2 = new System.Windows.Forms.RadioButton();
+ this.radioButton1 = new System.Windows.Forms.RadioButton();
+ this.groupBox3 = new System.Windows.Forms.GroupBox();
+ this.workplaceNameTextBox = new System.Windows.Forms.TextBox();
+ this.saveButton = new System.Windows.Forms.Button();
+ this.cancelButton = new System.Windows.Forms.Button();
+ this.groupBox4 = new System.Windows.Forms.GroupBox();
+ this.extraBatteryLifetimeTextBox = new System.Windows.Forms.TextBox();
+ this.oracleGroupBox = new System.Windows.Forms.GroupBox();
+ this.checkPcbIsInOracleCheckBox = new System.Windows.Forms.CheckBox();
+ this.oracleBatteryCheckBox = new System.Windows.Forms.CheckBox();
+ this.groupBox5 = new System.Windows.Forms.GroupBox();
+ this.usersDBConnStringTextBox = new System.Windows.Forms.TextBox();
+ this.timeGroupBox = new System.Windows.Forms.GroupBox();
+ this.timePicker3 = new System.Windows.Forms.DateTimePicker();
+ this.timePicker2 = new System.Windows.Forms.DateTimePicker();
+ this.timePicker1 = new System.Windows.Forms.DateTimePicker();
+ this.label1 = new System.Windows.Forms.Label();
+ this.groupBox1.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.groupBox3.SuspendLayout();
+ this.groupBox4.SuspendLayout();
+ this.oracleGroupBox.SuspendLayout();
+ this.groupBox5.SuspendLayout();
+ this.timeGroupBox.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.connectionStringTextBox);
+ this.groupBox1.Location = new System.Drawing.Point(12, 69);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(622, 50);
+ this.groupBox1.TabIndex = 1;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Connection string pre záznamy z výroby";
+ //
+ // connectionStringTextBox
+ //
+ this.connectionStringTextBox.Location = new System.Drawing.Point(17, 18);
+ this.connectionStringTextBox.Name = "connectionStringTextBox";
+ this.connectionStringTextBox.Size = new System.Drawing.Size(586, 20);
+ this.connectionStringTextBox.TabIndex = 0;
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.radioButton2);
+ this.groupBox2.Controls.Add(this.radioButton1);
+ this.groupBox2.Location = new System.Drawing.Point(12, 250);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(222, 70);
+ this.groupBox2.TabIndex = 4;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "Režim činnosti";
+ //
+ // radioButton2
+ //
+ this.radioButton2.AutoSize = true;
+ this.radioButton2.Location = new System.Drawing.Point(95, 41);
+ this.radioButton2.Name = "radioButton2";
+ this.radioButton2.Size = new System.Drawing.Size(58, 17);
+ this.radioButton2.TabIndex = 1;
+ this.radioButton2.TabStop = true;
+ this.radioButton2.Text = "Výroba";
+ this.radioButton2.UseVisualStyleBackColor = true;
+ //
+ // radioButton1
+ //
+ this.radioButton1.AutoSize = true;
+ this.radioButton1.Location = new System.Drawing.Point(95, 20);
+ this.radioButton1.Name = "radioButton1";
+ this.radioButton1.Size = new System.Drawing.Size(46, 17);
+ this.radioButton1.TabIndex = 0;
+ this.radioButton1.TabStop = true;
+ this.radioButton1.Text = "Test";
+ this.radioButton1.UseVisualStyleBackColor = true;
+ //
+ // groupBox3
+ //
+ this.groupBox3.Controls.Add(this.workplaceNameTextBox);
+ this.groupBox3.Location = new System.Drawing.Point(12, 12);
+ this.groupBox3.Name = "groupBox3";
+ this.groupBox3.Size = new System.Drawing.Size(622, 50);
+ this.groupBox3.TabIndex = 0;
+ this.groupBox3.TabStop = false;
+ this.groupBox3.Text = "Meno pracoviska";
+ //
+ // workplaceNameTextBox
+ //
+ this.workplaceNameTextBox.Location = new System.Drawing.Point(17, 18);
+ this.workplaceNameTextBox.Name = "workplaceNameTextBox";
+ this.workplaceNameTextBox.Size = new System.Drawing.Size(586, 20);
+ this.workplaceNameTextBox.TabIndex = 0;
+ //
+ // saveButton
+ //
+ this.saveButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.saveButton.Location = new System.Drawing.Point(400, 270);
+ this.saveButton.Name = "saveButton";
+ this.saveButton.Size = new System.Drawing.Size(104, 42);
+ this.saveButton.TabIndex = 6;
+ this.saveButton.Text = "Uložiť";
+ this.saveButton.UseVisualStyleBackColor = true;
+ this.saveButton.Click += new System.EventHandler(this.saveButton_Click);
+ //
+ // cancelButton
+ //
+ this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.cancelButton.Location = new System.Drawing.Point(523, 270);
+ this.cancelButton.Name = "cancelButton";
+ this.cancelButton.Size = new System.Drawing.Size(104, 42);
+ this.cancelButton.TabIndex = 7;
+ this.cancelButton.Text = "Zrušiť";
+ this.cancelButton.UseVisualStyleBackColor = true;
+ this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
+ //
+ // groupBox4
+ //
+ this.groupBox4.Controls.Add(this.extraBatteryLifetimeTextBox);
+ this.groupBox4.Location = new System.Drawing.Point(12, 182);
+ this.groupBox4.Name = "groupBox4";
+ this.groupBox4.Size = new System.Drawing.Size(222, 62);
+ this.groupBox4.TabIndex = 3;
+ this.groupBox4.TabStop = false;
+ this.groupBox4.Text = "Predĺženie životnosti baterky v mesiacoch";
+ //
+ // extraBatteryLifetimeTextBox
+ //
+ this.extraBatteryLifetimeTextBox.Location = new System.Drawing.Point(17, 25);
+ this.extraBatteryLifetimeTextBox.Name = "extraBatteryLifetimeTextBox";
+ this.extraBatteryLifetimeTextBox.Size = new System.Drawing.Size(191, 20);
+ this.extraBatteryLifetimeTextBox.TabIndex = 0;
+ //
+ // oracleGroupBox
+ //
+ this.oracleGroupBox.Controls.Add(this.checkPcbIsInOracleCheckBox);
+ this.oracleGroupBox.Controls.Add(this.oracleBatteryCheckBox);
+ this.oracleGroupBox.Location = new System.Drawing.Point(384, 182);
+ this.oracleGroupBox.Name = "oracleGroupBox";
+ this.oracleGroupBox.Size = new System.Drawing.Size(249, 74);
+ this.oracleGroupBox.TabIndex = 5;
+ this.oracleGroupBox.TabStop = false;
+ this.oracleGroupBox.Text = "Oracle";
+ this.oracleGroupBox.Visible = false;
+ //
+ // checkPcbIsInOracleCheckBox
+ //
+ this.checkPcbIsInOracleCheckBox.AutoSize = true;
+ this.checkPcbIsInOracleCheckBox.Location = new System.Drawing.Point(18, 45);
+ this.checkPcbIsInOracleCheckBox.Name = "checkPcbIsInOracleCheckBox";
+ this.checkPcbIsInOracleCheckBox.Size = new System.Drawing.Size(213, 17);
+ this.checkPcbIsInOracleCheckBox.TabIndex = 0;
+ this.checkPcbIsInOracleCheckBox.Text = "Skontrolovať či PCB už bola overovaná";
+ this.checkPcbIsInOracleCheckBox.UseVisualStyleBackColor = true;
+ //
+ // oracleBatteryCheckBox
+ //
+ this.oracleBatteryCheckBox.AutoSize = true;
+ this.oracleBatteryCheckBox.Location = new System.Drawing.Point(18, 19);
+ this.oracleBatteryCheckBox.Name = "oracleBatteryCheckBox";
+ this.oracleBatteryCheckBox.Size = new System.Drawing.Size(193, 17);
+ this.oracleBatteryCheckBox.TabIndex = 0;
+ this.oracleBatteryCheckBox.Text = "Uložiť informácie o batérii do Oracle";
+ this.oracleBatteryCheckBox.UseVisualStyleBackColor = true;
+ //
+ // groupBox5
+ //
+ this.groupBox5.Controls.Add(this.usersDBConnStringTextBox);
+ this.groupBox5.Location = new System.Drawing.Point(12, 125);
+ this.groupBox5.Name = "groupBox5";
+ this.groupBox5.Size = new System.Drawing.Size(622, 50);
+ this.groupBox5.TabIndex = 2;
+ this.groupBox5.TabStop = false;
+ this.groupBox5.Text = "Connection string pre centrálnu databázu používateľov";
+ //
+ // usersDBConnStringTextBox
+ //
+ this.usersDBConnStringTextBox.Location = new System.Drawing.Point(17, 18);
+ this.usersDBConnStringTextBox.Name = "usersDBConnStringTextBox";
+ this.usersDBConnStringTextBox.Size = new System.Drawing.Size(586, 20);
+ this.usersDBConnStringTextBox.TabIndex = 0;
+ //
+ // timeGroupBox
+ //
+ this.timeGroupBox.Controls.Add(this.label1);
+ this.timeGroupBox.Controls.Add(this.timePicker3);
+ this.timeGroupBox.Controls.Add(this.timePicker2);
+ this.timeGroupBox.Controls.Add(this.timePicker1);
+ this.timeGroupBox.Location = new System.Drawing.Point(240, 181);
+ this.timeGroupBox.Name = "timeGroupBox";
+ this.timeGroupBox.Size = new System.Drawing.Size(138, 140);
+ this.timeGroupBox.TabIndex = 8;
+ this.timeGroupBox.TabStop = false;
+ this.timeGroupBox.Text = "Čas odlogovania";
+ this.timeGroupBox.Visible = false;
+ //
+ // timePicker3
+ //
+ this.timePicker3.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+ this.timePicker3.Location = new System.Drawing.Point(19, 98);
+ this.timePicker3.Name = "timePicker3";
+ this.timePicker3.Size = new System.Drawing.Size(98, 20);
+ this.timePicker3.TabIndex = 2;
+ //
+ // timePicker2
+ //
+ this.timePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+ this.timePicker2.Location = new System.Drawing.Point(19, 72);
+ this.timePicker2.Name = "timePicker2";
+ this.timePicker2.Size = new System.Drawing.Size(98, 20);
+ this.timePicker2.TabIndex = 1;
+ //
+ // timePicker1
+ //
+ this.timePicker1.AllowDrop = true;
+ this.timePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+ this.timePicker1.Location = new System.Drawing.Point(19, 46);
+ this.timePicker1.Name = "timePicker1";
+ this.timePicker1.Size = new System.Drawing.Size(98, 20);
+ this.timePicker1.TabIndex = 0;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(17, 27);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(106, 13);
+ this.label1.TabIndex = 3;
+ this.label1.Text = "00:00 = neodlogovať";
+ //
+ // SettingsDlg
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(648, 333);
+ this.Controls.Add(this.timeGroupBox);
+ this.Controls.Add(this.groupBox5);
+ this.Controls.Add(this.oracleGroupBox);
+ this.Controls.Add(this.groupBox4);
+ this.Controls.Add(this.cancelButton);
+ this.Controls.Add(this.saveButton);
+ this.Controls.Add(this.groupBox3);
+ this.Controls.Add(this.groupBox2);
+ this.Controls.Add(this.groupBox1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.MaximizeBox = false;
+ this.Name = "SettingsDlg";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.Text = "SettingsDlg";
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ this.groupBox2.ResumeLayout(false);
+ this.groupBox2.PerformLayout();
+ this.groupBox3.ResumeLayout(false);
+ this.groupBox3.PerformLayout();
+ this.groupBox4.ResumeLayout(false);
+ this.groupBox4.PerformLayout();
+ this.oracleGroupBox.ResumeLayout(false);
+ this.oracleGroupBox.PerformLayout();
+ this.groupBox5.ResumeLayout(false);
+ this.groupBox5.PerformLayout();
+ this.timeGroupBox.ResumeLayout(false);
+ this.timeGroupBox.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.TextBox connectionStringTextBox;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.GroupBox groupBox3;
+ private System.Windows.Forms.TextBox workplaceNameTextBox;
+ private System.Windows.Forms.Button saveButton;
+ private System.Windows.Forms.Button cancelButton;
+ private System.Windows.Forms.RadioButton radioButton2;
+ private System.Windows.Forms.RadioButton radioButton1;
+ private System.Windows.Forms.GroupBox groupBox4;
+ private System.Windows.Forms.TextBox extraBatteryLifetimeTextBox;
+ private System.Windows.Forms.GroupBox oracleGroupBox;
+ private System.Windows.Forms.CheckBox oracleBatteryCheckBox;
+ private System.Windows.Forms.CheckBox checkPcbIsInOracleCheckBox;
+ private System.Windows.Forms.GroupBox groupBox5;
+ private System.Windows.Forms.TextBox usersDBConnStringTextBox;
+ private System.Windows.Forms.GroupBox timeGroupBox;
+ private System.Windows.Forms.DateTimePicker timePicker3;
+ private System.Windows.Forms.DateTimePicker timePicker2;
+ private System.Windows.Forms.DateTimePicker timePicker1;
+ private System.Windows.Forms.Label label1;
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.cs
new file mode 100644
index 00000000..ae30c400
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Windows.Forms;
+
+namespace MonitoringDB.Forms
+{
+ public partial class SettingsDlg : Form
+ {
+ static readonly DateTime MinTime = new DateTime(1753, 1, 1, 0, 0, 0);
+
+
+ public string WorkplaceName
+ {
+ set { workplaceNameTextBox.Text = value; }
+ get { return workplaceNameTextBox.Text; }
+ }
+
+ public string ConnectionString
+ {
+ set { connectionStringTextBox.Text = value; }
+ get { return connectionStringTextBox.Text; }
+ }
+
+ public string UsersDBConnString
+ {
+ set { usersDBConnStringTextBox.Text = value; }
+ get { return usersDBConnStringTextBox.Text; }
+ }
+
+ public bool OracleBattery
+ {
+ set { oracleBatteryCheckBox.Checked = value; }
+ get { return oracleBatteryCheckBox.Checked; }
+ }
+
+ public bool CheckPcbIsInOracle
+ {
+ set { checkPcbIsInOracleCheckBox.Checked = value; }
+ get { return checkPcbIsInOracleCheckBox.Checked; }
+ }
+
+ public int ExtraBatterLifetime
+ {
+ get
+ {
+ int extraLifetime;
+ if (int.TryParse(extraBatteryLifetimeTextBox.Text, out extraLifetime) && extraLifetime >= 0) return extraLifetime;
+ return 0;
+ }
+ }
+
+ public MonitoringDB.Mode Mode
+ {
+ set
+ {
+ radioButton1.Checked = (value == MonitoringDB.Mode.Test);
+ radioButton2.Checked = (value == MonitoringDB.Mode.Production);
+ }
+ get
+ {
+ return radioButton1.Checked ? MonitoringDB.Mode.Test : MonitoringDB.Mode.Production;
+ }
+ }
+
+ public DateTime LogoutTime1
+ {
+ get { return timePicker1.Value; }
+ set { timePicker1.Value = (value.CompareTo(MinTime) < 0) ? MinTime : value; }
+ }
+
+ public DateTime LogoutTime2
+ {
+ get { return timePicker2.Value; }
+ set { timePicker2.Value = (value.CompareTo(MinTime) < 0) ? MinTime : value; }
+ }
+
+ public DateTime LogoutTime3
+ {
+ get { return timePicker3.Value; }
+ set { timePicker3.Value = (value.CompareTo(MinTime) < 0) ? MinTime : value; }
+ }
+
+
+ ///
+ /// Basic configuration dialog
+ ///
+ /// false = Konfiguracia pracovisk, true = Pracovisko
+ public SettingsDlg(bool isWorkplace)
+ {
+ InitializeComponent();
+ if (isWorkplace)
+ {
+ oracleGroupBox.Visible = true;
+ timeGroupBox.Visible = true;
+ }
+ extraBatteryLifetimeTextBox.Text = "0";
+
+ timePicker1.Format = DateTimePickerFormat.Custom;
+ timePicker1.CustomFormat = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
+
+ timePicker2.Format = DateTimePickerFormat.Custom;
+ timePicker2.CustomFormat = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
+
+ timePicker3.Format = DateTimePickerFormat.Custom;
+ timePicker3.CustomFormat = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
+ }
+
+ private void saveButton_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ private void cancelButton_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.resx b/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/SettingsDlg.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.cs
new file mode 100644
index 00000000..417172f0
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Windows.Forms;
+
+namespace MonitoringDB.Forms
+{
+ public partial class TrivialLoginDlg : Form
+ {
+ public LoginLevel LoginLevel;
+
+ public TrivialLoginDlg()
+ {
+ InitializeComponent();
+ LoginLevel = LoginLevel.None;
+ }
+
+ private void okButton_Click(object sender, EventArgs e)
+ {
+ if (passwordTextBox.Text.ToLower().Equals("barcode"))
+ {
+ LoginLevel = LoginLevel.Administrator;
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ else if (passwordTextBox.Text.ToLower().Equals("teamleader"))
+ {
+ LoginLevel = LoginLevel.TeamLeader;
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ else if (passwordTextBox.Text.ToLower().Equals("kremik"))
+ {
+ LoginLevel = LoginLevel.MH;
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ else
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+
+ private void cancelButton_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.designer.cs b/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.designer.cs
new file mode 100644
index 00000000..a6ed92a7
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.designer.cs
@@ -0,0 +1,105 @@
+namespace MonitoringDB.Forms
+{
+ partial class TrivialLoginDlg
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.passwordGroupBox = new System.Windows.Forms.GroupBox();
+ this.passwordTextBox = new System.Windows.Forms.TextBox();
+ this.okButton = new System.Windows.Forms.Button();
+ this.cancelButton = new System.Windows.Forms.Button();
+ this.passwordGroupBox.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // passwordGroupBox
+ //
+ this.passwordGroupBox.Controls.Add(this.passwordTextBox);
+ this.passwordGroupBox.Location = new System.Drawing.Point(12, 10);
+ this.passwordGroupBox.Name = "passwordGroupBox";
+ this.passwordGroupBox.Size = new System.Drawing.Size(200, 49);
+ this.passwordGroupBox.TabIndex = 0;
+ this.passwordGroupBox.TabStop = false;
+ this.passwordGroupBox.Text = "Heslo";
+ //
+ // passwordTextBox
+ //
+ this.passwordTextBox.Location = new System.Drawing.Point(51, 18);
+ this.passwordTextBox.Name = "passwordTextBox";
+ this.passwordTextBox.PasswordChar = '*';
+ this.passwordTextBox.Size = new System.Drawing.Size(100, 20);
+ this.passwordTextBox.TabIndex = 0;
+ //
+ // okButton
+ //
+ this.okButton.Location = new System.Drawing.Point(237, 18);
+ this.okButton.Name = "okButton";
+ this.okButton.Size = new System.Drawing.Size(75, 39);
+ this.okButton.TabIndex = 1;
+ this.okButton.Text = "OK";
+ this.okButton.UseVisualStyleBackColor = true;
+ this.okButton.Click += new System.EventHandler(this.okButton_Click);
+ //
+ // cancelButton
+ //
+ this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.cancelButton.Location = new System.Drawing.Point(330, 18);
+ this.cancelButton.Name = "cancelButton";
+ this.cancelButton.Size = new System.Drawing.Size(75, 39);
+ this.cancelButton.TabIndex = 2;
+ this.cancelButton.Text = "Cancel";
+ this.cancelButton.UseVisualStyleBackColor = true;
+ this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
+ //
+ // LoginDlg
+ //
+ this.AcceptButton = this.okButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.cancelButton;
+ this.ClientSize = new System.Drawing.Size(426, 73);
+ this.Controls.Add(this.cancelButton);
+ this.Controls.Add(this.okButton);
+ this.Controls.Add(this.passwordGroupBox);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "LoginDlg";
+ this.Text = "LoginDlg";
+ this.passwordGroupBox.ResumeLayout(false);
+ this.passwordGroupBox.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox passwordGroupBox;
+ private System.Windows.Forms.TextBox passwordTextBox;
+ private System.Windows.Forms.Button okButton;
+ private System.Windows.Forms.Button cancelButton;
+ }
+}
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.resx b/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Forms/TrivialLoginDlg.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/Interfaces/IOption.cs b/TBF_V2/Sources/TBF/MonitoringDB/Interfaces/IOption.cs
new file mode 100644
index 00000000..c585a3ad
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/Interfaces/IOption.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace MonitoringDB.Interfaces
+{
+ public interface IOption
+ {
+ int Id { get; }
+ int ItemNr { get; set; }
+ string Name { get; set; }
+ string OraDBType { get; set; }
+ string Description { get; set; }
+ CodeType CodeType { get; set; }
+ CodeForm CodeForm { get; set; }
+ CodeLocation CodeLocation { get; set; }
+ LifetimeManagement LifetimeManagement { get; set; }
+ bool Enabled { get; set; }
+ Entities.Part GetPart(Entities.Process owningProcess);
+ }
+}
diff --git a/TBF_V2/Sources/TBF/MonitoringDB/ItemSpec.cs b/TBF_V2/Sources/TBF/MonitoringDB/ItemSpec.cs
new file mode 100644
index 00000000..9826e58b
--- /dev/null
+++ b/TBF_V2/Sources/TBF/MonitoringDB/ItemSpec.cs
@@ -0,0 +1,306 @@
+///
+/// Copyright (c) 2016-2017 Sensus Slovensko a.s.
+///
+using System;
+using System.Collections.Generic;
+using MonitoringDB.Entities;
+using MonitoringDB.Resources;
+using NHibernate;
+using NHibernate.Criterion;
+
+namespace MonitoringDB
+{
+ public class ItemSpec
+ {
+ ///
+ /// Function delegate to pick a reference record and convert it to a string
+ ///
+ public delegate string PrintDlgt(object x, string format, string precision, int width);
+
+ ///
+ /// Public fields
+ ///
+ public readonly ItemSpecID Uid; /// Unique Uid used to distinguish items
+ public readonly string Name; /// Name that can be localized to identify the item in a list
+ public readonly PrintDlgt PrintFn; /// Function used to convert the result to a text
+
+ public string Caption; /// User defined text printed in the column header
+ public string Format; /// Specifies the text generation
+ public string Precision; /// Specifies the text generation
+ public int Width; /// Specifies the text generation
+
+ readonly ItemSpecCaps itemSpecCaps;
+
+ /// Public parameterless constructor
+ public ItemSpec()
+ {
+ }
+
+ /// Constructor to specify all items
+ public ItemSpec(ItemSpecID uid, string name, PrintDlgt printFn, ItemSpecCaps itemSpecCaps)
+ {
+ Uid = uid;
+ Name = name;
+ PrintFn = printFn;
+ this.itemSpecCaps = itemSpecCaps;
+ ///
+ Caption = name;
+ Format = "{0}";
+ Precision = string.Empty;
+ Width = 0;
+ }
+
+ /// Copy constructor
+ public ItemSpec Clone()
+ {
+ ItemSpec newItem = new ItemSpec(Uid, Name, PrintFn, itemSpecCaps);
+ newItem.Caption = Caption;
+ newItem.Format = Format;
+ newItem.Precision = Precision;
+ newItem.Width = Width;
+ return newItem;
+ }
+
+
+ /// Safe wrapper which replaces null-s by empty strings
+ public string Print(object x)
+ {
+ string str = PrintFn(x, Format, Precision, Width);
+ return (str == null) ? string.Empty : str;
+ }
+
+
+ /// Similar to Print(), in addition embeds text into ""
+ public string Export(object x)
+ {
+ string str = PrintFn(x, Format, Precision, Width);
+ if (str == null) str = string.Empty;
+
+ if (Uid == ItemSpecID.Barcode || Uid == ItemSpecID.PartBarcode || Uid == ItemSpecID.SerialNr || Uid == ItemSpecID.PurchaseOrder)
+ {
+ return string.Format("=\"{0}\"", str);
+ }
+ return str;
+ }
+
+
+ /// Static list of all available items
+ public static readonly IList AllItems;
+
+ ///
+ /// Static constructor that initializes the list of all items
+ ///
+ static ItemSpec()
+ {
+ AllItems = new List();
+
+ AllItems.Add(new ItemSpec(ItemSpecID.RefRecordID, Strings.RefRecordID, (x, f, p, w) => ((int)x).ToString(), ItemSpecCaps.ReferenceRecord));
+
+ AllItems.Add(new ItemSpec(ItemSpecID.TimeStamp, Strings.Time_stamp, (x, f, p, w) => string.IsNullOrEmpty(f) ? ((DateTime)x).ToString() : string.Format(f, (DateTime)x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.Workstep, Strings.Workstep, (x, f, p, w) => string.IsNullOrEmpty(f) ? ((Workstep)x).Name : string.Format(f, ((Workstep)x).Name), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.Workplace, Strings.Workplace, (x, f, p, w) => string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.UserName, Strings.User_name, (x, f, p, w) => string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.Barcode, Strings.Barcode, (x, f, p, w) => string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.PartBarcode, Strings.Part_barcode, (x, f, p, w) => string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord | ItemSpecCaps.AssociatedRecord));
+
+ AllItems.Add(new ItemSpec(ItemSpecID.TimeStamp2, Strings.Time_stamp+"2", (x, f, p, w) => string.IsNullOrEmpty(f) ? ((DateTime)x).ToString() : string.Format(f, (DateTime)x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.Workstep2, Strings.Workstep+"2", (x, f, p, w) => string.IsNullOrEmpty(f) ? ((Workstep)x).Name : string.Format(f, ((Workstep)x).Name), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.Workplace2, Strings.Workplace+"2", (x, f, p, w) => string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.UserName2, Strings.User_name+"2", (x, f, p, w) => string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.Barcode2, Strings.Barcode+"2", (x, f, p, w) => string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord));
+ AllItems.Add(new ItemSpec(ItemSpecID.PartBarcode2, Strings.Part_barcode+"2",(x, f, p, w)=> string.IsNullOrEmpty(f) ? (string)x : string.Format(f, x), ItemSpecCaps.ReferenceRecord | ItemSpecCaps.AssociatedRecord));
+
+ AllItems.Add(new ItemSpec(ItemSpecID.SerialNr, Strings.Serial_nr, (x, f, p, w) => x as string, ItemSpecCaps.ReferenceRecord | ItemSpecCaps.OracleQuery));
+ AllItems.Add(new ItemSpec(ItemSpecID.PurchaseOrder, Strings.Purchase_order, (x, f, p, w) => x as string, ItemSpecCaps.ReferenceRecord | ItemSpecCaps.OracleQuery));
+ AllItems.Add(new ItemSpec(ItemSpecID.TestResult, Strings.Test_result, (x, f, p, w) => x as string, ItemSpecCaps.ReferenceRecord | ItemSpecCaps.OracleQuery));
+ AllItems.Add(new ItemSpec(ItemSpecID.MaxPruefindex, Strings.Max_pruefindex, (x, f, p, w) => x as string, ItemSpecCaps.ReferenceRecord | ItemSpecCaps.OracleQuery));
+
+ AllItems.Add(new ItemSpec(ItemSpecID.Process, Strings.Process, (x, f, p, w) => string.IsNullOrEmpty(f) ? ((Process)x).Name : string.Format(f, ((Process)x).Name), ItemSpecCaps.ReferenceRecord));
+ }
+
+ public PropertyProjection GetProperty(ReferenceRecord refRecord, Record record)
+ {
+ switch (Uid)
+ {
+ case ItemSpecID.RefRecordID: return Projections.Property(() => refRecord.Id);
+
+ case ItemSpecID.TimeStamp: return Projections.Property(() => refRecord.TimeStamp);
+ case ItemSpecID.Workstep: return Projections.Property(() => refRecord.Workstep);
+ case ItemSpecID.Workplace: return Projections.Property(() => refRecord.Workplace);
+ case ItemSpecID.UserName: return Projections.Property(() => refRecord.UserName);
+ case ItemSpecID.Barcode: return Projections.Property(() => refRecord.Code);
+ case ItemSpecID.PartBarcode: return Projections.Property(() => record.Code);
+
+ case ItemSpecID.TimeStamp2: return null;
+ case ItemSpecID.Workstep2: return null;
+ case ItemSpecID.Workplace2: return null;
+ case ItemSpecID.UserName2: return null;
+ case ItemSpecID.Barcode2: return null;
+ case ItemSpecID.PartBarcode2: return null;
+
+ case ItemSpecID.SerialNr: return null;
+ case ItemSpecID.PurchaseOrder: return null;
+ case ItemSpecID.TestResult: return null;
+ case ItemSpecID.MaxPruefindex: return null;
+
+ case ItemSpecID.Process: return Projections.Property(() => refRecord.Process);
+
+ default: return null;
+ }
+ }
+
+ public PropertyProjection GetProperty2(ReferenceRecord refRecord2, Record record2)
+ {
+ switch (Uid)
+ {
+ case ItemSpecID.RefRecordID: return null;
+
+ case ItemSpecID.TimeStamp: return null;
+ case ItemSpecID.Workstep: return null;
+ case ItemSpecID.Workplace: return null;
+ case ItemSpecID.UserName: return null;
+ case ItemSpecID.Barcode: return null;
+ case ItemSpecID.PartBarcode: return null;
+
+ case ItemSpecID.TimeStamp2: return Projections.Property(() => refRecord2.TimeStamp);
+ case ItemSpecID.Workstep2: return Projections.Property(() => refRecord2.Workstep);
+ case ItemSpecID.Workplace2: return Projections.Property(() => refRecord2.Workplace);
+ case ItemSpecID.UserName2: return Projections.Property(() => refRecord2.UserName);
+ case ItemSpecID.Barcode2: return Projections.Property(() => refRecord2.Code);
+ case ItemSpecID.PartBarcode2: return Projections.Property(() => record2.Code);
+
+ case ItemSpecID.SerialNr: return null;
+ case ItemSpecID.PurchaseOrder: return null;
+ case ItemSpecID.TestResult: return null;
+ case ItemSpecID.MaxPruefindex: return null;
+
+ case ItemSpecID.Process: return Projections.Property(() => refRecord2.Process);
+
+ default: return null;
+ }
+ }
+
+ public ItemSpecCaps GetCaps()
+ {
+ return itemSpecCaps;
+ }
+
+
+ public static ItemSpec GetItem(ItemSpecID id)
+ {
+ foreach (var item in AllItems)
+ if (item.Uid == id)
+ return item.Clone();
+
+ return null;
+ }
+
+ public static ItemSpec GetItem(string uidName)
+ {
+ foreach (var item in AllItems)
+ if (item.Uid.ToString() == uidName)
+ return item.Clone();
+
+ return null;
+ }
+
+
+ public static ProjectionList GetProjections(IList items, ReferenceRecord refRecord, Record record)
+ {
+ ProjectionList projections = Projections.ProjectionList();
+ foreach (var item in items)
+ {
+ PropertyProjection projection = item.GetProperty(refRecord, record);
+ if (projection != null)
+ projections.Add(projection);
+ }
+
+ return projections;
+ }
+
+ public static IList