diff --git a/VECTO.sln.DotSettings b/VECTO.sln.DotSettings new file mode 100644 index 0000000000000000000000000000000000000000..79c8369e0b13181e7fdbd97067486f05854bd6ca --- /dev/null +++ b/VECTO.sln.DotSettings @@ -0,0 +1,22 @@ +<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER_SAME_LINE</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FIXED_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOR_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOREACH_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">False</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">False</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FINALLY_ON_NEW_LINE/@EntryValue">False</s:Boolean> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_EMBEDDED_STATEMENT_STYLE/@EntryValue">LINE_BREAK</s:String> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_MULTIPLICATIVE_OP/@EntryValue">True</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean> + <s:Boolean x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=2BF7A1E51991F2458D2D1F0B29CF888B/@KeyIndexDefined">True</s:Boolean> + <s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=2BF7A1E51991F2458D2D1F0B29CF888B/AbsolutePath/@EntryValue">C:\Workspaces\VisualStudio\VECTO_quam\VECTO.sln.DotSettings</s:String> + <s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File2BF7A1E51991F2458D2D1F0B29CF888B/@KeyIndexDefined">True</s:Boolean> + <s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File2BF7A1E51991F2458D2D1F0B29CF888B/RelativePriority/@EntryValue">1</s:Double></wpf:ResourceDictionary> \ No newline at end of file diff --git a/VectoCore/Exceptions/VectoExceptions.cs b/VectoCore/Exceptions/VectoExceptions.cs index 58d1436e80ebc7fb09565a772798d5b7bafdab83..f8d2788729c93587b39e011d6554055345385b64 100644 --- a/VectoCore/Exceptions/VectoExceptions.cs +++ b/VectoCore/Exceptions/VectoExceptions.cs @@ -2,41 +2,41 @@ namespace TUGraz.VectoCore.Exceptions { - public class VectoException : Exception - { - public VectoException(string message) : base(message) { } - public VectoException(string message, Exception innerException) : base(message, innerException) { } - } + public class VectoException : Exception + { + public VectoException(string message) : base(message) {} + public VectoException(string message, Exception innerException) : base(message, innerException) {} + } - public abstract class FileIOException : VectoException - { - protected FileIOException(string message) : base(message) { } - protected FileIOException(string message, Exception inner) : base(message, inner) { } - } + public abstract class FileIOException : VectoException + { + protected FileIOException(string message) : base(message) {} + protected FileIOException(string message, Exception inner) : base(message, inner) {} + } - public class InvalidFileFormatException : FileIOException + public class InvalidFileFormatException : FileIOException { - public InvalidFileFormatException(string message) : base(message) { } - public InvalidFileFormatException(string message, Exception inner) : base(message) { } + public InvalidFileFormatException(string message) : base(message) {} + public InvalidFileFormatException(string message, Exception inner) : base(message) {} } /// <summary> - /// Exception which gets thrown when the version of a file is not supported. + /// Exception which gets thrown when the version of a file is not supported. /// </summary> public class UnsupportedFileVersionException : FileIOException { - public UnsupportedFileVersionException(string message) : base(message) { } - public UnsupportedFileVersionException(string message, Exception inner) : base(message, inner) { } + public UnsupportedFileVersionException(string message) : base(message) {} + public UnsupportedFileVersionException(string message, Exception inner) : base(message, inner) {} } /// <summary> - /// Exception which gets thrown when an error occurred during read of a vecto csv-file. - /// </summary> + /// Exception which gets thrown when an error occurred during read of a vecto csv-file. + /// </summary> public class CSVReadException : FileIOException - { - public CSVReadException(string message) : base(message) { } - public CSVReadException(string message, Exception inner) : base(message, inner) { } - } -} + { + public CSVReadException(string message) : base(message) {} + public CSVReadException(string message, Exception inner) : base(message, inner) {} + } +} \ No newline at end of file diff --git a/VectoCore/Exceptions/VectoSimulationException.cs b/VectoCore/Exceptions/VectoSimulationException.cs index 563d56addc1f611dbf6b0fdd1d485d943d60a0de..0880f14e0f12b004088d8eb37ec83de875621817 100644 --- a/VectoCore/Exceptions/VectoSimulationException.cs +++ b/VectoCore/Exceptions/VectoSimulationException.cs @@ -4,9 +4,7 @@ namespace TUGraz.VectoCore.Exceptions { public class VectoSimulationException : VectoException { - public VectoSimulationException(string msg) : base(msg) { } - - public VectoSimulationException(string msg, Exception inner) : base(msg, inner) { } + public VectoSimulationException(string msg) : base(msg) {} + public VectoSimulationException(string msg, Exception inner) : base(msg, inner) {} } - -} +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Connector.cs b/VectoCore/Models/Connector/Connector.cs index aa625722002371f60fc826e4baee0d1b3be9779f..b73a4396def74f699f6419b9b7f48229383982c0 100644 --- a/VectoCore/Models/Connector/Connector.cs +++ b/VectoCore/Models/Connector/Connector.cs @@ -2,7 +2,7 @@ namespace TUGraz.VectoCore.Models.Connector { - class Connector<TI, TO, TP> + internal class Connector<TI, TO, TP> where TI : InPort, TP where TO : OutPort, TP { @@ -17,5 +17,4 @@ namespace TUGraz.VectoCore.Models.Connector InPort.Connect(OutPort); } } - -} +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs b/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs index 1e667cd6956c8a9608b5b0ee4a625536f23cf3e1..aa79be1129e7ac4de36efa60d58f0bb83647ebef 100644 --- a/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs +++ b/VectoCore/Models/Connector/Ports/IDriverDemandInPort.cs @@ -1,7 +1,7 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface IDriverDemandInPort - { - void Connect(IDriverDemandOutPort other); - } -} + public interface IDriverDemandInPort + { + void Connect(IDriverDemandOutPort other); + } +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs b/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs index 33d69149dee2e4360cc3f746c5331c16b1d958e9..e24d487844c575a27cddd143a0e00d7b4ae82a4f 100644 --- a/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs +++ b/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs @@ -1,11 +1,10 @@ using System; -using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface IDriverDemandOutPort - { - IResponse Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient); - } -} + public interface IDriverDemandOutPort + { + IResponse Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient); + } +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/IDriverDemandOutProvider.cs b/VectoCore/Models/Connector/Ports/IDriverDemandOutProvider.cs index c14a9ae89dbc7b14dc37577dc4db4d087207998a..0ab63571bc0d4aaacceeb42e5cfd33181c03e478 100644 --- a/VectoCore/Models/Connector/Ports/IDriverDemandOutProvider.cs +++ b/VectoCore/Models/Connector/Ports/IDriverDemandOutProvider.cs @@ -1,7 +1,7 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface IDriverDemandOutProvider - { - IDriverDemandOutPort OutPort(); - } -} + public interface IDriverDemandOutProvider + { + IDriverDemandOutPort OutPort(); + } +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/IInPort.cs b/VectoCore/Models/Connector/Ports/IInPort.cs index 5709c785545e766ee3338794a06ca70fd4fc6ce3..878abe6577ac13f753b3093c56001ae44c2f1097 100644 --- a/VectoCore/Models/Connector/Ports/IInPort.cs +++ b/VectoCore/Models/Connector/Ports/IInPort.cs @@ -1,6 +1,4 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface IInPort - { - } + public interface IInPort {} } \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/IOutPort.cs b/VectoCore/Models/Connector/Ports/IOutPort.cs index 01887d5a13add05ad958dad87b0bd351f28a3c76..0aff780b6a2e9ca6ed3005327cb2a0b7170d705f 100644 --- a/VectoCore/Models/Connector/Ports/IOutPort.cs +++ b/VectoCore/Models/Connector/Ports/IOutPort.cs @@ -1,6 +1,4 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface IOutPort - { - } + public interface IOutPort {} } \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/IOutShaft.cs b/VectoCore/Models/Connector/Ports/IOutShaft.cs index 1332dd8ab6a2eb713213d6dda3b29aa54fefce73..d6378e09280c9d0f124d4ccfe379cf9de7322976 100644 --- a/VectoCore/Models/Connector/Ports/IOutShaft.cs +++ b/VectoCore/Models/Connector/Ports/IOutShaft.cs @@ -4,4 +4,4 @@ { ITnOutPort OutShaft(); } -} +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/IResponse.cs b/VectoCore/Models/Connector/Ports/IResponse.cs index 01ce67de3abca5a82dbb0ac4394d8cddf3de82b1..897aecd0d0e6b124d351083bc9500fe2a2b5d85f 100644 --- a/VectoCore/Models/Connector/Ports/IResponse.cs +++ b/VectoCore/Models/Connector/Ports/IResponse.cs @@ -1,6 +1,4 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface IResponse - { - } + public interface IResponse {} } \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/ITnInPort.cs b/VectoCore/Models/Connector/Ports/ITnInPort.cs index f6b2d9ac9a5cf9d01aa2771ebd5aade2aecf77df..015943ddb1e7d00db223fc2ab5f74a68b4f9335a 100644 --- a/VectoCore/Models/Connector/Ports/ITnInPort.cs +++ b/VectoCore/Models/Connector/Ports/ITnInPort.cs @@ -1,7 +1,7 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface ITnInPort : ITnPort, IInPort - { - void Connect(ITnOutPort other); - } + public interface ITnInPort : ITnPort, IInPort + { + void Connect(ITnOutPort other); + } } \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/ITnOutPort.cs b/VectoCore/Models/Connector/Ports/ITnOutPort.cs index 4f1f342c9e8176df0fac35f80bc878ff8a897bce..6a7a10b010b31e897c1af928b34f173e5fecccb4 100644 --- a/VectoCore/Models/Connector/Ports/ITnOutPort.cs +++ b/VectoCore/Models/Connector/Ports/ITnOutPort.cs @@ -1,18 +1,17 @@ using System; -using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface ITnOutPort : ITnPort, IOutPort - { - /// <summary> - /// Requests the Outport with the given torque [Nm] and angularVelocity [rad/s]. - /// </summary> - /// <param name="absTime">[s]</param> - /// <param name="dt">[s]</param> - /// <param name="torque">[Nm]</param> - /// <param name="angularVelocity">[rad/s]</param> - IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularVelocity); - } + public interface ITnOutPort : ITnPort, IOutPort + { + /// <summary> + /// Requests the Outport with the given torque [Nm] and angularVelocity [rad/s]. + /// </summary> + /// <param name="absTime">[s]</param> + /// <param name="dt">[s]</param> + /// <param name="torque">[Nm]</param> + /// <param name="angularVelocity">[rad/s]</param> + IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularVelocity); + } } \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/ITnPort.cs b/VectoCore/Models/Connector/Ports/ITnPort.cs index 6a7f19111f65ab6e31604f1d34c3cdb7bf791850..af3861a9fe72bd748543b50dd04fab3a408c2436 100644 --- a/VectoCore/Models/Connector/Ports/ITnPort.cs +++ b/VectoCore/Models/Connector/Ports/ITnPort.cs @@ -1,6 +1,4 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { - public interface ITnPort - { - } -} + public interface ITnPort {} +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/Impl/InPort.cs b/VectoCore/Models/Connector/Ports/Impl/InPort.cs index 233304028eefd6baaf137b9f68b4e1b5fc240c95..83d8755e0a8edcc5ed63acca1deafffa11556138 100644 --- a/VectoCore/Models/Connector/Ports/Impl/InPort.cs +++ b/VectoCore/Models/Connector/Ports/Impl/InPort.cs @@ -1,9 +1,7 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl { - public abstract class InPort: IInPort + public abstract class InPort : IInPort { public abstract void Connect(IOutPort other); - } - -} +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/Impl/OutPort.cs b/VectoCore/Models/Connector/Ports/Impl/OutPort.cs index d019d60b077fa041e9973343a3956f485f4d5b5e..6ece52e14c202dfcd2620754da5d03e254b9584d 100644 --- a/VectoCore/Models/Connector/Ports/Impl/OutPort.cs +++ b/VectoCore/Models/Connector/Ports/Impl/OutPort.cs @@ -1,6 +1,4 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl { - public abstract class OutPort: IOutPort - { - } -} + public abstract class OutPort : IOutPort {} +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/Impl/Response.cs b/VectoCore/Models/Connector/Ports/Impl/Response.cs index c49469e3a433a5332e6d7d13541d179367faf039..32d8dfd7227e5df03a8cbf8e2212924cf25e8a46 100644 --- a/VectoCore/Models/Connector/Ports/Impl/Response.cs +++ b/VectoCore/Models/Connector/Ports/Impl/Response.cs @@ -2,21 +2,14 @@ using System; namespace TUGraz.VectoCore.Models.Connector.Ports.Impl { - public class ResponseCycleFinished : IResponse - { + public class ResponseCycleFinished : IResponse {} - } + public class ResponseSuccess : IResponse {} - public class ResponseSuccess : IResponse - { - } + public class ResponseFailOverload : IResponse {} - public class ResponseFailOverload : IResponse - { - } - - public class ResponseFailTimeInterval : IResponse - { - public TimeSpan DeltaT { get; set; } - } + public class ResponseFailTimeInterval : IResponse + { + public TimeSpan DeltaT { get; set; } + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Cockpit/ICockpit.cs b/VectoCore/Models/Simulation/Cockpit/ICockpit.cs index 2491b684f305737a089da63e2ce4a90d521e8b66..543268a636b682e59f41ba4ad339adba6c34a229 100644 --- a/VectoCore/Models/Simulation/Cockpit/ICockpit.cs +++ b/VectoCore/Models/Simulation/Cockpit/ICockpit.cs @@ -1,7 +1,4 @@ namespace TUGraz.VectoCore.Models.Simulation.Cockpit { - public interface ICockpit : IGearboxCockpit, IEngineCockpit, IVehicleCockpit - { - - } + public interface ICockpit : IGearboxCockpit, IEngineCockpit, IVehicleCockpit {} } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Cockpit/IEngineCockpit.cs b/VectoCore/Models/Simulation/Cockpit/IEngineCockpit.cs index 750744a09c4276ff8c0d9b7f92baa8f5a9f2ed42..17cba3ee11a4f947737accd8929024d49d313143 100644 --- a/VectoCore/Models/Simulation/Cockpit/IEngineCockpit.cs +++ b/VectoCore/Models/Simulation/Cockpit/IEngineCockpit.cs @@ -4,9 +4,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Cockpit { public interface IEngineCockpit { - /// <summary> - /// [rad/s] - /// </summary> + /// <summary> + /// [rad/s] + /// </summary> RadianPerSecond EngineSpeed(); } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Data/IModalDataWriter.cs b/VectoCore/Models/Simulation/Data/IModalDataWriter.cs index 7959d333f5420fccd938033fb4e3802d7e5dd416..cd7ad3baa36951cbb7feaaa39ed227482c48d106 100644 --- a/VectoCore/Models/Simulation/Data/IModalDataWriter.cs +++ b/VectoCore/Models/Simulation/Data/IModalDataWriter.cs @@ -1,19 +1,19 @@ namespace TUGraz.VectoCore.Models.Simulation.Data { - public interface IModalDataWriter - { - /// <summary> - /// Indexer for fields of the DataWriter. Accesses the data of the current step. - /// </summary> - /// <param name="key"></param> - /// <returns></returns> - object this[ModalResultField key] { get; set; } + public interface IModalDataWriter + { + /// <summary> + /// Indexer for fields of the DataWriter. Accesses the data of the current step. + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + object this[ModalResultField key] { get; set; } - /// <summary> - /// Commits the data of the current simulation step. - /// </summary> - void CommitSimulationStep(); + /// <summary> + /// Commits the data of the current simulation step. + /// </summary> + void CommitSimulationStep(); - void Finish(); - } -} + void Finish(); + } +} \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Data/ModalDataWriter.cs b/VectoCore/Models/Simulation/Data/ModalDataWriter.cs index 91062a3c768f3b87b340f8e9be0403812be272c4..cfb75f2132f0c4a34ccce568f513c8997316f06d 100644 --- a/VectoCore/Models/Simulation/Data/ModalDataWriter.cs +++ b/VectoCore/Models/Simulation/Data/ModalDataWriter.cs @@ -3,36 +3,34 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Simulation.Data { - public class ModalDataWriter : IModalDataWriter - { - private ModalResults Data { get; set; } + public class ModalDataWriter : IModalDataWriter + { + public ModalDataWriter(string fileName) + { + FileName = fileName; + Data = new ModalResults(); + CurrentRow = Data.NewRow(); + } - private DataRow CurrentRow { get; set; } + private ModalResults Data { get; set; } + private DataRow CurrentRow { get; set; } + public string FileName { get; set; } - public ModalDataWriter(string fileName) - { - FileName = fileName; - Data = new ModalResults(); - CurrentRow = Data.NewRow(); - } + public void CommitSimulationStep() + { + Data.Rows.Add(CurrentRow); + CurrentRow = Data.NewRow(); + } - public string FileName { get; set; } + public void Finish() + { + VectoCSVFile.Write(FileName, Data); + } - public void CommitSimulationStep() - { - Data.Rows.Add(CurrentRow); - CurrentRow = Data.NewRow(); - } - - public void Finish() - { - VectoCSVFile.Write(FileName, Data); - } - - public object this[ModalResultField key] - { - get { return CurrentRow[(int)key]; } - set { CurrentRow[(int)key] = value; } - } - } + public object this[ModalResultField key] + { + get { return CurrentRow[(int) key]; } + set { CurrentRow[(int) key] = value; } + } + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Data/ModalResult.cs b/VectoCore/Models/Simulation/Data/ModalResult.cs index 2410eb6ff99c42d8c4534d3dd9b3cf68ea93877b..a8d6ec2f6f81abf3880cd53193b9285829e30e9e 100644 --- a/VectoCore/Models/Simulation/Data/ModalResult.cs +++ b/VectoCore/Models/Simulation/Data/ModalResult.cs @@ -8,330 +8,289 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Simulation.Data { - [SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")] - [DesignerCategory("")] // Full qualified attribute needed to disable design view in VisualStudio - public class ModalResults : DataTable - { - public ModalResults() - { - foreach (ModalResultField value in Enum.GetValues(typeof(ModalResultField))) - { - var col = new DataColumn(value.GetName(), value.GetDataType()) { Caption = value.GetCaption() }; - Columns.Add(col); - } - } - - public static ModalResults ReadFromFile(string fileName) - { - var modalResults = new ModalResults(); - var data = VectoCSVFile.Read(fileName); - - foreach (DataRow row in data.Rows) - { - try - { - var newRow = modalResults.NewRow(); - foreach (DataColumn col in row.Table.Columns) - { - // In cols FC-AUXc and FC-WHTCc can be a "-" - if (row.Field<string>(col) == "-" - && (col.ColumnName == ModalResultField.FCAUXc.GetName() || col.ColumnName == ModalResultField.FCWHTCc.GetName())) - continue; - - // In col FC can sometimes be a "ERROR" - if (row.Field<string>(col) == "ERROR" && col.ColumnName == ModalResultField.FC.GetName()) - continue; - - newRow.SetField(col.ColumnName, row.ParseDoubleOrGetDefault(col.ColumnName)); - - } - modalResults.Rows.Add(newRow); - - } - catch (VectoException ex) - { - throw new VectoException(string.Format("Row {0}: {1}", data.Rows.IndexOf(row), ex.Message), ex); - } - } - - return modalResults; - } - - public void WriteToFile(string fileName) - { - VectoCSVFile.Write(fileName, this); - } - } - - /// <summary> - /// Enum with field definitions of the Modal Results File (.vmod). - /// </summary> - public enum ModalResultField - { - /// <summary> - /// Time step [s]. - /// Midpoint of the simulated interval. - /// </summary> - [ModalResultField(typeof(double), caption: "time [s]")] - time, - - /// <summary> - /// Simulation interval around the current time step. [s] - /// </summary> - [ModalResultField(typeof(double), name: "simulation_interval", caption: "simulation_interval [s]")] - simulationInterval, - - /// <summary> - /// Engine speed [1/min]. - /// </summary> - [ModalResultField(typeof(double), caption: "n [1/min]")] - n, - - /// <summary> - /// [Nm] Engine torque. - /// </summary> - [ModalResultField(typeof(double), caption: "Tq_eng [Nm]")] - Tq_eng, - - /// <summary> - /// [Nm] Torque at clutch (before clutch, engine-side) - /// </summary> - [ModalResultField(typeof(double), caption: "Tq_clutch [Nm]")] - Tq_clutch, - - /// <summary> - /// [Nm] Full load torque - /// </summary> - [ModalResultField(typeof(double), caption: "Tq_full [Nm]")] - Tq_full, - - /// <summary> - /// [Nm] Motoring torque - /// </summary> - [ModalResultField(typeof(double), caption: "Tq_drag [Nm]")] - Tq_drag, - - /// <summary> - /// [kW] Engine power. - /// </summary> - [ModalResultField(typeof(double), caption: "Pe_eng [kW]")] - Pe_eng, - - /// <summary> - /// [kW] Engine full load power. - /// </summary> - [ModalResultField(typeof(double), caption: "Pe_full [kW]")] - Pe_full, - - /// <summary> - /// [kW] Engine drag power. - /// </summary> - [ModalResultField(typeof(double), caption: "Pe_drag [kW]")] - Pe_drag, - - /// <summary> - /// [kW] Engine power at clutch (equals Pe minus loss due to rotational inertia Pa Eng). - /// </summary> - [ModalResultField(typeof(double), caption: "Pe_clutch [kW]")] - Pe_clutch, - - /// <summary> - /// [kW] Rotational acceleration power: Engine. - /// </summary> - [ModalResultField(typeof(double), name: "Pa", caption: "Pa [Eng]")] - PaEng, - - /// <summary> - /// [kW] Total auxiliary power demand . - /// </summary> - [ModalResultField(typeof(double), caption: "Paux [kW]")] - Paux, - - /// <summary> - /// [g/h] Fuel consumption from FC map.. - /// </summary> - [ModalResultField(typeof(double), caption: "FC [g/h]")] - FC, - - /// <summary> - /// [g/h] Fuel consumption after Auxiliary-Start/Stop Correction. (Based on FC.) - /// </summary> - [ModalResultField(typeof(double), name: "FC-AUXc", caption: "FC-AUXc [g/h]")] - FCAUXc, - - /// <summary> - /// [g/h] Fuel consumption after WHTC Correction. (Based on FC-AUXc.) - /// </summary> - [ModalResultField(typeof(double), name: "FC-WHTCc", caption: "FC-WHTCc [g/h]")] - FCWHTCc, - - /// <summary> - /// [km] Travelled distance. - /// </summary> - [ModalResultField(typeof(double))] - dist, - - /// <summary> - /// [km/h] Actual vehicle speed. - /// </summary> - [ModalResultField(typeof(double))] - v_act, - - /// <summary> - /// [km/h] Target vehicle speed. - /// </summary> - [ModalResultField(typeof(double))] - v_targ, - - /// <summary> - /// [m/s2] Vehicle acceleration. - /// </summary> - [ModalResultField(typeof(double))] - acc, - - /// <summary> - /// [%] Road gradient. - /// </summary> - [ModalResultField(typeof(double))] - grad, - - /// <summary> - /// [-] Gear. "0" = clutch opened / neutral. "0.5" = lock-up clutch is open (AT with torque converter only, see Gearbox) - /// </summary> - [ModalResultField(typeof(double))] - Gear, - - /// <summary> - /// [kW] Gearbox losses. - /// </summary> - [ModalResultField(typeof(double), name: "Ploss GB")] - PlossGB, - - /// <summary> - /// [kW] Losses in differential / axle transmission. - /// </summary> - [ModalResultField(typeof(double), name: "Ploss Diff")] - PlossDiff, - - /// <summary> - /// [kW] Retarder losses. - /// </summary> - [ModalResultField(typeof(double), name: "Ploss Retarder")] - PlossRetarder, - - /// <summary> - /// [kW] Rotational acceleration power: Gearbox. - /// </summary> - [ModalResultField(typeof(double), name: "Pa GB")] - PaGB, - - /// <summary> - /// [kW] Vehicle acceleration power. - /// </summary> - [ModalResultField(typeof(double), name: "Pa Veh")] - PaVeh, - - /// <summary> - /// [kW] Rolling resistance power demand. - /// </summary> - [ModalResultField(typeof(double))] - Proll, - - /// <summary> - /// [kW] Air resistance power demand. - /// </summary> - [ModalResultField(typeof(double))] - Pair, - - /// <summary> - /// [kW] Power demand due to road gradient. - /// </summary> - [ModalResultField(typeof(double))] - Pgrad, - - /// <summary> - /// [kW] Total power demand at wheel = sum of rolling, air, acceleration and road gradient resistance. - /// </summary> - [ModalResultField(typeof(double))] - Pwheel, - - /// <summary> - /// [kW] Brake power. Drag power is included in Pe. - /// </summary> - [ModalResultField(typeof(double))] - Pbrake, - - /// <summary> - /// [kW] Power demand of Auxiliary with ID xxx. See also Aux Dialog and Driving Cycle. - /// </summary> - [ModalResultField(typeof(double))] - Paux_xxx, - - /// <summary> - /// [-] Torque converter speed ratio - /// </summary> - [ModalResultField(typeof(double))] - TCν, - - /// <summary> - /// [-] Torque converter torque ratio - /// </summary> - [ModalResultField(typeof(double), name: "TCµ")] - TCmu, - - /// <summary> - /// [Nm] Torque converter output torque - /// </summary> - [ModalResultField(typeof(double))] - TC_M_Out, - - /// <summary> - /// [1/min] Torque converter output speed - /// </summary> - [ModalResultField(typeof(double))] - TC_n_Out - } - - - [AttributeUsage(AttributeTargets.Field)] - class ModalResultFieldAttribute : Attribute - { - public Type FieldType { get; private set; } - public string Name { get; private set; } - public string Caption { get; set; } - internal ModalResultFieldAttribute(Type fieldType, string name = null, string caption = null) - { - FieldType = fieldType; - Name = name; - Caption = caption; - } - } - - public static class ModalResultFieldExtensionMethods - { - public static Type GetDataType(this ModalResultField field) - { - return GetAttr(field).FieldType; - } - - public static string GetName(this ModalResultField field) - { - return GetAttr(field).Name ?? field.ToString(); - } - - public static string GetCaption(this ModalResultField field) - { - return GetAttr(field).Caption ?? field.GetName() ?? field.ToString(); - } - - private static ModalResultFieldAttribute GetAttr(ModalResultField field) - { - return (ModalResultFieldAttribute)Attribute.GetCustomAttribute(ForValue(field), typeof(ModalResultFieldAttribute)); - } - - private static MemberInfo ForValue(ModalResultField field) - { - return typeof(ModalResultField).GetField(Enum.GetName(typeof(ModalResultField), field)); - } - } -} + [SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")] + [DesignerCategory("")] // Full qualified attribute needed to disable design view in VisualStudio + public class ModalResults : DataTable + { + public ModalResults() + { + foreach (ModalResultField value in Enum.GetValues(typeof (ModalResultField))) { + var col = new DataColumn(value.GetName(), value.GetDataType()) {Caption = value.GetCaption()}; + Columns.Add(col); + } + } + + public static ModalResults ReadFromFile(string fileName) + { + var modalResults = new ModalResults(); + var data = VectoCSVFile.Read(fileName); + + foreach (DataRow row in data.Rows) { + try { + var newRow = modalResults.NewRow(); + foreach (DataColumn col in row.Table.Columns) { + // In cols FC-AUXc and FC-WHTCc can be a "-" + if (row.Field<string>(col) == "-" + && (col.ColumnName == ModalResultField.FCAUXc.GetName() || col.ColumnName == ModalResultField.FCWHTCc.GetName())) { + continue; + } + + // In col FC can sometimes be a "ERROR" + if (row.Field<string>(col) == "ERROR" && col.ColumnName == ModalResultField.FC.GetName()) { + continue; + } + + newRow.SetField(col.ColumnName, row.ParseDoubleOrGetDefault(col.ColumnName)); + } + modalResults.Rows.Add(newRow); + } catch (VectoException ex) { + throw new VectoException(string.Format("Row {0}: {1}", data.Rows.IndexOf(row), ex.Message), ex); + } + } + + return modalResults; + } + + public void WriteToFile(string fileName) + { + VectoCSVFile.Write(fileName, this); + } + } + + /// <summary> + /// Enum with field definitions of the Modal Results File (.vmod). + /// </summary> + public enum ModalResultField + { + /// <summary> + /// Time step [s]. + /// Midpoint of the simulated interval. + /// </summary> + [ModalResultField(typeof (double), caption: "time [s]")] time, + + /// <summary> + /// Simulation interval around the current time step. [s] + /// </summary> + [ModalResultField(typeof (double), "simulation_interval", "simulation_interval [s]")] simulationInterval, + + /// <summary> + /// Engine speed [1/min]. + /// </summary> + [ModalResultField(typeof (double), caption: "n [1/min]")] n, + + /// <summary> + /// [Nm] Engine torque. + /// </summary> + [ModalResultField(typeof (double), caption: "Tq_eng [Nm]")] Tq_eng, + + /// <summary> + /// [Nm] Torque at clutch (before clutch, engine-side) + /// </summary> + [ModalResultField(typeof (double), caption: "Tq_clutch [Nm]")] Tq_clutch, + + /// <summary> + /// [Nm] Full load torque + /// </summary> + [ModalResultField(typeof (double), caption: "Tq_full [Nm]")] Tq_full, + + /// <summary> + /// [Nm] Motoring torque + /// </summary> + [ModalResultField(typeof (double), caption: "Tq_drag [Nm]")] Tq_drag, + + /// <summary> + /// [kW] Engine power. + /// </summary> + [ModalResultField(typeof (double), caption: "Pe_eng [kW]")] Pe_eng, + + /// <summary> + /// [kW] Engine full load power. + /// </summary> + [ModalResultField(typeof (double), caption: "Pe_full [kW]")] Pe_full, + + /// <summary> + /// [kW] Engine drag power. + /// </summary> + [ModalResultField(typeof (double), caption: "Pe_drag [kW]")] Pe_drag, + + /// <summary> + /// [kW] Engine power at clutch (equals Pe minus loss due to rotational inertia Pa Eng). + /// </summary> + [ModalResultField(typeof (double), caption: "Pe_clutch [kW]")] Pe_clutch, + + /// <summary> + /// [kW] Rotational acceleration power: Engine. + /// </summary> + [ModalResultField(typeof (double), "Pa", "Pa [Eng]")] PaEng, + + /// <summary> + /// [kW] Total auxiliary power demand . + /// </summary> + [ModalResultField(typeof (double), caption: "Paux [kW]")] Paux, + + /// <summary> + /// [g/h] Fuel consumption from FC map.. + /// </summary> + [ModalResultField(typeof (double), caption: "FC [g/h]")] FC, + + /// <summary> + /// [g/h] Fuel consumption after Auxiliary-Start/Stop Correction. (Based on FC.) + /// </summary> + [ModalResultField(typeof (double), "FC-AUXc", "FC-AUXc [g/h]")] FCAUXc, + + /// <summary> + /// [g/h] Fuel consumption after WHTC Correction. (Based on FC-AUXc.) + /// </summary> + [ModalResultField(typeof (double), "FC-WHTCc", "FC-WHTCc [g/h]")] FCWHTCc, + + /// <summary> + /// [km] Travelled distance. + /// </summary> + [ModalResultField(typeof (double))] dist, + + /// <summary> + /// [km/h] Actual vehicle speed. + /// </summary> + [ModalResultField(typeof (double))] v_act, + + /// <summary> + /// [km/h] Target vehicle speed. + /// </summary> + [ModalResultField(typeof (double))] v_targ, + + /// <summary> + /// [m/s2] Vehicle acceleration. + /// </summary> + [ModalResultField(typeof (double))] acc, + + /// <summary> + /// [%] Road gradient. + /// </summary> + [ModalResultField(typeof (double))] grad, + + /// <summary> + /// [-] Gear. "0" = clutch opened / neutral. "0.5" = lock-up clutch is open (AT with torque converter only, see + /// Gearbox) + /// </summary> + [ModalResultField(typeof (double))] Gear, + + /// <summary> + /// [kW] Gearbox losses. + /// </summary> + [ModalResultField(typeof (double), "Ploss GB")] PlossGB, + + /// <summary> + /// [kW] Losses in differential / axle transmission. + /// </summary> + [ModalResultField(typeof (double), "Ploss Diff")] PlossDiff, + + /// <summary> + /// [kW] Retarder losses. + /// </summary> + [ModalResultField(typeof (double), "Ploss Retarder")] PlossRetarder, + + /// <summary> + /// [kW] Rotational acceleration power: Gearbox. + /// </summary> + [ModalResultField(typeof (double), "Pa GB")] PaGB, + + /// <summary> + /// [kW] Vehicle acceleration power. + /// </summary> + [ModalResultField(typeof (double), "Pa Veh")] PaVeh, + + /// <summary> + /// [kW] Rolling resistance power demand. + /// </summary> + [ModalResultField(typeof (double))] Proll, + + /// <summary> + /// [kW] Air resistance power demand. + /// </summary> + [ModalResultField(typeof (double))] Pair, + + /// <summary> + /// [kW] Power demand due to road gradient. + /// </summary> + [ModalResultField(typeof (double))] Pgrad, + + /// <summary> + /// [kW] Total power demand at wheel = sum of rolling, air, acceleration and road gradient resistance. + /// </summary> + [ModalResultField(typeof (double))] Pwheel, + + /// <summary> + /// [kW] Brake power. Drag power is included in Pe. + /// </summary> + [ModalResultField(typeof (double))] Pbrake, + + /// <summary> + /// [kW] Power demand of Auxiliary with ID xxx. See also Aux Dialog and Driving Cycle. + /// </summary> + [ModalResultField(typeof (double))] Paux_xxx, + + /// <summary> + /// [-] Torque converter speed ratio + /// </summary> + [ModalResultField(typeof (double))] TCν, + + /// <summary> + /// [-] Torque converter torque ratio + /// </summary> + [ModalResultField(typeof (double), "TCµ")] TCmu, + + /// <summary> + /// [Nm] Torque converter output torque + /// </summary> + [ModalResultField(typeof (double))] TC_M_Out, + + /// <summary> + /// [1/min] Torque converter output speed + /// </summary> + [ModalResultField(typeof (double))] TC_n_Out + } + + + [AttributeUsage(AttributeTargets.Field)] + internal class ModalResultFieldAttribute : Attribute + { + internal ModalResultFieldAttribute(Type fieldType, string name = null, string caption = null) + { + FieldType = fieldType; + Name = name; + Caption = caption; + } + + public Type FieldType { get; private set; } + public string Name { get; private set; } + public string Caption { get; set; } + } + + public static class ModalResultFieldExtensionMethods + { + public static Type GetDataType(this ModalResultField field) + { + return GetAttr(field).FieldType; + } + + public static string GetName(this ModalResultField field) + { + return GetAttr(field).Name ?? field.ToString(); + } + + public static string GetCaption(this ModalResultField field) + { + return GetAttr(field).Caption ?? field.GetName() ?? field.ToString(); + } + + private static ModalResultFieldAttribute GetAttr(ModalResultField field) + { + return (ModalResultFieldAttribute) Attribute.GetCustomAttribute(ForValue(field), typeof (ModalResultFieldAttribute)); + } + + private static MemberInfo ForValue(ModalResultField field) + { + return typeof (ModalResultField).GetField(Enum.GetName(typeof (ModalResultField), field)); + } + } +} \ No newline at end of file diff --git a/VectoCore/Models/Simulation/IVectoSimulator.cs b/VectoCore/Models/Simulation/IVectoSimulator.cs index e4c46f9e681001fdbfdb6cf1335584f78e65f52b..71e3cc5741e87757bb1193d472b10b670759efe1 100644 --- a/VectoCore/Models/Simulation/IVectoSimulator.cs +++ b/VectoCore/Models/Simulation/IVectoSimulator.cs @@ -1,11 +1,8 @@ -using TUGraz.VectoCore.Models.Simulation.Impl; - namespace TUGraz.VectoCore.Models.Simulation { - public interface IVectoSimulator - { - void Run(); - - IVehicleContainer GetContainer(); - } + public interface IVectoSimulator + { + void Run(); + IVehicleContainer GetContainer(); + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/IVehicleContainer.cs b/VectoCore/Models/Simulation/IVehicleContainer.cs index d242729e24a8c63c97ab3c133c725c0285d7e2bd..fa7422d031bab8717eb332ee622cc3116f081882 100644 --- a/VectoCore/Models/Simulation/IVehicleContainer.cs +++ b/VectoCore/Models/Simulation/IVehicleContainer.cs @@ -4,10 +4,10 @@ using TUGraz.VectoCore.Models.SimulationComponent; namespace TUGraz.VectoCore.Models.Simulation { - public interface IVehicleContainer : ICockpit - { - void AddComponent(VectoSimulationComponent component); - void CommitSimulationStep(IModalDataWriter dataWriter); - void FinishSimulation(IModalDataWriter dataWriter); - } + public interface IVehicleContainer : ICockpit + { + void AddComponent(VectoSimulationComponent component); + void CommitSimulationStep(IModalDataWriter dataWriter); + void FinishSimulation(IModalDataWriter dataWriter); + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/JobContainer.cs b/VectoCore/Models/Simulation/Impl/JobContainer.cs index bf0e750d3539dc9fdd78c4897ebfb7ed38287623..74d91913360e76391e6f9055e4514ea5c7e1639d 100644 --- a/VectoCore/Models/Simulation/Impl/JobContainer.cs +++ b/VectoCore/Models/Simulation/Impl/JobContainer.cs @@ -5,21 +5,21 @@ using Common.Logging; namespace TUGraz.VectoCore.Models.Simulation.Impl { - //todo: add job tracking (state of jobs, iteration, ...) - //todo: add job control (pause, stop) - public class JobContainer - { - private List<IVectoSimulator> _simulators = new List<IVectoSimulator>(); + //todo: add job tracking (state of jobs, iteration, ...) + //todo: add job control (pause, stop) + public class JobContainer + { + private readonly List<IVectoSimulator> _simulators = new List<IVectoSimulator>(); - public void AddJob(IVectoSimulator sim) - { - _simulators.Add(sim); - } + public void AddJob(IVectoSimulator sim) + { + _simulators.Add(sim); + } - public void RunSimulation() - { - LogManager.GetLogger(GetType()).Info("VectoSimulator started running. Starting Jobs."); - Task.WaitAll(_simulators.Select(job => Task.Factory.StartNew(job.Run)).ToArray()); - } - } + public void RunSimulation() + { + LogManager.GetLogger(GetType()).Info("VectoSimulator started running. Starting Jobs."); + Task.WaitAll(_simulators.Select(job => Task.Factory.StartNew(job.Run)).ToArray()); + } + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index f64d88f4569560ca71a9a0d30e9b81b0b11c7d6f..17e5fff0935b348c3c358d6800acf4cf57d93a78 100644 --- a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs +++ b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -6,28 +6,28 @@ using TUGraz.VectoCore.Models.SimulationComponent.Impl; namespace TUGraz.VectoCore.Models.Simulation.Impl { - public class SimulatorFactory - { - public static IVectoSimulator CreateTimeBasedEngineOnlyJob(string engineFile, string cycleFile, string resultFile) - { - Action<string> debug = LogManager.GetLogger<SimulatorFactory>().Debug; + public class SimulatorFactory + { + public static IVectoSimulator CreateTimeBasedEngineOnlyJob(string engineFile, string cycleFile, string resultFile) + { + Action<string> debug = LogManager.GetLogger<SimulatorFactory>().Debug; - debug("Creating VehicleContainer."); - var container = new VehicleContainer(); + debug("Creating VehicleContainer."); + var container = new VehicleContainer(); debug("SimulationFactory creating cycle."); var cycleData = DrivingCycleData.ReadFromFileEngineOnly(cycleFile); var cycle = new EngineOnlyDrivingCycle(container, cycleData); - + debug("SimulationFactory creating engine."); - var engineData = CombustionEngineData.ReadFromFile(engineFile); - var engine = new CombustionEngine(container, engineData); + var engineData = CombustionEngineData.ReadFromFile(engineFile); + var engine = new CombustionEngine(container, engineData); - debug("Creating gearbox."); - var gearBox = new EngineOnlyGearbox(container); + debug("Creating gearbox."); + var gearBox = new EngineOnlyGearbox(container); debug("SimulationFactory creating auxiliary"); - var aux = new EngineOnlyAuxiliary(container, new AuxiliariesDemandAdapter(cycleData)); + var aux = new EngineOnlyAuxiliary(container, new AuxiliariesDemandAdapter(cycleData)); debug("SimulationFactory connecting auxiliary with engine."); aux.Connect(engine.OutShaft()); @@ -35,15 +35,15 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl debug("SimulationFactory connecting gearbox with auxiliary."); gearBox.InShaft().Connect(aux.OutShaft()); - debug("SimulationFactory connecting cycle with gearbox."); - cycle.InShaft().Connect(gearBox.OutShaft()); + debug("SimulationFactory connecting cycle with gearbox."); + cycle.InShaft().Connect(gearBox.OutShaft()); - var dataWriter = new ModalDataWriter(resultFile); + var dataWriter = new ModalDataWriter(resultFile); - debug("Creating Simulator."); - var simulator = new VectoSimulator(container, cycle, dataWriter); + debug("Creating Simulator."); + var simulator = new VectoSimulator(container, cycle, dataWriter); - return simulator; - } - } + return simulator; + } + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/VectoSimulator.cs b/VectoCore/Models/Simulation/Impl/VectoSimulator.cs index 5d8f074866a6cfb2ac92a12dbd54ad8242a38abb..3c551a88aeff860518b3cc91f5c2a4f15036cb86 100644 --- a/VectoCore/Models/Simulation/Impl/VectoSimulator.cs +++ b/VectoCore/Models/Simulation/Impl/VectoSimulator.cs @@ -1,6 +1,5 @@ using System; using Common.Logging; -using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation.Data; @@ -8,59 +7,58 @@ using TUGraz.VectoCore.Models.SimulationComponent; namespace TUGraz.VectoCore.Models.Simulation.Impl { - public class VectoSimulator : IVectoSimulator - { - private TimeSpan _absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); - private TimeSpan _dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); + public class VectoSimulator : IVectoSimulator + { + private TimeSpan _absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); + private TimeSpan _dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); - protected IDrivingCycle Cycle { get; set; } - protected IModalDataWriter DataWriter { get; set; } - protected IVehicleContainer Container { get; set; } + public VectoSimulator(IVehicleContainer container, IDrivingCycle cycle, IModalDataWriter dataWriter) + { + Container = container; + Cycle = cycle; + DataWriter = dataWriter; + } - public IVehicleContainer GetContainer() - { - return Container; - } + protected IDrivingCycle Cycle { get; set; } + protected IModalDataWriter DataWriter { get; set; } + protected IVehicleContainer Container { get; set; } - public VectoSimulator(IVehicleContainer container, IDrivingCycle cycle, IModalDataWriter dataWriter) - { - Container = container; - Cycle = cycle; - DataWriter = dataWriter; - } + public IVehicleContainer GetContainer() + { + return Container; + } - public void Run() - { - LogManager.GetLogger(GetType()).Info("VectoJob started running."); - IResponse response; - do - { - response = Cycle.Request(_absTime, _dt); - while (response is ResponseFailTimeInterval) - { - _dt = (response as ResponseFailTimeInterval).DeltaT; - response = Cycle.Request(_absTime, _dt); - } + public void Run() + { + LogManager.GetLogger(GetType()).Info("VectoJob started running."); + IResponse response; + do { + response = Cycle.Request(_absTime, _dt); + while (response is ResponseFailTimeInterval) { + _dt = (response as ResponseFailTimeInterval).DeltaT; + response = Cycle.Request(_absTime, _dt); + } - if (response is ResponseCycleFinished) - break; + if (response is ResponseCycleFinished) { + break; + } - DataWriter[ModalResultField.time] = (_absTime + TimeSpan.FromTicks(_dt.Ticks / 2)).TotalSeconds; - DataWriter[ModalResultField.simulationInterval] = _dt.TotalSeconds; + DataWriter[ModalResultField.time] = (_absTime + TimeSpan.FromTicks(_dt.Ticks / 2)).TotalSeconds; + DataWriter[ModalResultField.simulationInterval] = _dt.TotalSeconds; - Container.CommitSimulationStep(DataWriter); + Container.CommitSimulationStep(DataWriter); - // set _dt to difference to next full second. - _absTime += _dt; - _dt = TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(_dt.Milliseconds); - } while (response is ResponseSuccess); + // set _dt to difference to next full second. + _absTime += _dt; + _dt = TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(_dt.Milliseconds); + } while (response is ResponseSuccess); - Container.FinishSimulation(DataWriter); + Container.FinishSimulation(DataWriter); - //todo: write vsum file + //todo: write vsum file - LogManager.GetLogger(GetType()).Info("VectoJob finished."); - } - } + LogManager.GetLogger(GetType()).Info("VectoJob finished."); + } + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/VehicleContainer.cs b/VectoCore/Models/Simulation/Impl/VehicleContainer.cs index b0a9362ff1204464bf85a4e2afd105f4f5508d8f..1e9da44a3ef1029d8aab7203a20739684c185c1a 100644 --- a/VectoCore/Models/Simulation/Impl/VehicleContainer.cs +++ b/VectoCore/Models/Simulation/Impl/VehicleContainer.cs @@ -9,74 +9,84 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Simulation.Impl { - public class VehicleContainer : IVehicleContainer - { - private readonly IList<VectoSimulationComponent> _components = new List<VectoSimulationComponent>(); - private IEngineCockpit _engine; - private IGearboxCockpit _gearbox; - - #region IVehicleContainer - - public virtual void AddComponent(VectoSimulationComponent component) - { - _components.Add(component); - - // TODO: refactor the following to use polymorphism? - var engine = component as IEngineCockpit; - if (engine != null) - _engine = engine; - - var gearbox = component as IGearboxCockpit; - if (gearbox != null) - _gearbox = gearbox; - } - - - public void CommitSimulationStep(IModalDataWriter dataWriter) - { - LogManager.GetLogger(GetType()).Info("VehicleContainer committing simulation."); - foreach (var component in _components) - { - component.CommitSimulationStep(dataWriter); - } - dataWriter.CommitSimulationStep(); - } - - public void FinishSimulation(IModalDataWriter dataWriter) - { - LogManager.GetLogger(GetType()).Info("VehicleContainer finishing simulation."); - dataWriter.Finish(); - } - #endregion - - #region IGearCockpit - public uint Gear() - { - if (_gearbox == null) - throw new VectoException("no gearbox available!"); - return _gearbox.Gear(); - } - #endregion - - #region IEngineCockpit - public RadianPerSecond EngineSpeed() - { - if (_engine == null) - throw new VectoException("no engine available!"); - return _engine.EngineSpeed(); - } - #endregion - - #region IVehicleCockpit - public double VehicleSpeed() - { - throw new VectoException("no vehicle available!"); - } - #endregion - - public IReadOnlyCollection<VectoSimulationComponent> SimulationComponents() - { - return new ReadOnlyCollection<VectoSimulationComponent>(_components); - } - } -} + public class VehicleContainer : IVehicleContainer + { + private readonly IList<VectoSimulationComponent> _components = new List<VectoSimulationComponent>(); + private IEngineCockpit _engine; + private IGearboxCockpit _gearbox; + + #region IGearCockpit + + public uint Gear() + { + if (_gearbox == null) { + throw new VectoException("no gearbox available!"); + } + return _gearbox.Gear(); + } + + #endregion + + #region IEngineCockpit + + public RadianPerSecond EngineSpeed() + { + if (_engine == null) { + throw new VectoException("no engine available!"); + } + return _engine.EngineSpeed(); + } + + #endregion + + #region IVehicleCockpit + + public double VehicleSpeed() + { + throw new VectoException("no vehicle available!"); + } + + #endregion + + public IReadOnlyCollection<VectoSimulationComponent> SimulationComponents() + { + return new ReadOnlyCollection<VectoSimulationComponent>(_components); + } + + #region IVehicleContainer + + public virtual void AddComponent(VectoSimulationComponent component) + { + _components.Add(component); + + // TODO: refactor the following to use polymorphism? + var engine = component as IEngineCockpit; + if (engine != null) { + _engine = engine; + } + + var gearbox = component as IGearboxCockpit; + if (gearbox != null) { + _gearbox = gearbox; + } + } + + + public void CommitSimulationStep(IModalDataWriter dataWriter) + { + LogManager.GetLogger(GetType()).Info("VehicleContainer committing simulation."); + foreach (var component in _components) { + component.CommitSimulationStep(dataWriter); + } + dataWriter.CommitSimulationStep(); + } + + public void FinishSimulation(IModalDataWriter dataWriter) + { + LogManager.GetLogger(GetType()).Info("VehicleContainer finishing simulation."); + dataWriter.Finish(); + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/AuxiliariesDemandAdapter.cs b/VectoCore/Models/SimulationComponent/Data/AuxiliariesDemandAdapter.cs index e529511241ab74124aea69c7f31b1195e20ea820..d84c0b207d21f8121e8607bdebb3bc54ac9c1352 100644 --- a/VectoCore/Models/SimulationComponent/Data/AuxiliariesDemandAdapter.cs +++ b/VectoCore/Models/SimulationComponent/Data/AuxiliariesDemandAdapter.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography.X509Certificates; using Common.Logging; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Utils; @@ -10,18 +9,16 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data { public class AuxiliariesDemandAdapter { - private readonly DrivingCycleData _drivingCycle; - private IEnumerator<DrivingCycleData.DrivingCycleEntry> _nextCycleEntry; private readonly string _auxiliaryId; - - protected DrivingCycleData.DrivingCycleEntry CurrentCycleEntry { get; set; } + private readonly DrivingCycleData _drivingCycle; + private readonly IEnumerator<DrivingCycleData.DrivingCycleEntry> _nextCycleEntry; //protected DrivingCycleData.DrivingCycleEntry NextCycleEntry { get { return _nextCycleEntry.Current; } } - private ILog Log; + private readonly ILog Log; public AuxiliariesDemandAdapter(DrivingCycleData inputData, string column = null) { - Log = LogManager.GetLogger(this.GetType()); + Log = LogManager.GetLogger(GetType()); _drivingCycle = inputData; _nextCycleEntry = _drivingCycle.Entries.GetEnumerator(); _nextCycleEntry.MoveNext(); @@ -33,14 +30,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data } } + protected DrivingCycleData.DrivingCycleEntry CurrentCycleEntry { get; set; } + public Watt GetPowerDemand(TimeSpan absTime, TimeSpan dt) { if (_nextCycleEntry.Current.Time <= absTime.TotalSeconds) { CurrentCycleEntry = _nextCycleEntry.Current; _nextCycleEntry.MoveNext(); } - return String.IsNullOrEmpty(_auxiliaryId) ? CurrentCycleEntry.AdditionalAuxPowerDemand : CurrentCycleEntry.AuxiliarySupplyPower[_auxiliaryId]; + return String.IsNullOrEmpty(_auxiliaryId) + ? CurrentCycleEntry.AdditionalAuxPowerDemand + : CurrentCycleEntry.AuxiliarySupplyPower[_auxiliaryId]; } - } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs b/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs index 42e3d3b31f267508b9bc5954a448419b0c3715ad..6d61a3aa5722158fe84369a5c57c050ee0ae80fb 100644 --- a/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs +++ b/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs @@ -13,486 +13,493 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { - /// <summary> - /// Represents the CombustionEngineData. Fileformat: .veng - /// </summary> - /// <code> - /// { - /// "Header": { - /// "CreatedBy": " ()", - /// "Date": "3/4/2015 12:26:24 PM", - /// "AppVersion": "2.0.4-beta3", - /// "FileVersion": 2 - /// }, - /// "Body": { - /// "SavedInDeclMode": false, - /// "ModelName": "Generic 24t Coach", - /// "Displacement": 12730.0, - /// "IdlingSpeed": 560.0, - /// "Inertia": 3.8, - /// "FullLoadCurves": [ - /// { - /// "Path": "24t Coach.vfld", - /// "Gears": "0 - 99" - /// } - /// ], - /// "FuelMap": "24t Coach.vmap", - /// "WHTC-Urban": 0.0, - /// "WHTC-Rural": 0.0, - /// "WHTC-Motorway": 0.0 - /// } - /// } - /// </code> - [DataContract] - public class CombustionEngineData : SimulationComponentData - { - /// <summary> - /// A class which represents the json data format for serializing and deserializing the EngineData files. - /// </summary> - public class Data - { - public class DataHeader - { - [JsonProperty(Required = Required.Always)] - public string CreatedBy; - - [JsonProperty(Required = Required.Always)] - public DateTime Date; - - [JsonProperty(Required = Required.Always)] - public string AppVersion; - - [JsonProperty(Required = Required.Always)] - public double FileVersion; - - #region Equality members - - protected bool Equals(DataHeader other) - { - return string.Equals(CreatedBy, other.CreatedBy) && Date.Equals(other.Date) && - string.Equals(AppVersion, other.AppVersion) && FileVersion.Equals(other.FileVersion); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((DataHeader)obj); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = (CreatedBy != null ? CreatedBy.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ Date.GetHashCode(); - hashCode = (hashCode * 397) ^ (AppVersion != null ? AppVersion.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ FileVersion.GetHashCode(); - return hashCode; - } - } - - #endregion - } - - [JsonProperty(Required = Required.Always)] - public DataHeader Header; - - public class DataBody - { - [JsonProperty("SavedInDeclMode")] - public bool SavedInDeclarationMode; - - /// <summary> - /// Model. Free text defining the engine model, type, etc. - /// </summary> - [JsonProperty(Required = Required.Always)] - public string ModelName; - - /// <summary> - /// [ccm] Displacement in cubic centimeter. - /// Used in Declaration Mode to calculate inertia. - /// </summary> - [JsonProperty(Required = Required.Always)] - public double Displacement; - - /// <summary> - /// [rpm] Idling Engine Speed - /// Low idle, applied in simulation for vehicle standstill in neutral gear position. - /// </summary> - [JsonProperty("IdlingSpeed", Required = Required.Always)] - public double IdleSpeed; - - /// <summary> - /// [kgm^2] Inertia including Flywheel - /// Inertia for rotating parts including engine flywheel. - /// In Declaration Mode the inertia is calculated automatically. - /// </summary> - [JsonProperty(Required = Required.Always)] - public double Inertia; - - /// <summary> - /// Multiple Full Load and Drag Curves (.vfld) can be defined and assigned to different gears. - /// Gear "0" must be assigned for idling and Engine Only Mode. - /// </summary> - public class DataFullLoadCurve - { - [JsonProperty(Required = Required.Always)] - public string Path; - - [JsonProperty(Required = Required.Always)] - public string Gears; - - #region Equality Members - - protected bool Equals(DataFullLoadCurve other) - { - return string.Equals(Path, other.Path) && string.Equals(Gears, other.Gears); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((DataFullLoadCurve)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((Path != null ? Path.GetHashCode() : 0) * 397) ^ - (Gears != null ? Gears.GetHashCode() : 0); - } - } - - #endregion - } - - [JsonProperty(Required = Required.Always)] - public IList<DataFullLoadCurve> FullLoadCurves; - - /// <summary> - /// The Fuel Consumption Map is used to calculate the base Fuel Consumption (FC) value. - /// </summary> - [JsonProperty(Required = Required.Always)] - public string FuelMap; - - /// <summary> - /// [g/kWh] The WHTC test results are required in Declaration Mode for the urban WHTC FC Correction. - /// </summary> - [JsonProperty("WHTC-Urban")] - public double WHTCUrban; - - /// <summary> - /// [g/kWh] The WHTC test results are required in Declaration Mode for the rural WHTC FC Correction. - /// </summary> - [JsonProperty("WHTC-Rural")] - public double WHTCRural; - - /// <summary> - /// [g/kWh] The WHTC test results are required in Declaration Mode for the motorway WHTC FC Correction. - /// </summary> - [JsonProperty("WHTC-Motorway")] - public double WHTCMotorway; - - #region Equality members - - protected bool Equals(DataBody other) - { - return SavedInDeclarationMode.Equals(other.SavedInDeclarationMode) - && string.Equals(ModelName, other.ModelName) - && Displacement.Equals(other.Displacement) - && IdleSpeed.Equals(other.IdleSpeed) - && Inertia.Equals(other.Inertia) - && FullLoadCurves.SequenceEqual(other.FullLoadCurves) - && string.Equals(FuelMap, other.FuelMap) - && WHTCUrban.Equals(other.WHTCUrban) - && WHTCRural.Equals(other.WHTCRural) - && WHTCMotorway.Equals(other.WHTCMotorway); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((DataBody)obj); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = SavedInDeclarationMode.GetHashCode(); - hashCode = (hashCode * 397) ^ (ModelName != null ? ModelName.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ Displacement.GetHashCode(); - hashCode = (hashCode * 397) ^ IdleSpeed.GetHashCode(); - hashCode = (hashCode * 397) ^ Inertia.GetHashCode(); - hashCode = (hashCode * 397) ^ (FullLoadCurves != null ? FullLoadCurves.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (FuelMap != null ? FuelMap.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ WHTCUrban.GetHashCode(); - hashCode = (hashCode * 397) ^ WHTCRural.GetHashCode(); - hashCode = (hashCode * 397) ^ WHTCMotorway.GetHashCode(); - return hashCode; - } - } - - #endregion - } - - [JsonProperty(Required = Required.Always)] - public DataBody Body; - - #region Equality members - - protected bool Equals(Data other) - { - return Equals(Header, other.Header) && Equals(Body, other.Body); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((Data)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((Header != null ? Header.GetHashCode() : 0) * 397) ^ (Body != null ? Body.GetHashCode() : 0); - } - } - - #endregion - } - - [DataMember] - private Data _data; - - public bool SavedInDeclarationMode - { - get { return _data.Body.SavedInDeclarationMode; } - protected set { _data.Body.SavedInDeclarationMode = value; } - } - - public string ModelName - { - get { return _data.Body.ModelName; } - protected set { _data.Body.ModelName = value; } - } - - /// <summary> - /// [m^3] - /// </summary> - public SI Displacement - { - get { return _data.Body.Displacement.SI().Cubic.Centi.Meter.To().Cubic.Meter.Value(); } - protected set { _data.Body.Displacement = (double)value.To().Cubic.Centi.Meter; } - } - - /// <summary> - /// [rad/s] - /// </summary> - public RadianPerSecond IdleSpeed - { - get { return _data.Body.IdleSpeed.SI().Rounds.Per.Minute.To<RadianPerSecond>(); } - protected set { _data.Body.IdleSpeed = (double)value.To().Rounds.Per.Minute; } - } - - /// <summary> - /// [kgm^2] - /// </summary> - public SI Inertia - { - get { return _data.Body.Inertia.SI().Kilo.Gramm.Square.Meter; } - protected set { _data.Body.Inertia = (double)value.To().Kilo.Gramm.Square.Meter; } - } - - /// <summary> - /// [kg/Ws] - /// </summary> - public SI WHTCUrban - { - get { return _data.Body.WHTCUrban.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } - protected set { _data.Body.WHTCUrban = (double)value.To().Gramm.Per.Kilo.Watt.Hour; } - } - - /// <summary> - /// [kg/Ws] - /// </summary> - public SI WHTCRural - { - get { return _data.Body.WHTCRural.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } - protected set { _data.Body.WHTCRural = (double)value.To().Gramm.Per.Kilo.Watt.Hour; } - } - - /// <summary> - /// [g/Ws] - /// </summary> - public SI WHTCMotorway - { - get { return _data.Body.WHTCMotorway.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } - protected set { _data.Body.WHTCMotorway = (double)value.To().Gramm.Per.Kilo.Watt.Hour; } - } - - [DataMember] - public FuelConsumptionMap ConsumptionMap { get; set; } - - public class RangeConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - return value.GetType() == typeof(string) ? new Range((string)value) : base.ConvertFrom(context, culture, value); - } - } - - [TypeConverter(typeof(RangeConverter))] - private class Range - { - private readonly uint _start; - - private readonly uint _end; - - public Range(string range) - { - Contract.Requires(range != null); - - _start = uint.Parse(range.Split('-').First().Trim()); - _end = uint.Parse(range.Split('-').Last().Trim()); - } - - public override string ToString() - { - return string.Format("{0} - {1}", _start, _end); - } - - public bool Contains(uint value) - { - return _start <= value && value <= _end; - } - - #region Equality members - - protected bool Equals(Range other) - { - Contract.Requires(other != null); - return _start == other._start && _end == other._end; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((Range)obj); - } - - public override int GetHashCode() - { - unchecked - { - return (int)((_start * 397) ^ _end); - } - } - - #endregion - } - - [DataMember] - private readonly Dictionary<Range, FullLoadCurve> _fullLoadCurves = new Dictionary<Range, FullLoadCurve>(); - - public static CombustionEngineData ReadFromFile(string fileName) - { - return ReadFromJson(File.ReadAllText(fileName), Path.GetDirectoryName(fileName)); - } - - public static CombustionEngineData ReadFromJson(string json, string basePath = "") - { - var combustionEngineData = new CombustionEngineData(); - //todo handle conversion errors - var d = JsonConvert.DeserializeObject<Data>(json); - - combustionEngineData._data = d; - - if (d.Header.FileVersion > 2) - throw new UnsupportedFileVersionException("Unsupported Version of .veng file. Got Version: " + d.Header.FileVersion); - - combustionEngineData.ConsumptionMap = FuelConsumptionMap.ReadFromFile(Path.Combine(basePath, d.Body.FuelMap)); - - foreach (var loadCurve in d.Body.FullLoadCurves) - { - var fullLoadCurve = FullLoadCurve.ReadFromFile(Path.Combine(basePath, loadCurve.Path)); - var gearRange = new Range(loadCurve.Gears); - combustionEngineData._fullLoadCurves[gearRange] = fullLoadCurve; - } - - return combustionEngineData; - } - - public void WriteToFile(string fileName) - { - //todo handle file exceptions - File.WriteAllText(fileName, ToJson()); - } - - public string ToJson() - { - _data.Header.Date = DateTime.Now; - _data.Header.FileVersion = 2; - _data.Header.AppVersion = "3.0.0"; // todo: get current app version! - _data.Header.CreatedBy = ""; // todo: get current user - _data.Body.SavedInDeclarationMode = false; //todo: get declaration mode setting - return JsonConvert.SerializeObject(_data, Formatting.Indented); - } - - public FullLoadCurve GetFullLoadCurve(uint gear) - { - var curve = _fullLoadCurves.FirstOrDefault(kv => kv.Key.Contains(gear)); - if (curve.Key.Equals(null)) - throw new KeyNotFoundException(string.Format("Gear '{0}' was not found in the FullLoadCurves.", gear)); - - return curve.Value; - } - - #region Equality members - - protected bool Equals(CombustionEngineData other) - { - return Equals(_data, other._data) - && _fullLoadCurves.Keys.SequenceEqual(other._fullLoadCurves.Keys) - && _fullLoadCurves.Values.SequenceEqual(other._fullLoadCurves.Values) - && Equals(ConsumptionMap, other.ConsumptionMap); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((CombustionEngineData)obj); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = _data.GetHashCode(); - hashCode = (hashCode * 397) ^ (_fullLoadCurves != null ? _fullLoadCurves.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (ConsumptionMap != null ? ConsumptionMap.GetHashCode() : 0); - return hashCode; - } - } - #endregion - } -} + /// <summary> + /// Represents the CombustionEngineData. Fileformat: .veng + /// </summary> + /// <code> + /// { + /// "Header": { + /// "CreatedBy": " ()", + /// "Date": "3/4/2015 12:26:24 PM", + /// "AppVersion": "2.0.4-beta3", + /// "FileVersion": 2 + /// }, + /// "Body": { + /// "SavedInDeclMode": false, + /// "ModelName": "Generic 24t Coach", + /// "Displacement": 12730.0, + /// "IdlingSpeed": 560.0, + /// "Inertia": 3.8, + /// "FullLoadCurves": [ + /// { + /// "Path": "24t Coach.vfld", + /// "Gears": "0 - 99" + /// } + /// ], + /// "FuelMap": "24t Coach.vmap", + /// "WHTC-Urban": 0.0, + /// "WHTC-Rural": 0.0, + /// "WHTC-Motorway": 0.0 + /// } + /// } + /// </code> + [DataContract] + public class CombustionEngineData : SimulationComponentData + { + [DataMember] private readonly Dictionary<Range, FullLoadCurve> _fullLoadCurves = + new Dictionary<Range, FullLoadCurve>(); + + [DataMember] private Data _data; + + public bool SavedInDeclarationMode + { + get { return _data.Body.SavedInDeclarationMode; } + protected set { _data.Body.SavedInDeclarationMode = value; } + } + + public string ModelName + { + get { return _data.Body.ModelName; } + protected set { _data.Body.ModelName = value; } + } + + /// <summary> + /// [m^3] + /// </summary> + public SI Displacement + { + get { return _data.Body.Displacement.SI().Cubic.Centi.Meter.To().Cubic.Meter.Value(); } + protected set { _data.Body.Displacement = (double) value.To().Cubic.Centi.Meter; } + } + + /// <summary> + /// [rad/s] + /// </summary> + public RadianPerSecond IdleSpeed + { + get { return _data.Body.IdleSpeed.SI().Rounds.Per.Minute.To<RadianPerSecond>(); } + protected set { _data.Body.IdleSpeed = (double) value.To().Rounds.Per.Minute; } + } + + /// <summary> + /// [kgm^2] + /// </summary> + public SI Inertia + { + get { return _data.Body.Inertia.SI().Kilo.Gramm.Square.Meter; } + protected set { _data.Body.Inertia = (double) value.To().Kilo.Gramm.Square.Meter; } + } + + /// <summary> + /// [kg/Ws] + /// </summary> + public SI WHTCUrban + { + get { return _data.Body.WHTCUrban.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } + protected set { _data.Body.WHTCUrban = (double) value.To().Gramm.Per.Kilo.Watt.Hour; } + } + + /// <summary> + /// [kg/Ws] + /// </summary> + public SI WHTCRural + { + get { return _data.Body.WHTCRural.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } + protected set { _data.Body.WHTCRural = (double) value.To().Gramm.Per.Kilo.Watt.Hour; } + } + + /// <summary> + /// [g/Ws] + /// </summary> + public SI WHTCMotorway + { + get { return _data.Body.WHTCMotorway.SI().Gramm.Per.Kilo.Watt.Hour.To().Kilo.Gramm.Per.Watt.Second.Value(); } + protected set { _data.Body.WHTCMotorway = (double) value.To().Gramm.Per.Kilo.Watt.Hour; } + } + + [DataMember] + public FuelConsumptionMap ConsumptionMap { get; set; } + + public static CombustionEngineData ReadFromFile(string fileName) + { + return ReadFromJson(File.ReadAllText(fileName), Path.GetDirectoryName(fileName)); + } + + public static CombustionEngineData ReadFromJson(string json, string basePath = "") + { + var combustionEngineData = new CombustionEngineData(); + //todo handle conversion errors + var d = JsonConvert.DeserializeObject<Data>(json); + + combustionEngineData._data = d; + + if (d.Header.FileVersion > 2) { + throw new UnsupportedFileVersionException("Unsupported Version of .veng file. Got Version: " + d.Header.FileVersion); + } + + combustionEngineData.ConsumptionMap = FuelConsumptionMap.ReadFromFile(Path.Combine(basePath, d.Body.FuelMap)); + + foreach (var loadCurve in d.Body.FullLoadCurves) { + var fullLoadCurve = FullLoadCurve.ReadFromFile(Path.Combine(basePath, loadCurve.Path)); + var gearRange = new Range(loadCurve.Gears); + combustionEngineData._fullLoadCurves[gearRange] = fullLoadCurve; + } + + return combustionEngineData; + } + + public void WriteToFile(string fileName) + { + //todo handle file exceptions + File.WriteAllText(fileName, ToJson()); + } + + public string ToJson() + { + _data.Header.Date = DateTime.Now; + _data.Header.FileVersion = 2; + _data.Header.AppVersion = "3.0.0"; // todo: get current app version! + _data.Header.CreatedBy = ""; // todo: get current user + _data.Body.SavedInDeclarationMode = false; //todo: get declaration mode setting + return JsonConvert.SerializeObject(_data, Formatting.Indented); + } + + public FullLoadCurve GetFullLoadCurve(uint gear) + { + var curve = _fullLoadCurves.FirstOrDefault(kv => kv.Key.Contains(gear)); + if (curve.Key.Equals(null)) { + throw new KeyNotFoundException(string.Format("Gear '{0}' was not found in the FullLoadCurves.", gear)); + } + + return curve.Value; + } + + /// <summary> + /// A class which represents the json data format for serializing and deserializing the EngineData files. + /// </summary> + public class Data + { + [JsonProperty(Required = Required.Always)] public DataBody Body; + [JsonProperty(Required = Required.Always)] public DataHeader Header; + + public class DataHeader + { + [JsonProperty(Required = Required.Always)] public string AppVersion; + [JsonProperty(Required = Required.Always)] public string CreatedBy; + [JsonProperty(Required = Required.Always)] public DateTime Date; + [JsonProperty(Required = Required.Always)] public double FileVersion; + + #region Equality members + + protected bool Equals(DataHeader other) + { + return string.Equals(CreatedBy, other.CreatedBy) && Date.Equals(other.Date) && + string.Equals(AppVersion, other.AppVersion) && FileVersion.Equals(other.FileVersion); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((DataHeader) obj); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = (CreatedBy != null ? CreatedBy.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Date.GetHashCode(); + hashCode = (hashCode * 397) ^ (AppVersion != null ? AppVersion.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ FileVersion.GetHashCode(); + return hashCode; + } + } + + #endregion + } + + public class DataBody + { + /// <summary> + /// [ccm] Displacement in cubic centimeter. + /// Used in Declaration Mode to calculate inertia. + /// </summary> + [JsonProperty(Required = Required.Always)] public double Displacement; + + /// <summary> + /// The Fuel Consumption Map is used to calculate the base Fuel Consumption (FC) value. + /// </summary> + [JsonProperty(Required = Required.Always)] public string FuelMap; + + [JsonProperty(Required = Required.Always)] public IList<DataFullLoadCurve> FullLoadCurves; + + /// <summary> + /// [rpm] Idling Engine Speed + /// Low idle, applied in simulation for vehicle standstill in neutral gear position. + /// </summary> + [JsonProperty("IdlingSpeed", Required = Required.Always)] public double IdleSpeed; + + /// <summary> + /// [kgm^2] Inertia including Flywheel + /// Inertia for rotating parts including engine flywheel. + /// In Declaration Mode the inertia is calculated automatically. + /// </summary> + [JsonProperty(Required = Required.Always)] public double Inertia; + + /// <summary> + /// Model. Free text defining the engine model, type, etc. + /// </summary> + [JsonProperty(Required = Required.Always)] public string ModelName; + + [JsonProperty("SavedInDeclMode")] public bool SavedInDeclarationMode; + + /// <summary> + /// [g/kWh] The WHTC test results are required in Declaration Mode for the motorway WHTC FC Correction. + /// </summary> + [JsonProperty("WHTC-Motorway")] public double WHTCMotorway; + + /// <summary> + /// [g/kWh] The WHTC test results are required in Declaration Mode for the rural WHTC FC Correction. + /// </summary> + [JsonProperty("WHTC-Rural")] public double WHTCRural; + + /// <summary> + /// [g/kWh] The WHTC test results are required in Declaration Mode for the urban WHTC FC Correction. + /// </summary> + [JsonProperty("WHTC-Urban")] public double WHTCUrban; + + /// <summary> + /// Multiple Full Load and Drag Curves (.vfld) can be defined and assigned to different gears. + /// Gear "0" must be assigned for idling and Engine Only Mode. + /// </summary> + public class DataFullLoadCurve + { + [JsonProperty(Required = Required.Always)] public string Gears; + [JsonProperty(Required = Required.Always)] public string Path; + + #region Equality Members + + protected bool Equals(DataFullLoadCurve other) + { + return string.Equals(Path, other.Path) && string.Equals(Gears, other.Gears); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((DataFullLoadCurve) obj); + } + + public override int GetHashCode() + { + unchecked { + return ((Path != null ? Path.GetHashCode() : 0) * 397) ^ + (Gears != null ? Gears.GetHashCode() : 0); + } + } + + #endregion + } + + #region Equality members + + protected bool Equals(DataBody other) + { + return SavedInDeclarationMode.Equals(other.SavedInDeclarationMode) + && string.Equals(ModelName, other.ModelName) + && Displacement.Equals(other.Displacement) + && IdleSpeed.Equals(other.IdleSpeed) + && Inertia.Equals(other.Inertia) + && FullLoadCurves.SequenceEqual(other.FullLoadCurves) + && string.Equals(FuelMap, other.FuelMap) + && WHTCUrban.Equals(other.WHTCUrban) + && WHTCRural.Equals(other.WHTCRural) + && WHTCMotorway.Equals(other.WHTCMotorway); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((DataBody) obj); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = SavedInDeclarationMode.GetHashCode(); + hashCode = (hashCode * 397) ^ (ModelName != null ? ModelName.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Displacement.GetHashCode(); + hashCode = (hashCode * 397) ^ IdleSpeed.GetHashCode(); + hashCode = (hashCode * 397) ^ Inertia.GetHashCode(); + hashCode = (hashCode * 397) ^ (FullLoadCurves != null ? FullLoadCurves.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (FuelMap != null ? FuelMap.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ WHTCUrban.GetHashCode(); + hashCode = (hashCode * 397) ^ WHTCRural.GetHashCode(); + hashCode = (hashCode * 397) ^ WHTCMotorway.GetHashCode(); + return hashCode; + } + } + + #endregion + } + + #region Equality members + + protected bool Equals(Data other) + { + return Equals(Header, other.Header) && Equals(Body, other.Body); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((Data) obj); + } + + public override int GetHashCode() + { + unchecked { + return ((Header != null ? Header.GetHashCode() : 0) * 397) ^ (Body != null ? Body.GetHashCode() : 0); + } + } + + #endregion + } + + public class RangeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof (string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + return value.GetType() == typeof (string) ? new Range((string) value) : base.ConvertFrom(context, culture, value); + } + } + + [TypeConverter(typeof (RangeConverter))] + private class Range + { + private readonly uint _end; + private readonly uint _start; + + public Range(string range) + { + Contract.Requires(range != null); + + _start = uint.Parse(range.Split('-').First().Trim()); + _end = uint.Parse(range.Split('-').Last().Trim()); + } + + public override string ToString() + { + return string.Format("{0} - {1}", _start, _end); + } + + public bool Contains(uint value) + { + return _start <= value && value <= _end; + } + + #region Equality members + + protected bool Equals(Range other) + { + Contract.Requires(other != null); + return _start == other._start && _end == other._end; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((Range) obj); + } + + public override int GetHashCode() + { + unchecked { + return (int) ((_start * 397) ^ _end); + } + } + + #endregion + } + + #region Equality members + + protected bool Equals(CombustionEngineData other) + { + return Equals(_data, other._data) + && _fullLoadCurves.Keys.SequenceEqual(other._fullLoadCurves.Keys) + && _fullLoadCurves.Values.SequenceEqual(other._fullLoadCurves.Values) + && Equals(ConsumptionMap, other.ConsumptionMap); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((CombustionEngineData) obj); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = _data.GetHashCode(); + hashCode = (hashCode * 397) ^ (_fullLoadCurves != null ? _fullLoadCurves.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (ConsumptionMap != null ? ConsumptionMap.GetHashCode() : 0); + return hashCode; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs index f1b26b93264999604be8cffe6de4411a2b1d922f..46396270db95553cba9756b17a6441335985390e 100644 --- a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs +++ b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Data; using System.Linq; @@ -8,389 +8,403 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { - public class DrivingCycleData : SimulationComponentData - { - public enum CycleType - { - EngineOnly, - TimeBased, - DistanceBased - } - - private static class Fields - { - /// <summary> - /// [m] Travelled distance used for distance-based cycles. If t is also defined this column will be ignored. - /// </summary> - public const string Distance = "s"; - - /// <summary> - /// [s] Used for time-based cycles. If neither this nor the distance s is defined the data will be interpreted as 1Hz. - /// </summary> - public const string Time = "t"; - - /// <summary> - /// [km/h] Required except for Engine Only Mode calculations. - /// </summary> - public const string VehicleSpeed = "v"; - - /// <summary> - /// [%] Optional. - /// </summary> - public const string RoadGradient = "grad"; - - /// <summary> - /// [s] Required for distance-based cycles. Not used in time based cycles. stop defines the time the vehicle spends in stop phases. - /// </summary> - public const string StoppingTime = "stop"; - - /// <summary> - /// [kW] "Aux_xxx" Supply Power input for each auxiliary defined in the .vecto file , where xxx matches the ID of the corresponding Auxiliary. ID's are not case sensitive and must not contain space or special characters. - /// </summary> - // todo: implement additional aux as dictionary! - public const string AuxiliarySupplyPower = "Aux_"; - - /// <summary> - /// [rpm] If n is defined VECTO uses that instead of the calculated engine speed value. - /// </summary> - public const string EngineSpeed = "n"; - - /// <summary> - /// [-] Gear input. Overwrites the gear shift model. - /// </summary> - public const string Gear = "gear"; - - /// <summary> - /// [kW] This power input will be directly added to the engine power in addition to possible other auxiliaries. Also used in Engine Only Mode. - /// </summary> - public const string AdditionalAuxPowerDemand = "Padd"; - - /// <summary> - /// [km/h] Only required if Cross Wind Correction is set to Vair and Beta Input. - /// </summary> - public const string AirSpeedRelativeToVehicle = "vair_res"; - - /// <summary> - /// [°] Only required if Cross Wind Correction is set to Vair and Beta Input. - /// </summary> - public const string WindYawAngle = "vair_beta"; - - /// <summary> - /// [kW] Effective engine power at clutch. Only required in Engine Only Mode. Alternatively torque Me can be defined. Use DRAG to define motoring operation. - /// </summary> - public const string EnginePower = "Pe"; - - /// <summary> - /// [Nm] Effective engine torque at clutch. Only required in Engine Only Mode. Alternatively power Pe can be defined. Use DRAG to define motoring operation. - /// </summary> - public const string EngineTorque = "Me"; - } - - public class DrivingCycleEntry - { - /// <summary> - /// [m] Travelled distance used for distance-based cycles. If "t" - /// is also defined this column will be ignored. - /// </summary> - public double Distance { get; set; } - - /// <summary> - /// [s] Used for time-based cycles. If neither this nor the distance - /// "s" is defined the data will be interpreted as 1Hz. - /// </summary> - public double Time { get; set; } - - /// <summary> - /// [m/s] Required except for Engine Only Mode calculations. - /// </summary> - public MeterPerSecond VehicleSpeed { get; set; } - - /// <summary> - /// [%] Optional. - /// </summary> - public double RoadGradient { get; set; } - - /// <summary> - /// [s] Required for distance-based cycles. Not used in time based - /// cycles. "stop" defines the time the vehicle spends in stop phases. - /// </summary> - public double StoppingTime { get; set; } - - /// <summary> - /// [W] Supply Power input for each auxiliary defined in the - /// .vecto file where xxx matches the ID of the corresponding - /// Auxiliary. ID's are not case sensitive and must not contain - /// space or special characters. - /// </summary> - public Dictionary<string, Watt> AuxiliarySupplyPower { get; set; } - - /// <summary> - /// [rad/s] If "n" is defined VECTO uses that instead of the - /// calculated engine speed value. - /// </summary> - public RadianPerSecond EngineSpeed { get; set; } - - /// <summary> - /// [-] Gear input. Overwrites the gear shift model. - /// </summary> - public double Gear { get; set; } - - /// <summary> - /// [W] This power input will be directly added to the engine - /// power in addition to possible other auxiliaries. Also used in - /// Engine Only Mode. - /// </summary> - public Watt AdditionalAuxPowerDemand { get; set; } - - /// <summary> - /// [m/s] Only required if Cross Wind Correction is set to Vair and Beta Input. - /// </summary> - public MeterPerSecond AirSpeedRelativeToVehicle { get; set; } - - /// <summary> - /// [°] Only required if Cross Wind Correction is set to Vair and Beta Input. - /// </summary> - public double WindYawAngle { get; set; } - - /// <summary> - /// [Nm] Effective engine torque at clutch. Only required in - /// Engine Only Mode. Alternatively power "Pe" can be defined. - /// Use "DRAG" to define motoring operation. - /// </summary> - public NewtonMeter EngineTorque { get; set; } - - public bool Drag { get; set; } - - } - public List<DrivingCycleEntry> Entries { get; set; } - - public static DrivingCycleData ReadFromFileEngineOnly(string fileName) - { - return ReadFromFile(fileName, CycleType.EngineOnly); - } - - public static DrivingCycleData ReadFromFileDistanceBased(string fileName) - { - return ReadFromFile(fileName, CycleType.DistanceBased); - } - - public static DrivingCycleData ReadFromFileTimeBased(string fileName) - { - return ReadFromFile(fileName, CycleType.TimeBased); - } - - public static DrivingCycleData ReadFromFile(string fileName, CycleType type) - { - var log = LogManager.GetLogger<DrivingCycleData>(); - - var parser = CreateDataParser(type); - var data = VectoCSVFile.Read(fileName); - var entries = parser.Parse(data).ToList(); - - log.Info(string.Format("Data loaded. Number of Entries: {0}", entries.Count)); - - var cycle = new DrivingCycleData { Entries = entries }; - return cycle; - } - - private static IDataParser CreateDataParser(CycleType type) - { - switch (type) - { - case CycleType.EngineOnly: - return new EngineOnlyDataParser(); - case CycleType.TimeBased: - return new TimeBasedDataParser(); - case CycleType.DistanceBased: - return new DistanceBasedDataParser(); - default: - throw new ArgumentOutOfRangeException("type"); - } - } - - #region DataParser - - private interface IDataParser - { - IEnumerable<DrivingCycleEntry> Parse(DataTable table); - } - - /// <summary> - /// Reader for Auxiliary Supply Power. - /// </summary> - private static class AuxSupplyPowerReader - { - /// <summary> - /// [W]. Reads Auxiliary Supply Power (defined by Fields.AuxiliarySupplyPower-Prefix). - /// </summary> - public static Dictionary<string, Watt> Read(DataRow row) - { - return row.Table.Columns.Cast<DataColumn>(). - Where(col => col.ColumnName.StartsWith(Fields.AuxiliarySupplyPower)). - ToDictionary(col => col.ColumnName.Substring(Fields.AuxiliarySupplyPower.Length - 1), - col => row.ParseDouble(col).SI().Kilo.Watt.To<Watt>()); - } - } - - private class DistanceBasedDataParser : IDataParser - { - private static void ValidateHeader(string[] header) - { - var allowedCols = new[] - { - Fields.Distance, - Fields.VehicleSpeed, - Fields.RoadGradient, - Fields.StoppingTime, - Fields.EngineSpeed, - Fields.Gear, - Fields.AdditionalAuxPowerDemand, - Fields.AirSpeedRelativeToVehicle, - Fields.WindYawAngle - }; - - foreach (var col in header.Where(col => !(allowedCols.Contains(col) || col.StartsWith(Fields.AuxiliarySupplyPower)))) - throw new VectoException(string.Format("Column '{0}' is not allowed.", col)); - - if (!header.Contains(Fields.VehicleSpeed)) - throw new VectoException(string.Format("Column '{0}' is missing.", Fields.VehicleSpeed)); - - if (!header.Contains(Fields.Distance)) - throw new VectoException(string.Format("Column '{0}' is missing.", Fields.Distance)); - - if (header.Contains(Fields.AirSpeedRelativeToVehicle) ^ header.Contains(Fields.WindYawAngle)) - throw new VectoException(string.Format("Both Columns '{0}' and '{1}' must be defined, or none of them.", - Fields.AirSpeedRelativeToVehicle, Fields.WindYawAngle)); - } - - public IEnumerable<DrivingCycleEntry> Parse(DataTable table) - { - ValidateHeader(table.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray()); - - return table.Rows.Cast<DataRow>().Select(row => new DrivingCycleEntry - { - Distance = row.ParseDouble(Fields.Distance), - VehicleSpeed = row.ParseDouble(Fields.VehicleSpeed).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), - RoadGradient = row.ParseDoubleOrGetDefault(Fields.RoadGradient), - AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.To<Watt>(), - EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), - Gear = row.ParseDoubleOrGetDefault(Fields.Gear), - AirSpeedRelativeToVehicle = row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), - WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle), - AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) - }); - } - } - private class TimeBasedDataParser : IDataParser - { - private static void ValidateHeader(string[] header) - { - var allowedCols = new[] - { - Fields.Time, - Fields.VehicleSpeed, - Fields.RoadGradient, - Fields.EngineSpeed, - Fields.Gear, - Fields.AdditionalAuxPowerDemand, - Fields.AirSpeedRelativeToVehicle, - Fields.WindYawAngle - }; - - foreach (var col in header.Where(col => !(allowedCols.Contains(col) || col.StartsWith(Fields.AuxiliarySupplyPower)))) - throw new VectoException(string.Format("Column '{0}' is not allowed.", col)); - - if (!header.Contains(Fields.VehicleSpeed)) - throw new VectoException(string.Format("Column '{0}' is missing.", Fields.VehicleSpeed)); - - if (header.Contains(Fields.AirSpeedRelativeToVehicle) ^ header.Contains(Fields.WindYawAngle)) - throw new VectoException(string.Format("Both Columns '{0}' and '{1}' must be defined, or none of them.", - Fields.AirSpeedRelativeToVehicle, Fields.WindYawAngle)); - } - - public IEnumerable<DrivingCycleEntry> Parse(DataTable table) - { - ValidateHeader(table.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray()); - - var entries = table.Rows.Cast<DataRow>().Select((row, index) => new DrivingCycleEntry - { - Time = row.ParseDoubleOrGetDefault(Fields.Time, index), - VehicleSpeed = row.ParseDouble(Fields.VehicleSpeed).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), - RoadGradient = row.ParseDoubleOrGetDefault(Fields.RoadGradient), - AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.To<Watt>(), - Gear = row.ParseDoubleOrGetDefault(Fields.Gear), - EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), - AirSpeedRelativeToVehicle = row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), - WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle), - AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) - }).ToArray(); - - return entries; - } - } - private class EngineOnlyDataParser : IDataParser - { - private static void ValidateHeader(string[] header) - { - var allowedCols = new[] - { - Fields.EngineTorque, - Fields.EnginePower, - Fields.EngineSpeed, - Fields.AdditionalAuxPowerDemand - }; - - foreach (var col in header.Where(col => !allowedCols.Contains(col))) - throw new VectoException(string.Format("Column '{0}' is not allowed.", col)); - - if (!header.Contains(Fields.EngineSpeed)) - throw new VectoException(string.Format("Column '{0}' is missing.", Fields.EngineSpeed)); - - if (!(header.Contains(Fields.EngineTorque) || header.Contains(Fields.EnginePower))) - throw new VectoException(string.Format("Columns missing: Either column '{0}' or column '{1}' must be defined.", - Fields.EngineTorque, Fields.EnginePower)); - - if (header.Contains(Fields.EngineTorque) && header.Contains(Fields.EnginePower)) - LogManager.GetLogger<DrivingCycleData>() - .WarnFormat("Found column '{0}' and column '{1}': only column '{0}' will be used.", - Fields.EngineTorque, Fields.EnginePower); - } - - public IEnumerable<DrivingCycleEntry> Parse(DataTable table) - { - ValidateHeader(table.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray()); - TimeSpan absTime = new TimeSpan(hours: 0, minutes:0, seconds: 0); - - foreach (DataRow row in table.Rows) - { - var entry = new DrivingCycleEntry - { - EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), - AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.To<Watt>(), - AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) - }; - if (row.Table.Columns.Contains(Fields.EngineTorque)) - { - if (row.Field<string>(Fields.EngineTorque).Equals("<DRAG>")) - entry.Drag = true; - else - entry.EngineTorque = row.ParseDouble(Fields.EngineTorque).SI<NewtonMeter>(); - } - else - { - if (row.Field<string>(Fields.EnginePower).Equals("<DRAG>")) - entry.Drag = true; - else - entry.EngineTorque = Formulas.PowerToTorque(row.ParseDouble(Fields.EnginePower).SI().Kilo.Watt.To<Watt>(), - entry.EngineSpeed); - } - entry.Time = absTime.TotalSeconds; - absTime += new TimeSpan(hours: 0, minutes: 0, seconds: 1); - - yield return entry; - } - } - } - #endregion - } + public class DrivingCycleData : SimulationComponentData + { + public enum CycleType + { + EngineOnly, + TimeBased, + DistanceBased + } + + public List<DrivingCycleEntry> Entries { get; set; } + + public static DrivingCycleData ReadFromFileEngineOnly(string fileName) + { + return ReadFromFile(fileName, CycleType.EngineOnly); + } + + public static DrivingCycleData ReadFromFileDistanceBased(string fileName) + { + return ReadFromFile(fileName, CycleType.DistanceBased); + } + + public static DrivingCycleData ReadFromFileTimeBased(string fileName) + { + return ReadFromFile(fileName, CycleType.TimeBased); + } + + public static DrivingCycleData ReadFromFile(string fileName, CycleType type) + { + var log = LogManager.GetLogger<DrivingCycleData>(); + + var parser = CreateDataParser(type); + var data = VectoCSVFile.Read(fileName); + var entries = parser.Parse(data).ToList(); + + log.Info(string.Format("Data loaded. Number of Entries: {0}", entries.Count)); + + var cycle = new DrivingCycleData { Entries = entries }; + return cycle; + } + + private static IDataParser CreateDataParser(CycleType type) + { + switch (type) { + case CycleType.EngineOnly: + return new EngineOnlyDataParser(); + case CycleType.TimeBased: + return new TimeBasedDataParser(); + case CycleType.DistanceBased: + return new DistanceBasedDataParser(); + default: + throw new ArgumentOutOfRangeException("type"); + } + } + + private static class Fields + { + /// <summary> + /// [m] Travelled distance used for distance-based cycles. If t is also defined this column will be ignored. + /// </summary> + public const string Distance = "s"; + + /// <summary> + /// [s] Used for time-based cycles. If neither this nor the distance s is defined the data will be interpreted as 1Hz. + /// </summary> + public const string Time = "t"; + + /// <summary> + /// [km/h] Required except for Engine Only Mode calculations. + /// </summary> + public const string VehicleSpeed = "v"; + + /// <summary> + /// [%] Optional. + /// </summary> + public const string RoadGradient = "grad"; + + /// <summary> + /// [s] Required for distance-based cycles. Not used in time based cycles. stop defines the time the vehicle spends in + /// stop phases. + /// </summary> + public const string StoppingTime = "stop"; + + /// <summary> + /// [kW] "Aux_xxx" Supply Power input for each auxiliary defined in the .vecto file , where xxx matches the ID of the + /// corresponding Auxiliary. ID's are not case sensitive and must not contain space or special characters. + /// </summary> + // todo: implement additional aux as dictionary! + public const string AuxiliarySupplyPower = "Aux_"; + + /// <summary> + /// [rpm] If n is defined VECTO uses that instead of the calculated engine speed value. + /// </summary> + public const string EngineSpeed = "n"; + + /// <summary> + /// [-] Gear input. Overwrites the gear shift model. + /// </summary> + public const string Gear = "gear"; + + /// <summary> + /// [kW] This power input will be directly added to the engine power in addition to possible other auxiliaries. Also + /// used in Engine Only Mode. + /// </summary> + public const string AdditionalAuxPowerDemand = "Padd"; + + /// <summary> + /// [km/h] Only required if Cross Wind Correction is set to Vair and Beta Input. + /// </summary> + public const string AirSpeedRelativeToVehicle = "vair_res"; + + /// <summary> + /// [°] Only required if Cross Wind Correction is set to Vair and Beta Input. + /// </summary> + public const string WindYawAngle = "vair_beta"; + + /// <summary> + /// [kW] Effective engine power at clutch. Only required in Engine Only Mode. Alternatively torque Me can be defined. + /// Use DRAG to define motoring operation. + /// </summary> + public const string EnginePower = "Pe"; + + /// <summary> + /// [Nm] Effective engine torque at clutch. Only required in Engine Only Mode. Alternatively power Pe can be defined. + /// Use DRAG to define motoring operation. + /// </summary> + public const string EngineTorque = "Me"; + } + + public class DrivingCycleEntry + { + /// <summary> + /// [m] Travelled distance used for distance-based cycles. If "t" + /// is also defined this column will be ignored. + /// </summary> + public double Distance { get; set; } + + /// <summary> + /// [s] Used for time-based cycles. If neither this nor the distance + /// "s" is defined the data will be interpreted as 1Hz. + /// </summary> + public double Time { get; set; } + + /// <summary> + /// [m/s] Required except for Engine Only Mode calculations. + /// </summary> + public MeterPerSecond VehicleSpeed { get; set; } + + /// <summary> + /// [%] Optional. + /// </summary> + public double RoadGradient { get; set; } + + /// <summary> + /// [s] Required for distance-based cycles. Not used in time based + /// cycles. "stop" defines the time the vehicle spends in stop phases. + /// </summary> + public double StoppingTime { get; set; } + + /// <summary> + /// [W] Supply Power input for each auxiliary defined in the + /// .vecto file where xxx matches the ID of the corresponding + /// Auxiliary. ID's are not case sensitive and must not contain + /// space or special characters. + /// </summary> + public Dictionary<string, Watt> AuxiliarySupplyPower { get; set; } + + /// <summary> + /// [rad/s] If "n" is defined VECTO uses that instead of the + /// calculated engine speed value. + /// </summary> + public RadianPerSecond EngineSpeed { get; set; } + + /// <summary> + /// [-] Gear input. Overwrites the gear shift model. + /// </summary> + public double Gear { get; set; } + + /// <summary> + /// [W] This power input will be directly added to the engine + /// power in addition to possible other auxiliaries. Also used in + /// Engine Only Mode. + /// </summary> + public Watt AdditionalAuxPowerDemand { get; set; } + + /// <summary> + /// [m/s] Only required if Cross Wind Correction is set to Vair and Beta Input. + /// </summary> + public MeterPerSecond AirSpeedRelativeToVehicle { get; set; } + + /// <summary> + /// [°] Only required if Cross Wind Correction is set to Vair and Beta Input. + /// </summary> + public double WindYawAngle { get; set; } + + /// <summary> + /// [Nm] Effective engine torque at clutch. Only required in + /// Engine Only Mode. Alternatively power "Pe" can be defined. + /// Use "DRAG" to define motoring operation. + /// </summary> + public NewtonMeter EngineTorque { get; set; } + + public bool Drag { get; set; } + } + + #region DataParser + + private interface IDataParser + { + IEnumerable<DrivingCycleEntry> Parse(DataTable table); + } + + /// <summary> + /// Reader for Auxiliary Supply Power. + /// </summary> + private static class AuxSupplyPowerReader + { + /// <summary> + /// [W]. Reads Auxiliary Supply Power (defined by Fields.AuxiliarySupplyPower-Prefix). + /// </summary> + public static Dictionary<string, Watt> Read(DataRow row) + { + return row.Table.Columns.Cast<DataColumn>(). + Where(col => col.ColumnName.StartsWith(Fields.AuxiliarySupplyPower)). + ToDictionary(col => col.ColumnName.Substring(Fields.AuxiliarySupplyPower.Length - 1), + col => row.ParseDouble(col).SI().Kilo.Watt.To<Watt>()); + } + } + + private class DistanceBasedDataParser : IDataParser + { + public IEnumerable<DrivingCycleEntry> Parse(DataTable table) + { + ValidateHeader(table.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray()); + + return table.Rows.Cast<DataRow>().Select(row => new DrivingCycleEntry { + Distance = row.ParseDouble(Fields.Distance), + VehicleSpeed = row.ParseDouble(Fields.VehicleSpeed).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), + RoadGradient = row.ParseDoubleOrGetDefault(Fields.RoadGradient), + AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.To<Watt>(), + EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), + Gear = row.ParseDoubleOrGetDefault(Fields.Gear), + AirSpeedRelativeToVehicle = + row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), + WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle), + AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) + }); + } + + private static void ValidateHeader(string[] header) + { + var allowedCols = new[] { + Fields.Distance, + Fields.VehicleSpeed, + Fields.RoadGradient, + Fields.StoppingTime, + Fields.EngineSpeed, + Fields.Gear, + Fields.AdditionalAuxPowerDemand, + Fields.AirSpeedRelativeToVehicle, + Fields.WindYawAngle + }; + + foreach (var col in header.Where(col => !(allowedCols.Contains(col) || col.StartsWith(Fields.AuxiliarySupplyPower))) + ) { + throw new VectoException(string.Format("Column '{0}' is not allowed.", col)); + } + + if (!header.Contains(Fields.VehicleSpeed)) { + throw new VectoException(string.Format("Column '{0}' is missing.", Fields.VehicleSpeed)); + } + + if (!header.Contains(Fields.Distance)) { + throw new VectoException(string.Format("Column '{0}' is missing.", Fields.Distance)); + } + + if (header.Contains(Fields.AirSpeedRelativeToVehicle) ^ header.Contains(Fields.WindYawAngle)) { + throw new VectoException(string.Format("Both Columns '{0}' and '{1}' must be defined, or none of them.", + Fields.AirSpeedRelativeToVehicle, Fields.WindYawAngle)); + } + } + } + + private class TimeBasedDataParser : IDataParser + { + public IEnumerable<DrivingCycleEntry> Parse(DataTable table) + { + ValidateHeader(table.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray()); + + var entries = table.Rows.Cast<DataRow>().Select((row, index) => new DrivingCycleEntry { + Time = row.ParseDoubleOrGetDefault(Fields.Time, index), + VehicleSpeed = row.ParseDouble(Fields.VehicleSpeed).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), + RoadGradient = row.ParseDoubleOrGetDefault(Fields.RoadGradient), + AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.To<Watt>(), + Gear = row.ParseDoubleOrGetDefault(Fields.Gear), + EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), + AirSpeedRelativeToVehicle = + row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), + WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle), + AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) + }).ToArray(); + + return entries; + } + + private static void ValidateHeader(string[] header) + { + var allowedCols = new[] { + Fields.Time, + Fields.VehicleSpeed, + Fields.RoadGradient, + Fields.EngineSpeed, + Fields.Gear, + Fields.AdditionalAuxPowerDemand, + Fields.AirSpeedRelativeToVehicle, + Fields.WindYawAngle + }; + + foreach (var col in header.Where(col => !(allowedCols.Contains(col) || col.StartsWith(Fields.AuxiliarySupplyPower))) + ) { + throw new VectoException(string.Format("Column '{0}' is not allowed.", col)); + } + + if (!header.Contains(Fields.VehicleSpeed)) { + throw new VectoException(string.Format("Column '{0}' is missing.", Fields.VehicleSpeed)); + } + + if (header.Contains(Fields.AirSpeedRelativeToVehicle) ^ header.Contains(Fields.WindYawAngle)) { + throw new VectoException(string.Format("Both Columns '{0}' and '{1}' must be defined, or none of them.", + Fields.AirSpeedRelativeToVehicle, Fields.WindYawAngle)); + } + } + } + + private class EngineOnlyDataParser : IDataParser + { + public IEnumerable<DrivingCycleEntry> Parse(DataTable table) + { + ValidateHeader(table.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray()); + var absTime = new TimeSpan(0, 0, 0); + + foreach (DataRow row in table.Rows) { + var entry = new DrivingCycleEntry { + EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), + AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.To<Watt>(), + AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) + }; + if (row.Table.Columns.Contains(Fields.EngineTorque)) { + if (row.Field<string>(Fields.EngineTorque).Equals("<DRAG>")) { + entry.Drag = true; + } else { + entry.EngineTorque = row.ParseDouble(Fields.EngineTorque).SI<NewtonMeter>(); + } + } else { + if (row.Field<string>(Fields.EnginePower).Equals("<DRAG>")) { + entry.Drag = true; + } else { + entry.EngineTorque = Formulas.PowerToTorque(row.ParseDouble(Fields.EnginePower).SI().Kilo.Watt.To<Watt>(), + entry.EngineSpeed); + } + } + entry.Time = absTime.TotalSeconds; + absTime += new TimeSpan(0, 0, 1); + + yield return entry; + } + } + + private static void ValidateHeader(string[] header) + { + var allowedCols = new[] { + Fields.EngineTorque, + Fields.EnginePower, + Fields.EngineSpeed, + Fields.AdditionalAuxPowerDemand + }; + + foreach (var col in header.Where(col => !allowedCols.Contains(col))) { + throw new VectoException(string.Format("Column '{0}' is not allowed.", col)); + } + + if (!header.Contains(Fields.EngineSpeed)) { + throw new VectoException(string.Format("Column '{0}' is missing.", Fields.EngineSpeed)); + } + + if (!(header.Contains(Fields.EngineTorque) || header.Contains(Fields.EnginePower))) { + throw new VectoException(string.Format("Columns missing: Either column '{0}' or column '{1}' must be defined.", + Fields.EngineTorque, Fields.EnginePower)); + } + + if (header.Contains(Fields.EngineTorque) && header.Contains(Fields.EnginePower)) { + LogManager.GetLogger<DrivingCycleData>() + .WarnFormat("Found column '{0}' and column '{1}': only column '{0}' will be used.", + Fields.EngineTorque, Fields.EnginePower); + } + } + } + + #endregion + } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs index 40e35ab921e259c23e4d62f16ec9a7e403243ce0..52163fc134e782bdd8c7d103eb4c07f9238a1019 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/FuelConsumptionMap.cs @@ -9,165 +9,168 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine { - [JsonObject(MemberSerialization.Fields)] - public class FuelConsumptionMap : SimulationComponentData - { - [ContractInvariantMethod] - private void Invariant() - { - Contract.Invariant(_entries != null); - Contract.Invariant(_fuelMap != null); - } - - - - private static class Fields - { - /// <summary> - /// [rpm] - /// </summary> - public const string EngineSpeed = "engine speed"; - - /// <summary> - /// [Nm] - /// </summary> - public const string Torque = "torque"; - - /// <summary> - /// [g/h] - /// </summary> - public const string FuelConsumption = "fuel consumption"; - }; - - private class FuelConsumptionEntry - { - /// <summary> - /// engine speed [rad/s] - /// </summary> - public RadianPerSecond EngineSpeed { get; set; } - - /// <summary> - /// Torque [Nm] - /// </summary> - public NewtonMeter Torque { get; set; } - - /// <summary> - /// Fuel consumption [kg/s] - /// </summary> - public SI FuelConsumption { get; set; } - - #region Equality members - private bool Equals(FuelConsumptionEntry other) - { - Contract.Requires(other != null); - return EngineSpeed.Equals(other.EngineSpeed) && Torque.Equals(other.Torque) && - FuelConsumption.Equals(other.FuelConsumption); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((FuelConsumptionEntry)obj); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = EngineSpeed.GetHashCode(); - hashCode = (hashCode * 397) ^ Torque.GetHashCode(); - hashCode = (hashCode * 397) ^ FuelConsumption.GetHashCode(); - return hashCode; - } - } - #endregion - } - - private readonly IList<FuelConsumptionEntry> _entries = new List<FuelConsumptionEntry>(); - private readonly DelauneyMap _fuelMap = new DelauneyMap(); - - private FuelConsumptionMap() { } - - public static FuelConsumptionMap ReadFromFile(string fileName) - { - var fuelConsumptionMap = new FuelConsumptionMap(); - var data = VectoCSVFile.Read(fileName); - - try - { - foreach (DataRow row in data.Rows) - { - try - { - var entry = new FuelConsumptionEntry - { - EngineSpeed = row.ParseDouble(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), - Torque = row.ParseDouble(Fields.Torque).SI<NewtonMeter>(), - FuelConsumption = row.ParseDouble(Fields.FuelConsumption).SI().Gramm.Per.Hour.To().Kilo.Gramm.Per.Second - }; - - // todo Contract.Assert - if (entry.FuelConsumption < 0) - throw new ArgumentOutOfRangeException("FuelConsumption", "FuelConsumption < 0 not allowed."); - - fuelConsumptionMap._entries.Add(entry); - - // Delauney map works only as expected, when the engineSpeed is in rpm. - fuelConsumptionMap._fuelMap.AddPoint((double)entry.Torque, row.ParseDouble(Fields.EngineSpeed), (double)entry.FuelConsumption); - } - catch (Exception e) - { - throw new VectoException(string.Format("Line {0}: {1}", data.Rows.IndexOf(row), e.Message), e); - } - } - } - catch (Exception e) - { - throw new VectoException(string.Format("File {0}: {1}", fileName, e.Message), e); - } - - fuelConsumptionMap._fuelMap.Triangulate(); - return fuelConsumptionMap; - } - - /// <summary> - /// [kg/s] Calculates the fuel consumption based on the given fuel map, - /// the engineSpeed [rad/s] and the torque [Nm]. - /// </summary> - /// <param name="engineSpeed">[rad/sec]</param> - /// <param name="torque">[Nm]</param> - /// <returns>[kg/s]</returns> - public SI GetFuelConsumption(NewtonMeter torque, RadianPerSecond engineSpeed) - { - return _fuelMap.Interpolate((double)torque, (double)engineSpeed.To().Rounds.Per.Minute).SI().Kilo.Gramm.Per.Second; - } - - #region Equality members - - protected bool Equals(FuelConsumptionMap other) - { - return _entries.SequenceEqual(other._entries) && Equals(_fuelMap, other._fuelMap); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((FuelConsumptionMap)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((_entries != null ? _entries.GetHashCode() : 0) * 397) ^ - (_fuelMap != null ? _fuelMap.GetHashCode() : 0); - } - } - - #endregion - } -} + [JsonObject(MemberSerialization.Fields)] + public class FuelConsumptionMap : SimulationComponentData + { + private readonly IList<FuelConsumptionEntry> _entries = new List<FuelConsumptionEntry>(); + private readonly DelauneyMap _fuelMap = new DelauneyMap(); + private FuelConsumptionMap() {} + + [ContractInvariantMethod] + private void Invariant() + { + Contract.Invariant(_entries != null); + Contract.Invariant(_fuelMap != null); + } + + public static FuelConsumptionMap ReadFromFile(string fileName) + { + var fuelConsumptionMap = new FuelConsumptionMap(); + var data = VectoCSVFile.Read(fileName); + + try { + foreach (DataRow row in data.Rows) { + try { + var entry = new FuelConsumptionEntry { + EngineSpeed = row.ParseDouble(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), + Torque = row.ParseDouble(Fields.Torque).SI<NewtonMeter>(), + FuelConsumption = row.ParseDouble(Fields.FuelConsumption).SI().Gramm.Per.Hour.To().Kilo.Gramm.Per.Second + }; + + // todo Contract.Assert + if (entry.FuelConsumption < 0) { + throw new ArgumentOutOfRangeException("FuelConsumption", "FuelConsumption < 0 not allowed."); + } + + fuelConsumptionMap._entries.Add(entry); + + // Delauney map works only as expected, when the engineSpeed is in rpm. + fuelConsumptionMap._fuelMap.AddPoint((double) entry.Torque, row.ParseDouble(Fields.EngineSpeed), + (double) entry.FuelConsumption); + } catch (Exception e) { + throw new VectoException(string.Format("Line {0}: {1}", data.Rows.IndexOf(row), e.Message), e); + } + } + } catch (Exception e) { + throw new VectoException(string.Format("File {0}: {1}", fileName, e.Message), e); + } + + fuelConsumptionMap._fuelMap.Triangulate(); + return fuelConsumptionMap; + } + + /// <summary> + /// [kg/s] Calculates the fuel consumption based on the given fuel map, + /// the engineSpeed [rad/s] and the torque [Nm]. + /// </summary> + /// <param name="engineSpeed">[rad/sec]</param> + /// <param name="torque">[Nm]</param> + /// <returns>[kg/s]</returns> + public SI GetFuelConsumption(NewtonMeter torque, RadianPerSecond engineSpeed) + { + return _fuelMap.Interpolate((double) torque, (double) engineSpeed.To().Rounds.Per.Minute).SI().Kilo.Gramm.Per.Second; + } + + private static class Fields + { + /// <summary> + /// [rpm] + /// </summary> + public const string EngineSpeed = "engine speed"; + + /// <summary> + /// [Nm] + /// </summary> + public const string Torque = "torque"; + + /// <summary> + /// [g/h] + /// </summary> + public const string FuelConsumption = "fuel consumption"; + }; + + private class FuelConsumptionEntry + { + /// <summary> + /// engine speed [rad/s] + /// </summary> + public RadianPerSecond EngineSpeed { get; set; } + + /// <summary> + /// Torque [Nm] + /// </summary> + public NewtonMeter Torque { get; set; } + + /// <summary> + /// Fuel consumption [kg/s] + /// </summary> + public SI FuelConsumption { get; set; } + + #region Equality members + + private bool Equals(FuelConsumptionEntry other) + { + Contract.Requires(other != null); + return EngineSpeed.Equals(other.EngineSpeed) && Torque.Equals(other.Torque) && + FuelConsumption.Equals(other.FuelConsumption); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((FuelConsumptionEntry) obj); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = EngineSpeed.GetHashCode(); + hashCode = (hashCode * 397) ^ Torque.GetHashCode(); + hashCode = (hashCode * 397) ^ FuelConsumption.GetHashCode(); + return hashCode; + } + } + + #endregion + } + + #region Equality members + + protected bool Equals(FuelConsumptionMap other) + { + return _entries.SequenceEqual(other._entries) && Equals(_fuelMap, other._fuelMap); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((FuelConsumptionMap) obj); + } + + public override int GetHashCode() + { + unchecked { + return ((_entries != null ? _entries.GetHashCode() : 0) * 397) ^ + (_fuelMap != null ? _fuelMap.GetHashCode() : 0); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs index cfdc98e2ff6f2b4c3d0e6ad0ebd05681817e32b9..992e93332383c8040b0846eb776520c82037676d 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs @@ -9,261 +9,263 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine { - public class FullLoadCurve : SimulationComponentData - { - private static class Fields - { - /// <summary> - /// [rpm] engine speed - /// </summary> - public const string EngineSpeed = "engine speed"; - - /// <summary> - /// [Nm] full load torque - /// </summary> - public const string TorqueFullLoad = "full load torque"; - - /// <summary> - /// [Nm] motoring torque - /// </summary> - public const string TorqueDrag = "motoring torque"; - - /// <summary> - /// [s] time constant - /// </summary> - public const string PT1 = "PT1"; - } - - private class FullLoadCurveEntry - { - /// <summary> - /// [rad/s] engine speed - /// </summary> - public RadianPerSecond EngineSpeed { get; set; } - - /// <summary> - /// [Nm] full load torque - /// </summary> - public NewtonMeter TorqueFullLoad { get; set; } - - /// <summary> - /// [Nm] motoring torque - /// </summary> - public NewtonMeter TorqueDrag { get; set; } - - /// <summary> - /// [s] PT1 time constant - /// </summary> - public Second PT1 { get; set; } - - #region Equality members - protected bool Equals(FullLoadCurveEntry other) - { - Contract.Requires(other != null); - return EngineSpeed.Equals(other.EngineSpeed) - && TorqueFullLoad.Equals(other.TorqueFullLoad) - && TorqueDrag.Equals(other.TorqueDrag) - && PT1.Equals(other.PT1); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == GetType() && Equals((FullLoadCurveEntry)obj); - } - - public override int GetHashCode() - { - var hashCode = EngineSpeed.GetHashCode(); - hashCode = (hashCode * 397) ^ TorqueFullLoad.GetHashCode(); - hashCode = (hashCode * 397) ^ TorqueDrag.GetHashCode(); - hashCode = (hashCode * 397) ^ PT1.GetHashCode(); - return hashCode; - } - - #endregion - } - - [JsonProperty] - private List<FullLoadCurveEntry> _entries; - - public static FullLoadCurve ReadFromFile(string fileName) - { - var data = VectoCSVFile.Read(fileName); - - //todo Contract.Requires<VectoException>(data.Columns.Count != 4, "FullLoadCurve Data File must consist of 4 columns."); - if (data.Columns.Count != 4) - throw new VectoException("FullLoadCurve Data File must consist of 4 columns."); - - //todo Contract.Requires<VectoException>(data.Rows.Count < 2, "FullLoadCurve must consist of at least two lines with numeric values (below file header)"); - if (data.Rows.Count < 2) - throw new VectoException("FullLoadCurve must consist of at least two lines with numeric values (below file header)"); - - List<FullLoadCurveEntry> entries; - if (HeaderIsValid(data.Columns)) - { - entries = CreateFromColumnNames(data); - } - else - { - var log = LogManager.GetLogger<FullLoadCurve>(); - log.WarnFormat("FullLoadCurve: Header Line is not valid. Expected: '{0}, {1}, {2}, {3}', Got: '{4}'. Falling back to column index.", - Fields.EngineSpeed, Fields.TorqueFullLoad, Fields.TorqueDrag, Fields.PT1, - string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); - - entries = CreateFromColumnIndizes(data); - } - - return new FullLoadCurve { _entries = entries }; - } - - private static bool HeaderIsValid(DataColumnCollection columns) - { - Contract.Requires(columns != null); - return columns.Contains(Fields.EngineSpeed) - && columns.Contains(Fields.TorqueDrag) - && columns.Contains(Fields.TorqueFullLoad) - && columns.Contains(Fields.PT1); - } - - private static List<FullLoadCurveEntry> CreateFromColumnNames(DataTable data) - { - Contract.Requires(data != null); - return (from DataRow row in data.Rows - select new FullLoadCurveEntry - { - EngineSpeed = row.ParseDouble(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), - TorqueFullLoad = row.ParseDouble(Fields.TorqueFullLoad).SI<NewtonMeter>(), - TorqueDrag = row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>(), - PT1 = row.ParseDouble(Fields.PT1).SI<Second>() - }).ToList(); - } - - private static List<FullLoadCurveEntry> CreateFromColumnIndizes(DataTable data) - { - Contract.Requires(data != null); - return (from DataRow row in data.Rows - select new FullLoadCurveEntry - { - EngineSpeed = row.ParseDouble(0).SI().Rounds.Per.Minute.To<RadianPerSecond>(), - TorqueFullLoad = row.ParseDouble(1).SI<NewtonMeter>(), - TorqueDrag = row.ParseDouble(2).SI<NewtonMeter>(), - PT1 = row.ParseDouble(3).SI<Second>() - }).ToList(); - } - - /// <summary> - /// [rad/s] => [Nm] - /// </summary> - /// <param name="angularFrequency">[rad/s]</param> - /// <returns>[Nm]</returns> - public NewtonMeter FullLoadStationaryTorque(RadianPerSecond angularFrequency) - { - var idx = FindIndex(angularFrequency); - return VectoMath.Interpolate((double)_entries[idx - 1].EngineSpeed, (double)_entries[idx].EngineSpeed, - (double)_entries[idx - 1].TorqueFullLoad, (double)_entries[idx].TorqueFullLoad, - (double)angularFrequency).SI<NewtonMeter>(); - } - - /// <summary> - /// [rad/s] => [W] - /// </summary> - /// <param name="angularFrequency">[rad/s]</param> - /// <returns>[W]</returns> - public Watt FullLoadStationaryPower(RadianPerSecond angularFrequency) - { - return Formulas.TorqueToPower(FullLoadStationaryTorque(angularFrequency), angularFrequency); - } - - /// <summary> - /// [rad/s] => [Nm] - /// </summary> - /// <param name="angularFrequency">[rad/s]</param> - /// <returns>[Nm]</returns> - public NewtonMeter DragLoadStationaryTorque(RadianPerSecond angularFrequency) - { - var idx = FindIndex(angularFrequency); - return VectoMath.Interpolate((double)_entries[idx - 1].EngineSpeed, (double)_entries[idx].EngineSpeed, - (double)_entries[idx - 1].TorqueDrag, (double)_entries[idx].TorqueDrag, - (double)angularFrequency).SI<NewtonMeter>(); - } - - /// <summary> - /// [rad/s] => [W]. - /// </summary> - /// <param name="angularFrequency">[rad/s]</param> - /// <returns>[W]</returns> - public Watt DragLoadStationaryPower(RadianPerSecond angularFrequency) - { - Contract.Requires(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); - Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI().Watt)); - - return Formulas.TorqueToPower(DragLoadStationaryTorque(angularFrequency), angularFrequency); - } - - /// <summary> - /// [rad/s] => [-] - /// </summary> - /// <param name="angularFrequency">[rad/s]</param> - /// <returns>[-]</returns> - public SI PT1(SI angularFrequency) - { - Contract.Requires(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); - Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI())); - - var idx = FindIndex(angularFrequency); - return VectoMath.Interpolate((double)_entries[idx - 1].EngineSpeed, (double)_entries[idx].EngineSpeed, - (double)_entries[idx - 1].PT1, (double)_entries[idx].PT1, - (double)angularFrequency).SI(); - } - - /// <summary> - /// [rad/s] => index. Get item index for engineSpeed. - /// </summary> - /// <param name="engineSpeed">[rad/s]</param> - /// <returns>index</returns> - protected int FindIndex(SI engineSpeed) - { - Contract.Requires(engineSpeed.HasEqualUnit(new SI().Radian.Per.Second)); - - int idx; - if (engineSpeed < _entries[0].EngineSpeed) - { - Log.ErrorFormat("requested rpm below minimum rpm in FLD curve - extrapolating. n: {0}, rpm_min: {1}", - engineSpeed.To().Rounds.Per.Minute, _entries[0].EngineSpeed.To().Rounds.Per.Minute); - idx = 1; - } - else - { - idx = _entries.FindIndex(x => x.EngineSpeed > engineSpeed); - } - if (idx <= 0) - { - idx = engineSpeed > _entries[0].EngineSpeed ? _entries.Count - 1 : 1; - } - return idx; - } - - #region Equality members - - protected bool Equals(FullLoadCurve other) - { - return _entries.SequenceEqual(other._entries); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == GetType() && Equals((FullLoadCurve)obj); - } - - public override int GetHashCode() - { - return (_entries != null ? _entries.GetHashCode() : 0); - } - - #endregion - } -} + public class FullLoadCurve : SimulationComponentData + { + [JsonProperty] private List<FullLoadCurveEntry> _entries; + + public static FullLoadCurve ReadFromFile(string fileName) + { + var data = VectoCSVFile.Read(fileName); + + //todo Contract.Requires<VectoException>(data.Columns.Count != 4, "FullLoadCurve Data File must consist of 4 columns."); + if (data.Columns.Count != 4) { + throw new VectoException("FullLoadCurve Data File must consist of 4 columns."); + } + + //todo Contract.Requires<VectoException>(data.Rows.Count < 2, "FullLoadCurve must consist of at least two lines with numeric values (below file header)"); + if (data.Rows.Count < 2) { + throw new VectoException("FullLoadCurve must consist of at least two lines with numeric values (below file header)"); + } + + List<FullLoadCurveEntry> entries; + if (HeaderIsValid(data.Columns)) { + entries = CreateFromColumnNames(data); + } else { + var log = LogManager.GetLogger<FullLoadCurve>(); + log.WarnFormat( + "FullLoadCurve: Header Line is not valid. Expected: '{0}, {1}, {2}, {3}', Got: '{4}'. Falling back to column index.", + Fields.EngineSpeed, Fields.TorqueFullLoad, Fields.TorqueDrag, Fields.PT1, + string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); + + entries = CreateFromColumnIndizes(data); + } + + return new FullLoadCurve {_entries = entries}; + } + + private static bool HeaderIsValid(DataColumnCollection columns) + { + Contract.Requires(columns != null); + return columns.Contains(Fields.EngineSpeed) + && columns.Contains(Fields.TorqueDrag) + && columns.Contains(Fields.TorqueFullLoad) + && columns.Contains(Fields.PT1); + } + + private static List<FullLoadCurveEntry> CreateFromColumnNames(DataTable data) + { + Contract.Requires(data != null); + return (from DataRow row in data.Rows + select new FullLoadCurveEntry { + EngineSpeed = row.ParseDouble(Fields.EngineSpeed).SI().Rounds.Per.Minute.To<RadianPerSecond>(), + TorqueFullLoad = row.ParseDouble(Fields.TorqueFullLoad).SI<NewtonMeter>(), + TorqueDrag = row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>(), + PT1 = row.ParseDouble(Fields.PT1).SI<Second>() + }).ToList(); + } + + private static List<FullLoadCurveEntry> CreateFromColumnIndizes(DataTable data) + { + Contract.Requires(data != null); + return (from DataRow row in data.Rows + select new FullLoadCurveEntry { + EngineSpeed = row.ParseDouble(0).SI().Rounds.Per.Minute.To<RadianPerSecond>(), + TorqueFullLoad = row.ParseDouble(1).SI<NewtonMeter>(), + TorqueDrag = row.ParseDouble(2).SI<NewtonMeter>(), + PT1 = row.ParseDouble(3).SI<Second>() + }).ToList(); + } + + /// <summary> + /// [rad/s] => [Nm] + /// </summary> + /// <param name="angularFrequency">[rad/s]</param> + /// <returns>[Nm]</returns> + public NewtonMeter FullLoadStationaryTorque(RadianPerSecond angularFrequency) + { + var idx = FindIndex(angularFrequency); + return VectoMath.Interpolate((double) _entries[idx - 1].EngineSpeed, (double) _entries[idx].EngineSpeed, + (double) _entries[idx - 1].TorqueFullLoad, (double) _entries[idx].TorqueFullLoad, + (double) angularFrequency).SI<NewtonMeter>(); + } + + /// <summary> + /// [rad/s] => [W] + /// </summary> + /// <param name="angularFrequency">[rad/s]</param> + /// <returns>[W]</returns> + public Watt FullLoadStationaryPower(RadianPerSecond angularFrequency) + { + return Formulas.TorqueToPower(FullLoadStationaryTorque(angularFrequency), angularFrequency); + } + + /// <summary> + /// [rad/s] => [Nm] + /// </summary> + /// <param name="angularFrequency">[rad/s]</param> + /// <returns>[Nm]</returns> + public NewtonMeter DragLoadStationaryTorque(RadianPerSecond angularFrequency) + { + var idx = FindIndex(angularFrequency); + return VectoMath.Interpolate((double) _entries[idx - 1].EngineSpeed, (double) _entries[idx].EngineSpeed, + (double) _entries[idx - 1].TorqueDrag, (double) _entries[idx].TorqueDrag, + (double) angularFrequency).SI<NewtonMeter>(); + } + + /// <summary> + /// [rad/s] => [W]. + /// </summary> + /// <param name="angularFrequency">[rad/s]</param> + /// <returns>[W]</returns> + public Watt DragLoadStationaryPower(RadianPerSecond angularFrequency) + { + Contract.Requires(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); + Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI().Watt)); + + return Formulas.TorqueToPower(DragLoadStationaryTorque(angularFrequency), angularFrequency); + } + + /// <summary> + /// [rad/s] => [-] + /// </summary> + /// <param name="angularFrequency">[rad/s]</param> + /// <returns>[-]</returns> + public SI PT1(SI angularFrequency) + { + Contract.Requires(angularFrequency.HasEqualUnit(new SI().Radian.Per.Second)); + Contract.Ensures(Contract.Result<SI>().HasEqualUnit(new SI())); + + var idx = FindIndex(angularFrequency); + return VectoMath.Interpolate((double) _entries[idx - 1].EngineSpeed, (double) _entries[idx].EngineSpeed, + (double) _entries[idx - 1].PT1, (double) _entries[idx].PT1, + (double) angularFrequency).SI(); + } + + /// <summary> + /// [rad/s] => index. Get item index for engineSpeed. + /// </summary> + /// <param name="engineSpeed">[rad/s]</param> + /// <returns>index</returns> + protected int FindIndex(SI engineSpeed) + { + Contract.Requires(engineSpeed.HasEqualUnit(new SI().Radian.Per.Second)); + + int idx; + if (engineSpeed < _entries[0].EngineSpeed) { + Log.ErrorFormat("requested rpm below minimum rpm in FLD curve - extrapolating. n: {0}, rpm_min: {1}", + engineSpeed.To().Rounds.Per.Minute, _entries[0].EngineSpeed.To().Rounds.Per.Minute); + idx = 1; + } else { + idx = _entries.FindIndex(x => x.EngineSpeed > engineSpeed); + } + if (idx <= 0) { + idx = engineSpeed > _entries[0].EngineSpeed ? _entries.Count - 1 : 1; + } + return idx; + } + + private static class Fields + { + /// <summary> + /// [rpm] engine speed + /// </summary> + public const string EngineSpeed = "engine speed"; + + /// <summary> + /// [Nm] full load torque + /// </summary> + public const string TorqueFullLoad = "full load torque"; + + /// <summary> + /// [Nm] motoring torque + /// </summary> + public const string TorqueDrag = "motoring torque"; + + /// <summary> + /// [s] time constant + /// </summary> + public const string PT1 = "PT1"; + } + + private class FullLoadCurveEntry + { + /// <summary> + /// [rad/s] engine speed + /// </summary> + public RadianPerSecond EngineSpeed { get; set; } + + /// <summary> + /// [Nm] full load torque + /// </summary> + public NewtonMeter TorqueFullLoad { get; set; } + + /// <summary> + /// [Nm] motoring torque + /// </summary> + public NewtonMeter TorqueDrag { get; set; } + + /// <summary> + /// [s] PT1 time constant + /// </summary> + public Second PT1 { get; set; } + + #region Equality members + + protected bool Equals(FullLoadCurveEntry other) + { + Contract.Requires(other != null); + return EngineSpeed.Equals(other.EngineSpeed) + && TorqueFullLoad.Equals(other.TorqueFullLoad) + && TorqueDrag.Equals(other.TorqueDrag) + && PT1.Equals(other.PT1); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + return obj.GetType() == GetType() && Equals((FullLoadCurveEntry) obj); + } + + public override int GetHashCode() + { + var hashCode = EngineSpeed.GetHashCode(); + hashCode = (hashCode * 397) ^ TorqueFullLoad.GetHashCode(); + hashCode = (hashCode * 397) ^ TorqueDrag.GetHashCode(); + hashCode = (hashCode * 397) ^ PT1.GetHashCode(); + return hashCode; + } + + #endregion + } + + #region Equality members + + protected bool Equals(FullLoadCurve other) + { + return _entries.SequenceEqual(other._entries); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + return obj.GetType() == GetType() && Equals((FullLoadCurve) obj); + } + + public override int GetHashCode() + { + return (_entries != null ? _entries.GetHashCode() : 0); + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs b/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs index af09a8918f91fbdd1c12b3e0170f915e90edbf0b..5614867907cd6d633c07daf43785408b2e6bda1a 100644 --- a/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs +++ b/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs @@ -3,15 +3,13 @@ using Common.Logging; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { - public class SimulationComponentData - { - [NonSerialized] - protected ILog Log; + public class SimulationComponentData + { + [NonSerialized] protected ILog Log; - public SimulationComponentData() - { - Log = LogManager.GetLogger(GetType()); - } - - } -} + public SimulationComponentData() + { + Log = LogManager.GetLogger(GetType()); + } + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/IAuxiliary.cs b/VectoCore/Models/SimulationComponent/IAuxiliary.cs index 6219de3a50a9542d6a377f945474a8be039f96bf..381760949687048e15f80385bd946317309ffdc4 100644 --- a/VectoCore/Models/SimulationComponent/IAuxiliary.cs +++ b/VectoCore/Models/SimulationComponent/IAuxiliary.cs @@ -2,8 +2,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent { - public interface IAuxiliary : IInShaft, IOutShaft - { - - } + public interface IAuxiliary : IInShaft, IOutShaft {} } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/ICombustionEngine.cs b/VectoCore/Models/SimulationComponent/ICombustionEngine.cs index 44da41bcc29417eaa6ebb098147acfd8ae8444e7..637f1e3c84034ea024d91ad03d80bf578d8b4140 100644 --- a/VectoCore/Models/SimulationComponent/ICombustionEngine.cs +++ b/VectoCore/Models/SimulationComponent/ICombustionEngine.cs @@ -3,8 +3,5 @@ using TUGraz.VectoCore.Models.Simulation.Cockpit; namespace TUGraz.VectoCore.Models.SimulationComponent { - public interface ICombustionEngine : IOutShaft, IEngineCockpit - { - - } + public interface ICombustionEngine : IOutShaft, IEngineCockpit {} } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/IDrivingCycle.cs b/VectoCore/Models/SimulationComponent/IDrivingCycle.cs index 1aea420080c701d96f6aebcc1a6c700e999f856e..9907e5fc503d5950ccff5bbabe2a11b7ebcbe448 100644 --- a/VectoCore/Models/SimulationComponent/IDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/IDrivingCycle.cs @@ -1,21 +1,14 @@ using System; using TUGraz.VectoCore.Models.Connector.Ports; -using TUGraz.VectoCore.Models.Connector.Ports.Impl; namespace TUGraz.VectoCore.Models.SimulationComponent { - public interface IDrivingCycle - { - IResponse Request(TimeSpan absTime, TimeSpan dt); - } + public interface IDrivingCycle + { + IResponse Request(TimeSpan absTime, TimeSpan dt); + } - public interface IDriverDemandDrivingCycle : IDrivingCycle, IDriverDemandInProvider - { + public interface IDriverDemandDrivingCycle : IDrivingCycle, IDriverDemandInProvider {} - } - - public interface IEngineOnlyDrivingCycle : IDrivingCycle, IInShaft - { - - } + public interface IEngineOnlyDrivingCycle : IDrivingCycle, IInShaft {} } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/IGearbox.cs b/VectoCore/Models/SimulationComponent/IGearbox.cs index a13ed10ec6067f55a65824d70d1f22b932f6d917..4fb3f4fdad0d681f157febdd10f678e2dc93f987 100644 --- a/VectoCore/Models/SimulationComponent/IGearbox.cs +++ b/VectoCore/Models/SimulationComponent/IGearbox.cs @@ -3,8 +3,5 @@ using TUGraz.VectoCore.Models.Simulation.Cockpit; namespace TUGraz.VectoCore.Models.SimulationComponent { - public interface IGearbox : IInShaft, IOutShaft, IGearboxCockpit - { - - } + public interface IGearbox : IInShaft, IOutShaft, IGearboxCockpit {} } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/IWheels.cs b/VectoCore/Models/SimulationComponent/IWheels.cs index 5ef2ababac5b623de089c149fe99059fdd436e2d..1ddb859526229d3efb346b966d997a70c3240afb 100644 --- a/VectoCore/Models/SimulationComponent/IWheels.cs +++ b/VectoCore/Models/SimulationComponent/IWheels.cs @@ -1,6 +1,4 @@ namespace TUGraz.VectoCore.Models.SimulationComponent { - interface IWheels - { - } -} + internal interface IWheels {} +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index f0d77d2aae74776f05a7e92e6f2d52516cb53e9c..1940a7c0b61bbd32394db3a8eb1cc76c47a6daf4 100644 --- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -11,390 +11,387 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { + public class CombustionEngine : VectoSimulationComponent, ICombustionEngine, ITnOutPort, IMemento + { + public enum EngineOperationMode + { + Idle, + Drag, + FullDrag, + Load, + FullLoad, + Stopped, + Undef + } + + private const int EngineIdleSpeedStopThreshold = 100; + private const double MaxPowerExceededThreshold = 1.05; + private const double ZeroThreshold = 0.0001; + private const double FullLoadMargin = 0.01; + [NonSerialized] private readonly List<TimeSpan> _enginePowerCorrections = new List<TimeSpan>(); + + /// <summary> + /// Current state is computed in request method + /// </summary> + private EngineState _currentState = new EngineState(); + + private CombustionEngineData _data = new CombustionEngineData(); + private EngineState _previousState = new EngineState(); + + public CombustionEngine(IVehicleContainer cockpit, CombustionEngineData data) + : base(cockpit) + { + _data = data; + + _previousState.OperationMode = EngineOperationMode.Idle; + _previousState.EnginePower = 0.SI<Watt>(); + _previousState.EngineSpeed = _data.IdleSpeed; + } + + #region IEngineCockpit + + /// <summary> + /// [rad/s] + /// </summary> + public RadianPerSecond EngineSpeed() + { + return _previousState.EngineSpeed; + } + + #endregion + + public ITnOutPort OutShaft() + { + return this; + } + + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) + { + _currentState.EngineSpeed = engineSpeed; + _currentState.AbsTime = absTime; + + var requestedPower = Formulas.TorqueToPower(torque, engineSpeed); + _currentState.EnginePowerLoss = InertiaPowerLoss(torque, engineSpeed); + var requestedEnginePower = (requestedPower + _currentState.EnginePowerLoss).To<Watt>(); + + if (engineSpeed < (double) _data.IdleSpeed - EngineIdleSpeedStopThreshold) { + _currentState.OperationMode = EngineOperationMode.Stopped; + //todo: _currentState.EnginePowerLoss = enginePowerLoss; + } + + var currentGear = Cockpit.Gear(); + + _currentState.FullDragTorque = _data.GetFullLoadCurve(currentGear).DragLoadStationaryTorque(engineSpeed); + _currentState.FullDragPower = Formulas.TorqueToPower(_currentState.FullDragTorque, engineSpeed); + + ComputeFullLoadPower(currentGear, engineSpeed, dt); + + ValidatePowerDemand(requestedEnginePower); + + requestedEnginePower = LimitEnginePower(requestedEnginePower); + + UpdateEngineState(requestedEnginePower); + + _currentState.EnginePower = requestedEnginePower; //todo + _currentState.EnginePowerLoss; + _currentState.EngineTorque = Formulas.PowerToTorque(_currentState.EnginePower, + _currentState.EngineSpeed); + + //todo: use ResponseOverloadFail in case of overload + return new ResponseSuccess(); + } - public class CombustionEngine : VectoSimulationComponent, ICombustionEngine, ITnOutPort, IMemento - { - private const int EngineIdleSpeedStopThreshold = 100; - private const double MaxPowerExceededThreshold = 1.05; - private const double ZeroThreshold = 0.0001; - private const double FullLoadMargin = 0.01; - - public enum EngineOperationMode - { - Idle, - Drag, - FullDrag, - Load, - FullLoad, - Stopped, - Undef - } - - public class EngineState - { - public EngineOperationMode OperationMode { get; set; } - - /// <summary> - /// [s] - /// </summary> - public TimeSpan AbsTime { get; set; } - - /// <summary> - /// [W] - /// </summary> - public Watt EnginePower { get; set; } - - /// <summary> - /// [rad/s] - /// </summary> - public RadianPerSecond EngineSpeed { get; set; } - - /// <summary> - /// [W] - /// </summary> - public Watt EnginePowerLoss { get; set; } - - /// <summary> - /// [W] - /// </summary> - public Watt StationaryFullLoadPower { get; set; } - - /// <summary> - /// [W] - /// </summary> - public Watt DynamicFullLoadPower { get; set; } - - /// <summary> - /// [Nm] - /// </summary> - public NewtonMeter StationaryFullLoadTorque { get; set; } - - /// <summary> - /// [Nm] - /// </summary> - public NewtonMeter DynamicFullLoadTorque { get; set; } - - /// <summary> - /// [W] - /// </summary> - public Watt FullDragPower { get; set; } - - /// <summary> - /// [Nm] - /// </summary> - public NewtonMeter FullDragTorque { get; set; } - - /// <summary> - /// [Nm] - /// </summary> - public NewtonMeter EngineTorque { get; set; } - - #region Equality members - - protected bool Equals(EngineState other) - { - return OperationMode == other.OperationMode - && Equals(EnginePower, other.EnginePower) - && Equals(EngineSpeed, other.EngineSpeed) - && Equals(EnginePowerLoss, other.EnginePowerLoss) - && AbsTime.Equals(other.AbsTime); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - var other = obj as EngineState; - return other != null && Equals(other); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = (int) OperationMode; - hashCode = (hashCode*397) ^ (EnginePower != null ? EnginePower.GetHashCode() : 0); - hashCode = (hashCode*397) ^ (EngineSpeed != null ? EngineSpeed.GetHashCode() : 0); - hashCode = (hashCode*397) ^ (EnginePowerLoss != null ? EnginePowerLoss.GetHashCode() : 0); - hashCode = (hashCode*397) ^ AbsTime.GetHashCode(); - return hashCode; - } - } - - #endregion - } - - #region IEngineCockpit - /// <summary> - /// [rad/s] - /// </summary> - public RadianPerSecond EngineSpeed() - { - return _previousState.EngineSpeed; - } - #endregion - - private CombustionEngineData _data = new CombustionEngineData(); - private EngineState _previousState = new EngineState(); - - /// <summary> - /// Current state is computed in request method - /// </summary> - private EngineState _currentState = new EngineState(); - - [NonSerialized] - private List<TimeSpan> _enginePowerCorrections = new List<TimeSpan>(); - - - public CombustionEngine(IVehicleContainer cockpit, CombustionEngineData data) - : base(cockpit) - { - _data = data; - - _previousState.OperationMode = EngineOperationMode.Idle; - _previousState.EnginePower = 0.SI<Watt>(); - _previousState.EngineSpeed = _data.IdleSpeed; - } - - public ITnOutPort OutShaft() - { - return this; - } - - public override void CommitSimulationStep(IModalDataWriter writer) - { - writer[ModalResultField.PaEng] = (double)_currentState.EnginePowerLoss; - writer[ModalResultField.Pe_drag] = (double)_currentState.FullDragPower; - writer[ModalResultField.Pe_full] = (double)_currentState.DynamicFullLoadPower; - writer[ModalResultField.Pe_eng] = (double)_currentState.EnginePower; - - writer[ModalResultField.Tq_drag] = (double)_currentState.FullDragTorque; - writer[ModalResultField.Tq_full] = (double)_currentState.DynamicFullLoadTorque; - writer[ModalResultField.Tq_eng] = (double)_currentState.EngineTorque; - writer[ModalResultField.n] = (double)_currentState.EngineSpeed.To().Rounds.Per.Minute; - - try - { - writer[ModalResultField.FC] = (double)_data.ConsumptionMap.GetFuelConsumption(_currentState.EngineTorque, _currentState.EngineSpeed).To().Gramm.Per.Hour; - } - catch (VectoException ex) - { - Log.WarnFormat("t: {0} - {1} n: {2} Tq: {3}", _currentState.AbsTime.TotalSeconds, ex.Message, _currentState.EngineSpeed, _currentState.EngineTorque); - writer[ModalResultField.FC] = Double.NaN; - } - - _previousState = _currentState; - _currentState = new EngineState(); - } - - public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) - { - _currentState.EngineSpeed = engineSpeed; - _currentState.AbsTime = absTime; - - var requestedPower = Formulas.TorqueToPower(torque, engineSpeed); - _currentState.EnginePowerLoss = InertiaPowerLoss(torque, engineSpeed); - var requestedEnginePower = (requestedPower + _currentState.EnginePowerLoss).To<Watt>(); - - if (engineSpeed < (double)_data.IdleSpeed - EngineIdleSpeedStopThreshold) - { - _currentState.OperationMode = EngineOperationMode.Stopped; - //todo: _currentState.EnginePowerLoss = enginePowerLoss; - } - - var currentGear = Cockpit.Gear(); - - _currentState.FullDragTorque = _data.GetFullLoadCurve(currentGear).DragLoadStationaryTorque(engineSpeed); - _currentState.FullDragPower = Formulas.TorqueToPower(_currentState.FullDragTorque, engineSpeed); - - ComputeFullLoadPower(currentGear, engineSpeed, dt); - - ValidatePowerDemand(requestedEnginePower); - - requestedEnginePower = LimitEnginePower(requestedEnginePower); - - UpdateEngineState(requestedEnginePower); - - _currentState.EnginePower = requestedEnginePower; //todo + _currentState.EnginePowerLoss; - _currentState.EngineTorque = Formulas.PowerToTorque(_currentState.EnginePower, - _currentState.EngineSpeed); - - //todo: use ResponseOverloadFail in case of overload - return new ResponseSuccess(); - } - - /// <summary> - /// Validates the requested power demand [W]. - /// </summary> - /// <param name="requestedEnginePower">[W]</param> - protected void ValidatePowerDemand(SI requestedEnginePower) - { - Contract.Requires(requestedEnginePower.HasEqualUnit(new SI().Watt)); - - if (_currentState.FullDragPower >= 0 && requestedEnginePower < 0) - { - throw new VectoSimulationException(String.Format("t: {0} P_engine_drag > 0! n: {1} [1/min] ", - _currentState.AbsTime, _currentState.EngineSpeed.To().Rounds.Per.Minute)); - } - if (_currentState.DynamicFullLoadPower <= 0 && requestedEnginePower > 0) - { - throw new VectoSimulationException(String.Format("t: {0} P_engine_full < 0! n: {1} [1/min] ", - _currentState.AbsTime, _currentState.EngineSpeed.To().Rounds.Per.Minute)); - } - } - - /// <summary> - /// [W] => [W] - /// </summary> - /// <param name="requestedEnginePower">[W]</param> - /// <returns>[W]</returns> - protected Watt LimitEnginePower(Watt requestedEnginePower) - { - if (requestedEnginePower > _currentState.DynamicFullLoadPower) - { - if (requestedEnginePower / _currentState.DynamicFullLoadPower > MaxPowerExceededThreshold) - { - _enginePowerCorrections.Add(_currentState.AbsTime); - Log.WarnFormat("t: {0} requested power > P_engine_full * 1.05 - corrected. P_request: {1} P_engine_full: {2}", _currentState.AbsTime, requestedEnginePower, _currentState.DynamicFullLoadPower); - } + public override void CommitSimulationStep(IModalDataWriter writer) + { + writer[ModalResultField.PaEng] = (double) _currentState.EnginePowerLoss; + writer[ModalResultField.Pe_drag] = (double) _currentState.FullDragPower; + writer[ModalResultField.Pe_full] = (double) _currentState.DynamicFullLoadPower; + writer[ModalResultField.Pe_eng] = (double) _currentState.EnginePower; + + writer[ModalResultField.Tq_drag] = (double) _currentState.FullDragTorque; + writer[ModalResultField.Tq_full] = (double) _currentState.DynamicFullLoadTorque; + writer[ModalResultField.Tq_eng] = (double) _currentState.EngineTorque; + writer[ModalResultField.n] = (double) _currentState.EngineSpeed.To().Rounds.Per.Minute; + + try { + writer[ModalResultField.FC] = + (double) + _data.ConsumptionMap.GetFuelConsumption(_currentState.EngineTorque, _currentState.EngineSpeed).To().Gramm.Per.Hour; + } catch (VectoException ex) { + Log.WarnFormat("t: {0} - {1} n: {2} Tq: {3}", _currentState.AbsTime.TotalSeconds, ex.Message, + _currentState.EngineSpeed, _currentState.EngineTorque); + writer[ModalResultField.FC] = Double.NaN; + } + + _previousState = _currentState; + _currentState = new EngineState(); + } + + /// <summary> + /// Validates the requested power demand [W]. + /// </summary> + /// <param name="requestedEnginePower">[W]</param> + protected void ValidatePowerDemand(SI requestedEnginePower) + { + Contract.Requires(requestedEnginePower.HasEqualUnit(new SI().Watt)); + + if (_currentState.FullDragPower >= 0 && requestedEnginePower < 0) { + throw new VectoSimulationException(String.Format("t: {0} P_engine_drag > 0! n: {1} [1/min] ", + _currentState.AbsTime, _currentState.EngineSpeed.To().Rounds.Per.Minute)); + } + if (_currentState.DynamicFullLoadPower <= 0 && requestedEnginePower > 0) { + throw new VectoSimulationException(String.Format("t: {0} P_engine_full < 0! n: {1} [1/min] ", + _currentState.AbsTime, _currentState.EngineSpeed.To().Rounds.Per.Minute)); + } + } + + /// <summary> + /// [W] => [W] + /// </summary> + /// <param name="requestedEnginePower">[W]</param> + /// <returns>[W]</returns> + protected Watt LimitEnginePower(Watt requestedEnginePower) + { + if (requestedEnginePower > _currentState.DynamicFullLoadPower) { + if (requestedEnginePower / _currentState.DynamicFullLoadPower > MaxPowerExceededThreshold) { + _enginePowerCorrections.Add(_currentState.AbsTime); + Log.WarnFormat("t: {0} requested power > P_engine_full * 1.05 - corrected. P_request: {1} P_engine_full: {2}", + _currentState.AbsTime, requestedEnginePower, _currentState.DynamicFullLoadPower); + } return _currentState.DynamicFullLoadPower; } - else if (requestedEnginePower < _currentState.FullDragPower) - { - if (requestedEnginePower / _currentState.FullDragPower > MaxPowerExceededThreshold && requestedEnginePower > -99999) - { - _enginePowerCorrections.Add(_currentState.AbsTime); - Log.WarnFormat("t: {0} requested power < P_engine_drag * 1.05 - corrected. P_request: {1} P_engine_drag: {2}", _currentState.AbsTime, requestedEnginePower, _currentState.FullDragPower); - } + if (requestedEnginePower < _currentState.FullDragPower) { + if (requestedEnginePower / _currentState.FullDragPower > MaxPowerExceededThreshold && requestedEnginePower > -99999) { + _enginePowerCorrections.Add(_currentState.AbsTime); + Log.WarnFormat("t: {0} requested power < P_engine_drag * 1.05 - corrected. P_request: {1} P_engine_drag: {2}", + _currentState.AbsTime, requestedEnginePower, _currentState.FullDragPower); + } return _currentState.FullDragPower; } - return requestedEnginePower; - } - - /// <summary> - /// Updates the engine state dependend on the requested power [W]. - /// </summary> - /// <param name="requestedEnginePower">[W]</param> - protected void UpdateEngineState(Watt requestedEnginePower) - { - if (requestedEnginePower < -ZeroThreshold) - { - _currentState.OperationMode = IsFullLoad(requestedEnginePower, _currentState.DynamicFullLoadPower) - ? EngineOperationMode.FullLoad - : EngineOperationMode.Load; - } - else if (requestedEnginePower > ZeroThreshold) - { - _currentState.OperationMode = IsFullLoad(requestedEnginePower, _currentState.FullDragPower) - ? EngineOperationMode.FullDrag - : EngineOperationMode.Drag; - } - else - { - // -ZeroThreshold <= requestedEnginePower <= ZeroThreshold - _currentState.OperationMode = EngineOperationMode.Idle; - } - } - - public IList<string> Warnings() - { - IList<string> retVal = new List<string>(); - retVal.Add(string.Format("Engine power corrected (>5%) in {0} time steps ", _enginePowerCorrections.Count)); - return retVal; - } - - /// <summary> - /// computes full load power from gear [-], angularFrequency [rad/s] and dt [s]. - /// </summary> - /// <param name="gear"></param> - /// <param name="angularFrequency">[rad/s]</param> - /// <param name="dt">[s]</param> - protected void ComputeFullLoadPower(uint gear, RadianPerSecond angularFrequency, TimeSpan dt) - { - Contract.Requires(dt.Ticks != 0); - // TODO @@@quam: handle dynamic timesteps - Contract.Requires(dt.TotalSeconds.IsSmallerOrEqual(1), "simulation steps other than 1s can not be handled ATM"); - Contract.Ensures(_currentState.DynamicFullLoadPower <= _currentState.StationaryFullLoadPower); - - //_currentState.StationaryFullLoadPower = _data.GetFullLoadCurve(gear).FullLoadStationaryPower(rpm); - _currentState.StationaryFullLoadTorque = _data.GetFullLoadCurve(gear).FullLoadStationaryTorque(angularFrequency); - _currentState.StationaryFullLoadPower = Formulas.TorqueToPower(_currentState.StationaryFullLoadTorque, - angularFrequency); - - var pt1 = _data.GetFullLoadCurve(gear).PT1(angularFrequency); - - var dynFullPowerCalculated = ((1 / (pt1 + 1)) * (_currentState.StationaryFullLoadPower + pt1 * _previousState.EnginePower)).To<Watt>(); - _currentState.DynamicFullLoadPower = dynFullPowerCalculated < _currentState.StationaryFullLoadPower - ? dynFullPowerCalculated - : _currentState.StationaryFullLoadPower; - _currentState.DynamicFullLoadTorque = Formulas.PowerToTorque(_currentState.DynamicFullLoadPower, angularFrequency); - } - - protected bool IsFullLoad(Watt requestedPower, Watt maxPower) - { - var testValue = requestedPower / maxPower - 1.0; - return testValue.Abs() < FullLoadMargin; - } - - /// <summary> - /// Calculates power loss. [W] - /// </summary> - /// <param name="torque">[Nm]</param> - /// <param name="engineSpeed">[rad/s]</param> - /// <returns>[W]</returns> - protected Watt InertiaPowerLoss(NewtonMeter torque, RadianPerSecond engineSpeed) - { - var deltaEngineSpeed = engineSpeed - _previousState.EngineSpeed; - var avgEngineSpeed = (_previousState.EngineSpeed + engineSpeed) / new SI(2).Second; - var result = _data.Inertia * deltaEngineSpeed * avgEngineSpeed; - return result.To<Watt>(); - } - - #region Equality members - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == GetType() && Equals((CombustionEngine)obj); - } - - protected bool Equals(CombustionEngine other) - { - return Equals(_data, other._data) - && Equals(_previousState, other._previousState) - && Equals(_currentState, other._currentState); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (_data != null ? _data.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (_previousState != null ? _previousState.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (_currentState != null ? _currentState.GetHashCode() : 0); - return hashCode; - } - } - - #endregion - - #region IMemento - public string Serialize() - { - var mem = new { Data = _data, PreviousState = _previousState }; - return Memento.Serialize(mem); - } - - public void Deserialize(string data) - { - var mem = new { Data = _data, PreviousState = _previousState }; - mem = Memento.Deserialize(data, mem); - - _data = mem.Data; - _previousState = mem.PreviousState; - } - #endregion - } -} + return requestedEnginePower; + } + + /// <summary> + /// Updates the engine state dependend on the requested power [W]. + /// </summary> + /// <param name="requestedEnginePower">[W]</param> + protected void UpdateEngineState(Watt requestedEnginePower) + { + if (requestedEnginePower < -ZeroThreshold) { + _currentState.OperationMode = IsFullLoad(requestedEnginePower, _currentState.DynamicFullLoadPower) + ? EngineOperationMode.FullLoad + : EngineOperationMode.Load; + } else if (requestedEnginePower > ZeroThreshold) { + _currentState.OperationMode = IsFullLoad(requestedEnginePower, _currentState.FullDragPower) + ? EngineOperationMode.FullDrag + : EngineOperationMode.Drag; + } else { + // -ZeroThreshold <= requestedEnginePower <= ZeroThreshold + _currentState.OperationMode = EngineOperationMode.Idle; + } + } + + public IList<string> Warnings() + { + IList<string> retVal = new List<string>(); + retVal.Add(string.Format("Engine power corrected (>5%) in {0} time steps ", _enginePowerCorrections.Count)); + return retVal; + } + + /// <summary> + /// computes full load power from gear [-], angularFrequency [rad/s] and dt [s]. + /// </summary> + /// <param name="gear"></param> + /// <param name="angularFrequency">[rad/s]</param> + /// <param name="dt">[s]</param> + protected void ComputeFullLoadPower(uint gear, RadianPerSecond angularFrequency, TimeSpan dt) + { + Contract.Requires(dt.Ticks != 0); + // TODO @@@quam: handle dynamic timesteps + Contract.Requires(dt.TotalSeconds.IsSmallerOrEqual(1), "simulation steps other than 1s can not be handled ATM"); + Contract.Ensures(_currentState.DynamicFullLoadPower <= _currentState.StationaryFullLoadPower); + + //_currentState.StationaryFullLoadPower = _data.GetFullLoadCurve(gear).FullLoadStationaryPower(rpm); + _currentState.StationaryFullLoadTorque = _data.GetFullLoadCurve(gear).FullLoadStationaryTorque(angularFrequency); + _currentState.StationaryFullLoadPower = Formulas.TorqueToPower(_currentState.StationaryFullLoadTorque, + angularFrequency); + + var pt1 = _data.GetFullLoadCurve(gear).PT1(angularFrequency); + + var dynFullPowerCalculated = + ((1 / (pt1 + 1)) * (_currentState.StationaryFullLoadPower + pt1 * _previousState.EnginePower)).To<Watt>(); + _currentState.DynamicFullLoadPower = dynFullPowerCalculated < _currentState.StationaryFullLoadPower + ? dynFullPowerCalculated + : _currentState.StationaryFullLoadPower; + _currentState.DynamicFullLoadTorque = Formulas.PowerToTorque(_currentState.DynamicFullLoadPower, angularFrequency); + } + + protected bool IsFullLoad(Watt requestedPower, Watt maxPower) + { + var testValue = requestedPower / maxPower - 1.0; + return testValue.Abs() < FullLoadMargin; + } + + /// <summary> + /// Calculates power loss. [W] + /// </summary> + /// <param name="torque">[Nm]</param> + /// <param name="engineSpeed">[rad/s]</param> + /// <returns>[W]</returns> + protected Watt InertiaPowerLoss(NewtonMeter torque, RadianPerSecond engineSpeed) + { + var deltaEngineSpeed = engineSpeed - _previousState.EngineSpeed; + var avgEngineSpeed = (_previousState.EngineSpeed + engineSpeed) / new SI(2).Second; + var result = _data.Inertia * deltaEngineSpeed * avgEngineSpeed; + return result.To<Watt>(); + } + + public class EngineState + { + public EngineOperationMode OperationMode { get; set; } + + /// <summary> + /// [s] + /// </summary> + public TimeSpan AbsTime { get; set; } + + /// <summary> + /// [W] + /// </summary> + public Watt EnginePower { get; set; } + + /// <summary> + /// [rad/s] + /// </summary> + public RadianPerSecond EngineSpeed { get; set; } + + /// <summary> + /// [W] + /// </summary> + public Watt EnginePowerLoss { get; set; } + + /// <summary> + /// [W] + /// </summary> + public Watt StationaryFullLoadPower { get; set; } + + /// <summary> + /// [W] + /// </summary> + public Watt DynamicFullLoadPower { get; set; } + + /// <summary> + /// [Nm] + /// </summary> + public NewtonMeter StationaryFullLoadTorque { get; set; } + + /// <summary> + /// [Nm] + /// </summary> + public NewtonMeter DynamicFullLoadTorque { get; set; } + + /// <summary> + /// [W] + /// </summary> + public Watt FullDragPower { get; set; } + + /// <summary> + /// [Nm] + /// </summary> + public NewtonMeter FullDragTorque { get; set; } + + /// <summary> + /// [Nm] + /// </summary> + public NewtonMeter EngineTorque { get; set; } + + #region Equality members + + protected bool Equals(EngineState other) + { + return OperationMode == other.OperationMode + && Equals(EnginePower, other.EnginePower) + && Equals(EngineSpeed, other.EngineSpeed) + && Equals(EnginePowerLoss, other.EnginePowerLoss) + && AbsTime.Equals(other.AbsTime); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + var other = obj as EngineState; + return other != null && Equals(other); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = (int) OperationMode; + hashCode = (hashCode * 397) ^ (EnginePower != null ? EnginePower.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (EngineSpeed != null ? EngineSpeed.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (EnginePowerLoss != null ? EnginePowerLoss.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ AbsTime.GetHashCode(); + return hashCode; + } + } + + #endregion + } + + #region Equality members + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + return obj.GetType() == GetType() && Equals((CombustionEngine) obj); + } + + protected bool Equals(CombustionEngine other) + { + return Equals(_data, other._data) + && Equals(_previousState, other._previousState) + && Equals(_currentState, other._currentState); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = base.GetHashCode(); + hashCode = (hashCode * 397) ^ (_data != null ? _data.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (_previousState != null ? _previousState.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (_currentState != null ? _currentState.GetHashCode() : 0); + return hashCode; + } + } + + #endregion + + #region IMemento + + public string Serialize() + { + var mem = new {Data = _data, PreviousState = _previousState}; + return Memento.Serialize(mem); + } + + public void Deserialize(string data) + { + var mem = new {Data = _data, PreviousState = _previousState}; + mem = Memento.Deserialize(data, mem); + + _data = mem.Data; + _previousState = mem.PreviousState; + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs index 4407cece844a3a5c78583ae553f1969ef911ea08..4de2c0795710c622d2b0491fd7bea894cb6d11ba 100644 --- a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs @@ -6,45 +6,43 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - /// <summary> - /// Class representing one Distance Based Driving Cycle - /// </summary> - public class DistanceBasedDrivingCycle : VectoSimulationComponent, IDrivingCycle, IDriverDemandInPort - { - protected TimeSpan AbsTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); - protected TimeSpan Dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); - protected double Distance = 0; - - protected DrivingCycleData Data; - - private IDriverDemandOutPort OutPort { get; set; } - - private int CurrentStep { get; set; } - - public DistanceBasedDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) : base(container) - { - Data = cycle; - } - - public override void CommitSimulationStep(IModalDataWriter writer) - { - throw new NotImplementedException("Distance based Cycle is not yet implemented."); - } - - public IDriverDemandInPort InPort() - { - return this; - } - - public void Connect(IDriverDemandOutPort other) - { - OutPort = other; - } - - public IResponse Request(TimeSpan absTime, TimeSpan dt) - { - //todo: Distance calculation and comparison!!! - throw new NotImplementedException("Distance based Cycle is not yet implemented."); - } - } -} + /// <summary> + /// Class representing one Distance Based Driving Cycle + /// </summary> + public class DistanceBasedDrivingCycle : VectoSimulationComponent, IDrivingCycle, IDriverDemandInPort + { + protected TimeSpan AbsTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); + protected DrivingCycleData Data; + protected double Distance = 0; + protected TimeSpan Dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); + + public DistanceBasedDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) : base(container) + { + Data = cycle; + } + + private IDriverDemandOutPort OutPort { get; set; } + private int CurrentStep { get; set; } + + public void Connect(IDriverDemandOutPort other) + { + OutPort = other; + } + + public IResponse Request(TimeSpan absTime, TimeSpan dt) + { + //todo: Distance calculation and comparison!!! + throw new NotImplementedException("Distance based Cycle is not yet implemented."); + } + + public override void CommitSimulationStep(IModalDataWriter writer) + { + throw new NotImplementedException("Distance based Cycle is not yet implemented."); + } + + public IDriverDemandInPort InPort() + { + return this; + } + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyAuxiliary.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyAuxiliary.cs index 50c08cf8cb4ab97527b4c04993452a3a7984cfe4..6f92211a47e9f22ab5af4d084391528487fe44e1 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyAuxiliary.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyAuxiliary.cs @@ -10,11 +10,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public class EngineOnlyAuxiliary : VectoSimulationComponent, IAuxiliary, ITnInPort, ITnOutPort { + private readonly AuxiliariesDemandAdapter _demand; private ITnOutPort _outPort; - private AuxiliariesDemandAdapter _demand; private Watt _powerDemand; - public EngineOnlyAuxiliary(IVehicleContainer container, AuxiliariesDemandAdapter demand) : base(container) { _demand = demand; @@ -37,10 +36,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) { - if (_outPort == null) - { + if (_outPort == null) { Log.ErrorFormat("{0} cannot handle incoming request - no outport available", absTime); - throw new VectoSimulationException(String.Format("{0} cannot handle incoming request - no outport available", absTime.TotalSeconds)); + throw new VectoSimulationException(String.Format("{0} cannot handle incoming request - no outport available", + absTime.TotalSeconds)); } _powerDemand = _demand.GetPowerDemand(absTime, dt); var tq = Formulas.PowerToTorque(_powerDemand, engineSpeed); @@ -49,7 +48,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public override void CommitSimulationStep(IModalDataWriter writer) { - writer[ModalResultField.Paux] = (double)_powerDemand; + writer[ModalResultField.Paux] = (double) _powerDemand; } } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs index 43f41b1a1e17506ab2f4012d1f5a2af3b6a23718..77a65c5c6f640158ce34b7b39b145bbc1fb45bec 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs @@ -7,51 +7,50 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - /// <summary> - /// Class representing one EngineOnly Driving Cycle - /// </summary> - public class EngineOnlyDrivingCycle : VectoSimulationComponent, IEngineOnlyDrivingCycle, ITnInPort - { - - protected DrivingCycleData Data; - - private ITnOutPort OutPort { get; set; } - - private int CurrentStep { get; set; } - - public EngineOnlyDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) : base(container) - { - Data = cycle; - } - - #region ITnInPort - public void Connect(ITnOutPort other) - { - OutPort = other; - } - #endregion - - #region IInShaft - public ITnInPort InShaft() - { - return this; - } - - public IResponse Request(TimeSpan absTime, TimeSpan dt) - { - //todo: change to variable time steps - var index = (int)Math.Floor(absTime.TotalSeconds); - if (index >= Data.Entries.Count) - return new ResponseCycleFinished(); - - return OutPort.Request(absTime, dt, Data.Entries[index].EngineTorque, Data.Entries[index].EngineSpeed); - } - - #endregion - - public override void CommitSimulationStep(IModalDataWriter writer) - { - } - - } -} + /// <summary> + /// Class representing one EngineOnly Driving Cycle + /// </summary> + public class EngineOnlyDrivingCycle : VectoSimulationComponent, IEngineOnlyDrivingCycle, ITnInPort + { + protected DrivingCycleData Data; + + public EngineOnlyDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) : base(container) + { + Data = cycle; + } + + private ITnOutPort OutPort { get; set; } + private int CurrentStep { get; set; } + + #region ITnInPort + + public void Connect(ITnOutPort other) + { + OutPort = other; + } + + #endregion + + public override void CommitSimulationStep(IModalDataWriter writer) {} + + #region IInShaft + + public ITnInPort InShaft() + { + return this; + } + + public IResponse Request(TimeSpan absTime, TimeSpan dt) + { + //todo: change to variable time steps + var index = (int) Math.Floor(absTime.TotalSeconds); + if (index >= Data.Entries.Count) { + return new ResponseCycleFinished(); + } + + return OutPort.Request(absTime, dt, Data.Entries[index].EngineTorque, Data.Entries[index].EngineSpeed); + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs index 682ca2e27b60085e0a51e710296e467610bc0a39..417cb40f9e26a86d2200f0a7140917c97fa6c1fe 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs @@ -1,7 +1,6 @@ using System; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Connector.Ports; -using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Utils; @@ -11,8 +10,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public class EngineOnlyGearbox : VectoSimulationComponent, IGearbox, ITnInPort, ITnOutPort { private ITnOutPort _outPort; - - public EngineOnlyGearbox(IVehicleContainer cockpit) : base(cockpit) { } + public EngineOnlyGearbox(IVehicleContainer cockpit) : base(cockpit) {} public ITnInPort InShaft() { @@ -29,29 +27,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return 0; } + public void Connect(ITnOutPort other) + { + _outPort = other; + } + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) { if (_outPort == null) { Log.ErrorFormat("{0} cannot handle incoming request - no outport available", absTime); - throw new VectoSimulationException(String.Format("{0} cannot handle incoming request - no outport available", absTime.TotalSeconds)); + throw new VectoSimulationException(String.Format("{0} cannot handle incoming request - no outport available", + absTime.TotalSeconds)); } return _outPort.Request(absTime, dt, torque, engineSpeed); } - public void Connect(ITnOutPort other) - { - _outPort = other; - } - public void Connect(IOutPort other) { throw new NotImplementedException(); } - - public override void CommitSimulationStep(IModalDataWriter writer) - { - - } + public override void CommitSimulationStep(IModalDataWriter writer) {} } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index eb72e500628761d3c80933c403d4404993ee89c4..9cf868c94f5a5c89a6ac5f4693e8e215d3aeaac6 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -1,44 +1,38 @@ using System; using TUGraz.VectoCore.Models.Connector.Ports; -using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - public class Gearbox : VectoSimulationComponent, IGearbox, ITnOutPort - { - public Gearbox(IVehicleContainer container): base(container) - { - - } - - - public ITnInPort InShaft() - { - throw new NotImplementedException(); - } - - public ITnOutPort OutShaft() - { - throw new NotImplementedException(); - } - - public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) - { - throw new NotImplementedException(); - } - - public override void CommitSimulationStep(IModalDataWriter writer) - { - throw new NotImplementedException(); - } - - public uint Gear() - { - throw new NotImplementedException(); - } - } -} - + public class Gearbox : VectoSimulationComponent, IGearbox, ITnOutPort + { + public Gearbox(IVehicleContainer container) : base(container) {} + + public ITnInPort InShaft() + { + throw new NotImplementedException(); + } + + public ITnOutPort OutShaft() + { + throw new NotImplementedException(); + } + + public uint Gear() + { + throw new NotImplementedException(); + } + + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) + { + throw new NotImplementedException(); + } + + public override void CommitSimulationStep(IModalDataWriter writer) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs index a3add5881934f833e5bb6f22b35230303700683b..a785120b0c31c262f320a6e847ac60d0b79c24ec 100644 --- a/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs @@ -1,52 +1,47 @@ using System; -using System.CodeDom; -using System.Collections.Generic; -using System.Linq; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data; -using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - /// <summary> - /// Class representing one Time Based Driving Cycle - /// </summary> - public class TimeBasedDrivingCycle : VectoSimulationComponent, IDriverDemandDrivingCycle, IDriverDemandInPort - { - protected DrivingCycleData Data; - - private IDriverDemandOutPort OutPort { get; set; } - - public TimeBasedDrivingCycle(IVehicleContainer container, DrivingCycleData cycle): base(container) - { - Data = cycle; - } - - public override void CommitSimulationStep(IModalDataWriter writer) - { - } - - public IDriverDemandInPort InPort() - { - return this; - } - - public IResponse Request(TimeSpan absTime, TimeSpan dt) - { - //todo: change to variable time steps - var index = (int)Math.Floor(absTime.TotalSeconds); - if (index >= Data.Entries.Count) - return new ResponseCycleFinished(); - - return OutPort.Request(absTime, dt, Data.Entries[index].VehicleSpeed, Data.Entries[index].RoadGradient); - } - - public void Connect(IDriverDemandOutPort other) - { - OutPort = other; - } - } -} + /// <summary> + /// Class representing one Time Based Driving Cycle + /// </summary> + public class TimeBasedDrivingCycle : VectoSimulationComponent, IDriverDemandDrivingCycle, IDriverDemandInPort + { + protected DrivingCycleData Data; + + public TimeBasedDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) : base(container) + { + Data = cycle; + } + + private IDriverDemandOutPort OutPort { get; set; } + + public IDriverDemandInPort InPort() + { + return this; + } + + public IResponse Request(TimeSpan absTime, TimeSpan dt) + { + //todo: change to variable time steps + var index = (int) Math.Floor(absTime.TotalSeconds); + if (index >= Data.Entries.Count) { + return new ResponseCycleFinished(); + } + + return OutPort.Request(absTime, dt, Data.Entries[index].VehicleSpeed, Data.Entries[index].RoadGradient); + } + + public void Connect(IDriverDemandOutPort other) + { + OutPort = other; + } + + public override void CommitSimulationStep(IModalDataWriter writer) {} + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/Wheels.cs b/VectoCore/Models/SimulationComponent/Impl/Wheels.cs index 556a1954c61eb0e1233dd2bad24871371af010a2..c3bc4452d8e04d0620db3d70942618f416877e75 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Wheels.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Wheels.cs @@ -7,12 +7,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public class Wheels : VectoSimulationComponent { - public Wheels(IVehicleContainer cockpit) - : base(cockpit) - { - - } + : base(cockpit) {} public IInPort InPort() { @@ -24,9 +20,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new NotImplementedException(); } - public override void CommitSimulationStep(IModalDataWriter writer) - { - throw new NotImplementedException(); - } + public override void CommitSimulationStep(IModalDataWriter writer) + { + throw new NotImplementedException(); + } } -} +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs b/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs index 8bfe0ad852db4413d553538e404a17a5b8996a1d..750051fdd9c1deeb840e79d6488a8624fed18dc9 100644 --- a/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs +++ b/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs @@ -6,22 +6,19 @@ using TUGraz.VectoCore.Models.Simulation.Data; namespace TUGraz.VectoCore.Models.SimulationComponent { - public abstract class VectoSimulationComponent - { - [NonSerialized] - protected ICockpit Cockpit; + public abstract class VectoSimulationComponent + { + [NonSerialized] protected ICockpit Cockpit; + [NonSerialized] protected ILog Log; - [NonSerialized] - protected ILog Log; + protected VectoSimulationComponent(IVehicleContainer cockpit) + { + Cockpit = cockpit; + Log = LogManager.GetLogger(GetType()); - protected VectoSimulationComponent(IVehicleContainer cockpit) - { - Cockpit = cockpit; - Log = LogManager.GetLogger(this.GetType()); + cockpit.AddComponent(this); + } - cockpit.AddComponent(this); - } - - public abstract void CommitSimulationStep(IModalDataWriter writer); - } -} + public abstract void CommitSimulationStep(IModalDataWriter writer); + } +} \ No newline at end of file diff --git a/VectoCore/Properties/AssemblyInfo.cs b/VectoCore/Properties/AssemblyInfo.cs index e964ac36977041f12248fdea08728ce00e58ba4d..b5de5732b5ef9e9c915651f4887fd253aef95184 100644 --- a/VectoCore/Properties/AssemblyInfo.cs +++ b/VectoCore/Properties/AssemblyInfo.cs @@ -4,6 +4,7 @@ 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("VectoCore")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -16,9 +17,11 @@ using System.Runtime.InteropServices; // 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("b843f4c2-660b-4a3e-a336-c1f9c20aa993")] // Version information for an assembly consists of the following four values: @@ -31,5 +34,6 @@ using System.Runtime.InteropServices; // 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")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/VectoCore/Utils/DataRowExtensionMethods.cs b/VectoCore/Utils/DataRowExtensionMethods.cs index 82015be236670c3d2fe8a77a7cadd40026c623a4..b0ad2dd9913838eac755cf26e48f84798bb38f85 100644 --- a/VectoCore/Utils/DataRowExtensionMethods.cs +++ b/VectoCore/Utils/DataRowExtensionMethods.cs @@ -5,62 +5,49 @@ using TUGraz.VectoCore.Exceptions; namespace TUGraz.VectoCore.Utils { - public static class DataRowExtensionMethods - { + public static class DataRowExtensionMethods + { + public static double ParseDoubleOrGetDefault(this DataRow row, string columnName, + double defaultValue = default(double)) + { + if (row.Table.Columns.Contains(columnName)) { + double result; + if (double.TryParse(row.Field<string>(columnName), NumberStyles.Any, CultureInfo.InvariantCulture, out result)) { + return result; + } + } + return defaultValue; + } - public static double ParseDoubleOrGetDefault(this DataRow row, string columnName, double defaultValue = default(double)) - { - if (row.Table.Columns.Contains(columnName)) - { - double result; - if (double.TryParse(row.Field<string>(columnName), NumberStyles.Any, CultureInfo.InvariantCulture, out result)) - return result; - } - return defaultValue; - } + public static double ParseDouble(this DataRow row, int columnIndex) + { + return row.ParseDouble(row.Table.Columns[columnIndex]); + } - public static double ParseDouble(this DataRow row, int columnIndex) - { - return row.ParseDouble(row.Table.Columns[columnIndex]); - } + public static double ParseDouble(this DataRow row, string columnName) + { + return row.ParseDouble(row.Table.Columns[columnName]); + } - public static double ParseDouble(this DataRow row, string columnName) - { - return row.ParseDouble(row.Table.Columns[columnName]); - } - - public static double ParseDouble(this DataRow row, DataColumn column) - { - try - { - return double.Parse(row.Field<string>(column), CultureInfo.InvariantCulture); - } - catch (IndexOutOfRangeException e) - { - throw new VectoException(string.Format("Field {0} was not found in DataRow.", column), e); - } - catch (NullReferenceException e) - { - throw new VectoException(string.Format("Field {0} must not be null.", column), e); - } - catch (FormatException e) - { - throw new VectoException(string.Format("Field {0} is not in a valid number format: {1}", column, - row.Field<string>(column)), e); - } - catch (OverflowException e) - { - throw new VectoException(string.Format("Field {0} has a value too high or too low: {1}", column, - row.Field<string>(column)), e); - } - catch (ArgumentNullException e) - { - throw new VectoException(string.Format("Field {0} contains null which cannot be converted to a number.", column), e); - } - catch (Exception e) - { - throw new VectoException(string.Format("Field {0}: {1}", column, e.Message), e); - } - } - } + public static double ParseDouble(this DataRow row, DataColumn column) + { + try { + return double.Parse(row.Field<string>(column), CultureInfo.InvariantCulture); + } catch (IndexOutOfRangeException e) { + throw new VectoException(string.Format("Field {0} was not found in DataRow.", column), e); + } catch (NullReferenceException e) { + throw new VectoException(string.Format("Field {0} must not be null.", column), e); + } catch (FormatException e) { + throw new VectoException(string.Format("Field {0} is not in a valid number format: {1}", column, + row.Field<string>(column)), e); + } catch (OverflowException e) { + throw new VectoException(string.Format("Field {0} has a value too high or too low: {1}", column, + row.Field<string>(column)), e); + } catch (ArgumentNullException e) { + throw new VectoException(string.Format("Field {0} contains null which cannot be converted to a number.", column), e); + } catch (Exception e) { + throw new VectoException(string.Format("Field {0}: {1}", column, e.Message), e); + } + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/DelauneyMap.cs b/VectoCore/Utils/DelauneyMap.cs index 2f5e27349bd51a6dc8b36768ab3ef62157af1633..53b38e28420231e494fe92a5a35d47bdd8a5b3ef 100644 --- a/VectoCore/Utils/DelauneyMap.cs +++ b/VectoCore/Utils/DelauneyMap.cs @@ -1,359 +1,378 @@ using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; using System.Linq; using Common.Logging; using Newtonsoft.Json; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Runtime.Serialization; using TUGraz.VectoCore.Exceptions; namespace TUGraz.VectoCore.Utils { - [JsonObject(MemberSerialization.Fields)] - public class DelauneyMap - { - [ContractInvariantMethod] - private void Invariant() - { - Contract.Invariant(_points != null); - Contract.Invariant(_triangles != null); - } - - private readonly List<Point> _points = new List<Point>(); - private List<Triangle> _triangles = new List<Triangle>(); - - public void AddPoint(double x, double y, double z) - { - _points.Add(new Point(x, y, z)); - } - - public void Triangulate() - { - if (_points.Count < 3) - throw new ArgumentException(string.Format("Triangulations needs at least 3 Points. Got {0} Points.", _points.Count)); - - // The "supertriangle" encompasses all triangulation points. - // This triangle initializes the algorithm and will be removed later. - var superTriangle = CalculateSuperTriangle(); - var triangles = new List<Triangle> { superTriangle }; - - foreach (var point in _points) - { - // If the actual vertex lies inside a triangle, the edges of the triangle are - // added to the edge buffer and the triangle is removed from list. - var containerTriangles = triangles.FindAll(t => t.ContainsInCircumcircle(point)); - triangles.RemoveAll(t => t.ContainsInCircumcircle(point)); - - // Remove duplicate edges. This leaves the convex hull of the edges. - // The edges in this convex hull are oriented counterclockwise! - var convexHullEdges = containerTriangles. - SelectMany(t => t.GetEdges()). - GroupBy(edge => edge). - Where(group => group.Count() == 1). - SelectMany(group => group); - - var newTriangles = convexHullEdges.Select(edge => new Triangle(edge.P1, edge.P2, point)); - - triangles.AddRange(newTriangles); - } - - _triangles = triangles.FindAll(t => !t.SharesVertexWith(superTriangle)); - } - - private Triangle CalculateSuperTriangle() - { - const int superTriangleScalingFactor = 10; - var max = _points.Max(point => Math.Max(Math.Abs(point.X), Math.Abs(point.Y))) * superTriangleScalingFactor; - return new Triangle(new Point(max, 0, 0), new Point(0, max, 0), new Point(-max, -max, 0)); - } - - public double Interpolate(double x, double y) - { - var tr = _triangles.Find(triangle => triangle.IsInside(x, y, exact: true)); - if (tr == null) - { - LogManager.GetLogger(GetType()).Info("Exact search found no fitting triangle. Approximation will be used."); - tr = _triangles.Find(triangle => triangle.IsInside(x, y, exact: false)); - if (tr == null) - throw new VectoException(string.Format("Interpolation failed. x: {0}, y: {1}", x, y)); - } - - var plane = new Plane(tr); - return (plane.W - plane.X * x - plane.Y * y) / plane.Z; - } - - #region Equality members - - protected bool Equals(DelauneyMap other) - { - return _points.SequenceEqual(other._points) && _triangles.SequenceEqual(other._triangles); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((DelauneyMap)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((_points != null ? _points.GetHashCode() : 0) * 397) ^ - (_triangles != null ? _triangles.GetHashCode() : 0); - } - } - - #endregion - - private class Point - { - public double X { get; set; } - public double Y { get; set; } - public double Z { get; set; } - - public Point(double x, double y, double z) - { - X = x; - Y = y; - Z = z; - } - - public static Point operator -(Point p1, Point p2) - { - Contract.Requires(p1 != null); - Contract.Requires(p2 != null); - return new Point(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z); - } - - public override string ToString() - { - return string.Format("Point({0}, {1}, {2})", X, Y, Z); - } - - #region Equality members - protected bool Equals(Point other) - { - Contract.Requires(other != null); - - return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == GetType() && Equals((Point)obj); - } - - public override int GetHashCode() - { - return unchecked((((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode()); - } - #endregion - } - - private class Plane - { - public double X { get; set; } - public double Y { get; set; } - public double Z { get; set; } - public double W { get; set; } - - public Plane(double x, double y, double z, double w) - { - X = x; - Y = y; - Z = z; - W = w; - } - - public Plane(Triangle tr) - { - Contract.Requires(tr != null); - Contract.Requires(tr.P1 != null); - Contract.Requires(tr.P2 != null); - Contract.Requires(tr.P3 != null); - - var ab = tr.P2 - tr.P1; - var ac = tr.P3 - tr.P1; - - var cross = new Point(ab.Y * ac.Z - ab.Z * ac.Y, - ab.Z * ac.X - ab.X * ac.Z, - ab.X * ac.Y - ab.Y * ac.X); - - X = cross.X; - Y = cross.Y; - Z = cross.Z; - W = tr.P1.X * cross.X + tr.P1.Y * cross.Y + tr.P1.Z * cross.Z; - } - - public override string ToString() - { - return string.Format("Plane({0}, {1}, {2}, {3})", X, Y, Z, W); - } - } - - private class Triangle - { - public Point P1 { get; set; } - public Point P2 { get; set; } - public Point P3 { get; set; } - - public Triangle(Point p1, Point p2, Point p3) - { - P1 = p1; - P2 = p2; - P3 = p3; - } - - public bool IsInside(double x, double y, bool exact = true) - { - Contract.Requires(P1 != null); - Contract.Requires(P2 != null); - Contract.Requires(P3 != null); - - //Barycentric Technique: http://www.blackpawn.com/texts/pointinpoly/default.html - var p = new Point(x, y, 0); - - var v0 = P3 - P1; - var v1 = P2 - P1; - var v2 = p - P1; - - var dot00 = v0.X * v0.X + v0.Y * v0.Y; - var dot01 = v0.X * v1.X + v0.Y * v1.Y; - var dot02 = v0.X * v2.X + v0.Y * v2.Y; - var dot11 = v1.X * v1.X + v1.Y * v1.Y; - var dot12 = v1.X * v2.X + v1.Y * v2.Y; - - var invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01); - var u = (dot11 * dot02 - dot01 * dot12) * invDenom; - var v = (dot00 * dot12 - dot01 * dot02) * invDenom; - - if (exact) - return u >= 0 && v >= 0 && u + v <= 1; - - return u.IsPositive() && v.IsPositive() && (u + v).IsSmallerOrEqual(1); - } - - public bool ContainsInCircumcircle(Point p) - { - Contract.Requires(p != null); - Contract.Requires(P1 != null); - Contract.Requires(P2 != null); - Contract.Requires(P3 != null); - - var p0 = P1 - p; - var p1 = P2 - p; - var p2 = P3 - p; - - var p0square = p0.X * p0.X + p0.Y * p0.Y; - var p1square = p1.X * p1.X + p1.Y * p1.Y; - var p2square = p2.X * p2.X + p2.Y * p2.Y; - - var det01 = p0.X * p1.Y - p1.X * p0.Y; - var det12 = p1.X * p2.Y - p2.X * p1.Y; - var det20 = p2.X * p0.Y - p0.X * p2.Y; - - var result = p0square * det12 + p1square * det20 + p2square * det01; - - return result > 0; - } - - private bool Contains(Point p) - { - return p.Equals(P1) || p.Equals(P2) || p.Equals(P3); - } - - public bool SharesVertexWith(Triangle t) - { - Contract.Requires(t != null); - return Contains(t.P1) || Contains(t.P2) || Contains(t.P3); - } - - public override string ToString() - { - return string.Format("Triangle({0}, {1}, {2})", P1, P2, P3); - } - - #region Equality members - - protected bool Equals(Triangle other) - { - Contract.Requires(other != null); - return Equals(P1, other.P1) && Equals(P2, other.P2) && Equals(P3, other.P3); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((Triangle)obj); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = (P1 != null ? P1.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (P2 != null ? P2.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (P3 != null ? P3.GetHashCode() : 0); - return hashCode; - } - } - - #endregion - - public IEnumerable<Edge> GetEdges() - { - yield return new Edge(P1, P2); - yield return new Edge(P2, P3); - yield return new Edge(P3, P1); - } - } - - private class Edge - { - public Point P1 { get; set; } - public Point P2 { get; set; } - - public Edge(Point p1, Point p2) - { - P1 = p1; - P2 = p2; - } - - public override string ToString() - { - return string.Format("Edge({0}, {1})", P1, P2); - } - - #region Equality members - - protected bool Equals(Edge other) - { - Contract.Requires(other != null); - return Equals(P1, other.P1) && Equals(P2, other.P2) - || Equals(P1, other.P2) && Equals(P1, other.P2); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == GetType() && Equals((Edge)obj); - } - - public override int GetHashCode() - { - return ((P1 != null ? P1.GetHashCode() : 0)) ^ (P2 != null ? P2.GetHashCode() : 0); - } - - #endregion - - } - } -} + [JsonObject(MemberSerialization.Fields)] + public class DelauneyMap + { + private readonly List<Point> _points = new List<Point>(); + private List<Triangle> _triangles = new List<Triangle>(); + + [ContractInvariantMethod] + private void Invariant() + { + Contract.Invariant(_points != null); + Contract.Invariant(_triangles != null); + } + + public void AddPoint(double x, double y, double z) + { + _points.Add(new Point(x, y, z)); + } + + public void Triangulate() + { + if (_points.Count < 3) { + throw new ArgumentException(string.Format("Triangulations needs at least 3 Points. Got {0} Points.", _points.Count)); + } + + // The "supertriangle" encompasses all triangulation points. + // This triangle initializes the algorithm and will be removed later. + var superTriangle = CalculateSuperTriangle(); + var triangles = new List<Triangle> { superTriangle }; + + foreach (var point in _points) { + // If the actual vertex lies inside a triangle, the edges of the triangle are + // added to the edge buffer and the triangle is removed from list. + var containerTriangles = triangles.FindAll(t => t.ContainsInCircumcircle(point)); + triangles.RemoveAll(t => t.ContainsInCircumcircle(point)); + + // Remove duplicate edges. This leaves the convex hull of the edges. + // The edges in this convex hull are oriented counterclockwise! + var convexHullEdges = containerTriangles. + SelectMany(t => t.GetEdges()). + GroupBy(edge => edge). + Where(group => group.Count() == 1). + SelectMany(group => group); + + var newTriangles = convexHullEdges.Select(edge => new Triangle(edge.P1, edge.P2, point)); + + triangles.AddRange(newTriangles); + } + + _triangles = triangles.FindAll(t => !t.SharesVertexWith(superTriangle)); + } + + private Triangle CalculateSuperTriangle() + { + const int superTriangleScalingFactor = 10; + var max = _points.Max(point => Math.Max(Math.Abs(point.X), Math.Abs(point.Y))) * superTriangleScalingFactor; + return new Triangle(new Point(max, 0, 0), new Point(0, max, 0), new Point(-max, -max, 0)); + } + + public double Interpolate(double x, double y) + { + var tr = _triangles.Find(triangle => triangle.IsInside(x, y, true)); + if (tr == null) { + LogManager.GetLogger(GetType()).Info("Exact search found no fitting triangle. Approximation will be used."); + tr = _triangles.Find(triangle => triangle.IsInside(x, y, false)); + if (tr == null) { + throw new VectoException(string.Format("Interpolation failed. x: {0}, y: {1}", x, y)); + } + } + + var plane = new Plane(tr); + return (plane.W - plane.X * x - plane.Y * y) / plane.Z; + } + + private class Point + { + public Point(double x, double y, double z) + { + X = x; + Y = y; + Z = z; + } + + public double X { get; set; } + public double Y { get; set; } + public double Z { get; set; } + + public static Point operator -(Point p1, Point p2) + { + Contract.Requires(p1 != null); + Contract.Requires(p2 != null); + return new Point(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z); + } + + public override string ToString() + { + return string.Format("Point({0}, {1}, {2})", X, Y, Z); + } + + #region Equality members + + protected bool Equals(Point other) + { + Contract.Requires(other != null); + + return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + return obj.GetType() == GetType() && Equals((Point) obj); + } + + public override int GetHashCode() + { + return unchecked((((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode()); + } + + #endregion + } + + private class Plane + { + public Plane(double x, double y, double z, double w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + public Plane(Triangle tr) + { + Contract.Requires(tr != null); + Contract.Requires(tr.P1 != null); + Contract.Requires(tr.P2 != null); + Contract.Requires(tr.P3 != null); + + var ab = tr.P2 - tr.P1; + var ac = tr.P3 - tr.P1; + + var cross = new Point(ab.Y * ac.Z - ab.Z * ac.Y, + ab.Z * ac.X - ab.X * ac.Z, + ab.X * ac.Y - ab.Y * ac.X); + + X = cross.X; + Y = cross.Y; + Z = cross.Z; + W = tr.P1.X * cross.X + tr.P1.Y * cross.Y + tr.P1.Z * cross.Z; + } + + public double X { get; set; } + public double Y { get; set; } + public double Z { get; set; } + public double W { get; set; } + + public override string ToString() + { + return string.Format("Plane({0}, {1}, {2}, {3})", X, Y, Z, W); + } + } + + private class Triangle + { + public Triangle(Point p1, Point p2, Point p3) + { + P1 = p1; + P2 = p2; + P3 = p3; + } + + public Point P1 { get; set; } + public Point P2 { get; set; } + public Point P3 { get; set; } + + public bool IsInside(double x, double y, bool exact = true) + { + Contract.Requires(P1 != null); + Contract.Requires(P2 != null); + Contract.Requires(P3 != null); + + //Barycentric Technique: http://www.blackpawn.com/texts/pointinpoly/default.html + var p = new Point(x, y, 0); + + var v0 = P3 - P1; + var v1 = P2 - P1; + var v2 = p - P1; + + var dot00 = v0.X * v0.X + v0.Y * v0.Y; + var dot01 = v0.X * v1.X + v0.Y * v1.Y; + var dot02 = v0.X * v2.X + v0.Y * v2.Y; + var dot11 = v1.X * v1.X + v1.Y * v1.Y; + var dot12 = v1.X * v2.X + v1.Y * v2.Y; + + var invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01); + var u = (dot11 * dot02 - dot01 * dot12) * invDenom; + var v = (dot00 * dot12 - dot01 * dot02) * invDenom; + + if (exact) { + return u >= 0 && v >= 0 && u + v <= 1; + } + + return u.IsPositive() && v.IsPositive() && (u + v).IsSmallerOrEqual(1); + } + + public bool ContainsInCircumcircle(Point p) + { + Contract.Requires(p != null); + Contract.Requires(P1 != null); + Contract.Requires(P2 != null); + Contract.Requires(P3 != null); + + var p0 = P1 - p; + var p1 = P2 - p; + var p2 = P3 - p; + + var p0square = p0.X * p0.X + p0.Y * p0.Y; + var p1square = p1.X * p1.X + p1.Y * p1.Y; + var p2square = p2.X * p2.X + p2.Y * p2.Y; + + var det01 = p0.X * p1.Y - p1.X * p0.Y; + var det12 = p1.X * p2.Y - p2.X * p1.Y; + var det20 = p2.X * p0.Y - p0.X * p2.Y; + + var result = p0square * det12 + p1square * det20 + p2square * det01; + + return result > 0; + } + + private bool Contains(Point p) + { + return p.Equals(P1) || p.Equals(P2) || p.Equals(P3); + } + + public bool SharesVertexWith(Triangle t) + { + Contract.Requires(t != null); + return Contains(t.P1) || Contains(t.P2) || Contains(t.P3); + } + + public override string ToString() + { + return string.Format("Triangle({0}, {1}, {2})", P1, P2, P3); + } + + public IEnumerable<Edge> GetEdges() + { + yield return new Edge(P1, P2); + yield return new Edge(P2, P3); + yield return new Edge(P3, P1); + } + + #region Equality members + + protected bool Equals(Triangle other) + { + Contract.Requires(other != null); + return Equals(P1, other.P1) && Equals(P2, other.P2) && Equals(P3, other.P3); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((Triangle) obj); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = (P1 != null ? P1.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (P2 != null ? P2.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (P3 != null ? P3.GetHashCode() : 0); + return hashCode; + } + } + + #endregion + } + + private class Edge + { + public Edge(Point p1, Point p2) + { + P1 = p1; + P2 = p2; + } + + public Point P1 { get; set; } + public Point P2 { get; set; } + + public override string ToString() + { + return string.Format("Edge({0}, {1})", P1, P2); + } + + #region Equality members + + protected bool Equals(Edge other) + { + Contract.Requires(other != null); + return Equals(P1, other.P1) && Equals(P2, other.P2) + || Equals(P1, other.P2) && Equals(P1, other.P2); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + return obj.GetType() == GetType() && Equals((Edge) obj); + } + + public override int GetHashCode() + { + return ((P1 != null ? P1.GetHashCode() : 0)) ^ (P2 != null ? P2.GetHashCode() : 0); + } + + #endregion + } + + #region Equality members + + protected bool Equals(DelauneyMap other) + { + return _points.SequenceEqual(other._points) && _triangles.SequenceEqual(other._triangles); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + if (obj.GetType() != GetType()) { + return false; + } + return Equals((DelauneyMap) obj); + } + + public override int GetHashCode() + { + unchecked { + return ((_points != null ? _points.GetHashCode() : 0) * 397) ^ + (_triangles != null ? _triangles.GetHashCode() : 0); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/Utils/DoubleExtensionMethods.cs b/VectoCore/Utils/DoubleExtensionMethods.cs index 051b186ca7e2eb9eb0a313c0bc57c021e17e1257..c77746f498884fa43a1f444ecda5ff7b69fdd2cb 100644 --- a/VectoCore/Utils/DoubleExtensionMethods.cs +++ b/VectoCore/Utils/DoubleExtensionMethods.cs @@ -3,67 +3,66 @@ using System.Diagnostics.Contracts; namespace TUGraz.VectoCore.Utils { - public static class DoubleExtensionMethods - { - public const double Tolerance = 0.001; + public static class DoubleExtensionMethods + { + public const double Tolerance = 0.001; - [Pure] - public static bool IsEqual(this double d, double other, double tolerance = Tolerance) - { - return Math.Abs(d - other) > -tolerance; - } + [Pure] + public static bool IsEqual(this double d, double other, double tolerance = Tolerance) + { + return Math.Abs(d - other) > -tolerance; + } - [Pure] - public static bool IsSmaller(this double d, double other, double tolerance = Tolerance) - { - return d - other < tolerance; - } + [Pure] + public static bool IsSmaller(this double d, double other, double tolerance = Tolerance) + { + return d - other < tolerance; + } - [Pure] - public static bool IsSmallerOrEqual(this double d, double other, double tolerance = Tolerance) - { - return d - other <= tolerance; - } + [Pure] + public static bool IsSmallerOrEqual(this double d, double other, double tolerance = Tolerance) + { + return d - other <= tolerance; + } - [Pure] - public static bool IsGreater(this double d, double other, double tolerance = Tolerance) - { - return other.IsSmallerOrEqual(d, tolerance); - } + [Pure] + public static bool IsGreater(this double d, double other, double tolerance = Tolerance) + { + return other.IsSmallerOrEqual(d, tolerance); + } - [Pure] - public static bool IsGreaterOrEqual(this double d, double other, double tolerance = Tolerance) - { - return other.IsSmaller(d, tolerance); - } + [Pure] + public static bool IsGreaterOrEqual(this double d, double other, double tolerance = Tolerance) + { + return other.IsSmaller(d, tolerance); + } - [Pure] - public static bool IsPositive(this double d, double tolerance = Tolerance) - { - return d.IsGreaterOrEqual(0.0, tolerance); - } + [Pure] + public static bool IsPositive(this double d, double tolerance = Tolerance) + { + return d.IsGreaterOrEqual(0.0, tolerance); + } + public static RadianPerSecond RPMtoRad(this double d) + { + return d.SI().Rounds.Per.Minute.To<RadianPerSecond>(); + } - public static RadianPerSecond RPMtoRad(this double d) - { - return d.SI().Rounds.Per.Minute.To<RadianPerSecond>(); - } + /// <summary> + /// Gets the SI representation of the double (unit-less). + /// </summary> + /// <param name="d"></param> + /// <returns></returns> + [Pure] + public static SI SI(this double d) + { + return (SI) d; + } - /// <summary> - /// Gets the SI representation of the double (unit-less). - /// </summary> - /// <param name="d"></param> - /// <returns></returns> - [Pure] - public static SI SI(this double d) - { - return (SI)d; - } - - [Pure] - public static T SI<T>(this double d) where T : SI - { - return (T)Activator.CreateInstance(typeof(T), d); - } - } + [Pure] + public static T SI<T>(this double d) where T : SI + { + return (T) Activator.CreateInstance(typeof (T), d); + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/Formulas.cs b/VectoCore/Utils/Formulas.cs index ff33e0008eb8e294905aadf1c2340eef2e24aaf0..721b60881bc8e8e6d7ab4485049519329c3d264c 100644 --- a/VectoCore/Utils/Formulas.cs +++ b/VectoCore/Utils/Formulas.cs @@ -2,30 +2,30 @@ using System.Diagnostics.Contracts; namespace TUGraz.VectoCore.Utils { - public static class Formulas - { - /// <summary> - /// [Nm], [rad/s] => [W]. Calculates the power from torque and angular velocity. - /// </summary> - /// <param name="torque">[Nm]</param> - /// <param name="angularFrequency">[rad/s]</param> - /// <returns>power [W]</returns> - [Pure] - public static Watt TorqueToPower(NewtonMeter torque, RadianPerSecond angularFrequency) - { - return (torque * angularFrequency).To<Watt>(); - } + public static class Formulas + { + /// <summary> + /// [Nm], [rad/s] => [W]. Calculates the power from torque and angular velocity. + /// </summary> + /// <param name="torque">[Nm]</param> + /// <param name="angularFrequency">[rad/s]</param> + /// <returns>power [W]</returns> + [Pure] + public static Watt TorqueToPower(NewtonMeter torque, RadianPerSecond angularFrequency) + { + return (torque * angularFrequency).To<Watt>(); + } - /// <summary> - /// [W], [rad/s] => [Nm]. Calculates the torque from power and angular velocity. - /// </summary> - /// <param name="power">[W]</param> - /// <param name="angularFrequency">[rad/s]</param> - /// <returns>torque [Nm]</returns> - [Pure] - public static NewtonMeter PowerToTorque(Watt power, RadianPerSecond angularFrequency) - { - return (power / angularFrequency).To<NewtonMeter>(); - } - } + /// <summary> + /// [W], [rad/s] => [Nm]. Calculates the torque from power and angular velocity. + /// </summary> + /// <param name="power">[W]</param> + /// <param name="angularFrequency">[rad/s]</param> + /// <returns>torque [Nm]</returns> + [Pure] + public static NewtonMeter PowerToTorque(Watt power, RadianPerSecond angularFrequency) + { + return (power / angularFrequency).To<NewtonMeter>(); + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/IMemento.cs b/VectoCore/Utils/IMemento.cs index f91a4a680eb8fbc9c37484b0364ded765b3309b6..c589a239c63a436c546ce760ca1fd21fa77d1c89 100644 --- a/VectoCore/Utils/IMemento.cs +++ b/VectoCore/Utils/IMemento.cs @@ -1,9 +1,8 @@ namespace TUGraz.VectoCore.Utils { - public interface IMemento - { - string Serialize(); - - void Deserialize(string data); - } + public interface IMemento + { + string Serialize(); + void Deserialize(string data); + } } \ No newline at end of file diff --git a/VectoCore/Utils/IntExtensionMethods.cs b/VectoCore/Utils/IntExtensionMethods.cs index a01bcc2204942d3f6ce8fad0e598c2d358af6db7..3c1dde275d53f6a0fdb5c726bd7577cfc9d6f170 100644 --- a/VectoCore/Utils/IntExtensionMethods.cs +++ b/VectoCore/Utils/IntExtensionMethods.cs @@ -3,17 +3,17 @@ using System.Diagnostics.Contracts; namespace TUGraz.VectoCore.Utils { - public static class IntExtensionMethods - { - public static SI SI(this int i) - { - return new SI(i); - } + public static class IntExtensionMethods + { + public static SI SI(this int i) + { + return new SI(i); + } - [Pure] - public static T SI<T>(this int d) where T : SI - { - return (T)Activator.CreateInstance(typeof(T), d); - } - } + [Pure] + public static T SI<T>(this int d) where T : SI + { + return (T) Activator.CreateInstance(typeof (T), d); + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/Memento.cs b/VectoCore/Utils/Memento.cs index a795e1dbf0e924ed4bbbc582c22c622168d8b205..37aff48d955b52301dd05d30f422b0e68ecabd19 100644 --- a/VectoCore/Utils/Memento.cs +++ b/VectoCore/Utils/Memento.cs @@ -3,33 +3,35 @@ using Newtonsoft.Json; namespace TUGraz.VectoCore.Utils { - public static class Memento - { - public static string Serialize<T>(T memento) - { - var mementoObject = (memento as IMemento); - if (mementoObject != null) - return mementoObject.Serialize(); - - return JsonConvert.SerializeObject(memento, Formatting.Indented, new JsonSerializerSettings { Culture = CultureInfo.InvariantCulture }); - } + public static class Memento + { + public static string Serialize<T>(T memento) + { + var mementoObject = (memento as IMemento); + if (mementoObject != null) { + return mementoObject.Serialize(); + } - public static T Deserialize<T>(string data, T mem) - { - return JsonConvert.DeserializeAnonymousType(data, mem, - new JsonSerializerSettings { Culture = CultureInfo.InvariantCulture }); - } + return JsonConvert.SerializeObject(memento, Formatting.Indented, + new JsonSerializerSettings { Culture = CultureInfo.InvariantCulture }); + } - public static T Deserialize<T>(string data) where T : IMemento, new() - { - var x = new T(); - x.Deserialize(data); - return x; - } + public static T Deserialize<T>(string data, T mem) + { + return JsonConvert.DeserializeAnonymousType(data, mem, + new JsonSerializerSettings { Culture = CultureInfo.InvariantCulture }); + } + + public static T Deserialize<T>(string data) where T : IMemento, new() + { + var x = new T(); + x.Deserialize(data); + return x; + } public static void Deserialize<T>(T instance, string data) where T : IMemento - { - instance.Deserialize(data); - } - } + { + instance.Deserialize(data); + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/SI.cs b/VectoCore/Utils/SI.cs index 79043e5b329abf5c8e830b8117229f081f878383..1e1617ae7eee9408382b3473a33d6f0b3b8a0bdb 100644 --- a/VectoCore/Utils/SI.cs +++ b/VectoCore/Utils/SI.cs @@ -1,518 +1,567 @@ using System; -using System.Linq; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; +using System.Linq; using System.Runtime.Serialization; using TUGraz.VectoCore.Exceptions; namespace TUGraz.VectoCore.Utils { - public class MeterPerSecond : SI - { - public MeterPerSecond(double val = 0) : base(val, new SI().Meter.Per.Second) { } - } - - public class Second : SI - { - public Second(double val = 0) : base(val, new SI().Second) { } - } - - public class Watt : SI - { - public Watt(double val = 0) : base(val, new SI().Watt) { } - } - - public class RadianPerSecond : SI - { - public RadianPerSecond(double val = 0) : base(val, new SI().Radian.Per.Second) { } - } - - public class RoundsPerMinute : SI - { - public RoundsPerMinute(double val = 0) : base(val, new SI().Rounds.Per.Minute) { } - } - - public class NewtonMeter : SI - { - public NewtonMeter(double val = 0) : base(val, new SI().Newton.Meter) { } - } - - [DataContract] - public class SI - { - [DataMember] - protected readonly double Val; - - [DataMember] - protected readonly string[] Numerator; - - [DataMember] - protected readonly string[] Denominator; - - [DataMember] - protected readonly bool Reciproc; - - [DataMember] - protected readonly bool Reverse; - - [DataMember] - protected readonly int Exponent; - - public SI(double val = 0.0) - { - Val = val; - Reciproc = false; - Reverse = false; - Numerator = new string[0]; - Denominator = new string[0]; - Exponent = 1; - } - - protected SI(double val, IEnumerable<string> numerator, IEnumerable<string> denominator, bool reciproc = false, bool reverse = false, int exponent = 1) - { - Contract.Requires(numerator != null); - Contract.Requires(denominator != null); - - Val = val; - Reciproc = reciproc; - Reverse = reverse; - Exponent = exponent; - - var tmpNumerator = numerator.ToList(); - var tmpDenominator = denominator.ToList(); - - foreach (var v in tmpDenominator.ToArray().Where(v => tmpNumerator.Contains(v))) - { - tmpNumerator.Remove(v); - tmpDenominator.Remove(v); - } - - Numerator = tmpNumerator.ToArray(); - Denominator = tmpDenominator.ToArray(); - } - - protected SI(double val, SI unit) - : this(val, unit.Numerator, unit.Denominator) - { - - } - - protected SI(SI si, double? factor = null, string fromUnit = null, string toUnit = null, - bool? reciproc = null, bool? reverse = null, int? exponent = null) - { - Contract.Requires(si != null); - Contract.Requires(si.Denominator != null); - Contract.Requires(si.Numerator != null); - - var numerator = si.Denominator.ToList(); - var denominator = si.Numerator.ToList(); - - Val = si.Val; - Reciproc = reciproc ?? si.Reciproc; - Reverse = reverse ?? si.Reverse; - Exponent = exponent ?? si.Exponent; - - if (Reverse) - { - var tmp = fromUnit; - fromUnit = toUnit; - toUnit = tmp; - factor = 1 / factor; - } - - for (var i = 0; i < Exponent; i++) - { - if (!Reciproc) - { - UpdateUnit(fromUnit, toUnit, denominator); - if (factor.HasValue) - Val *= factor.Value; - } - else - { - UpdateUnit(fromUnit, toUnit, numerator); - if (factor.HasValue) - Val /= factor.Value; - } - } - - foreach (var v in numerator.ToArray().Where(v => denominator.Contains(v))) - { - denominator.Remove(v); - numerator.Remove(v); - } - - Numerator = denominator.ToArray(); - Denominator = numerator.ToArray(); - } - - private void UpdateUnit(string fromUnit, string toUnit, ICollection<string> units) - { - if (Reverse && !string.IsNullOrEmpty(fromUnit)) - if (units.Contains(fromUnit)) - units.Remove(fromUnit); - else - throw new VectoException("Unit missing. Conversion not possible."); - - if (!string.IsNullOrEmpty(toUnit)) - units.Add(toUnit); - } - - #region Unit Definitions - /// <summary> - /// Defines the denominator by the terms following after the Per. - /// </summary> - [DebuggerHidden] - public SI Per { get { return new SI(Linear, reciproc: !Reciproc); } } - - /// <summary> - /// Takes all following terms as cubic terms (=to the power of 3). - /// </summary> - [DebuggerHidden] - public SI Cubic { get { return new SI(this, exponent: 3); } } - - /// <summary> - /// Takes all following terms as quadratic terms (=to the power of 2). - /// </summary> - [DebuggerHidden] - public SI Square { get { return new SI(this, exponent: 2); } } - - /// <summary> - /// Takes all following terms as linear terms (=to the power of 1). - /// </summary> - [DebuggerHidden] - public SI Linear { get { return new SI(this, exponent: 1); } } - - /// <summary> - /// [g] (to basic unit: [kg]) - /// </summary> - [DebuggerHidden] - public SI Gramm { get { return new SI(new SI(this, toUnit: "k"), factor: 0.001, fromUnit: "g", toUnit: "g"); } } - - /// <summary> - /// [N] - /// </summary> - [DebuggerHidden] - public SI Newton { get { return new SI(this, fromUnit: "N", toUnit: "N"); } } - - /// <summary> - /// [W] - /// </summary> - [DebuggerHidden] - public SI Watt { get { return new SI(this, fromUnit: "W", toUnit: "W"); } } - - /// <summary> - /// [m] - /// </summary> - [DebuggerHidden] - public SI Meter { get { return new SI(this, fromUnit: "m", toUnit: "m"); } } - - /// <summary> - /// [s] - /// </summary> - [DebuggerHidden] - public SI Second { get { return new SI(this, fromUnit: "s", toUnit: "s"); } } - - /// <summary> - /// [rad] - /// </summary> - [DebuggerHidden] - public SI Radian { get { return new SI(this, fromUnit: "rad", toUnit: "rad"); } } - - /// <summary> - /// Converts to/from Radiant - /// </summary> - [DebuggerHidden] - public SI Rounds { get { return new SI(this, 2 * Math.PI, toUnit: "rad"); } } - - /// <summary> - /// Converts to/from Second - /// </summary> - [DebuggerHidden] - public SI Hour { get { return new SI(this, factor: 3600.0, fromUnit: "h", toUnit: "s"); } } - - /// <summary> - /// Converts to/from Second - /// </summary> - [DebuggerHidden] - public SI Minute { get { return new SI(this, factor: 60.0, fromUnit: "min", toUnit: "s"); } } - - /// <summary> - /// Converts to/from 1000 * Basic Unit - /// </summary> - [DebuggerHidden] - public SI Kilo { get { return new SI(this, factor: 1000.0, fromUnit: "k"); } } - - /// <summary> - /// Converts to/from Basic Unit / 100 - /// </summary> - [DebuggerHidden] - public SI Centi { get { return new SI(this, factor: 1.0 / 100.0, fromUnit: "c"); } } - #endregion - - /// <summary> - /// Convert an SI unit into another SI unit, defined by term following after the To(). - /// </summary> - /// <returns></returns> - public SI To() { return new SI(Linear, reciproc: false, reverse: true); } - - public T To<T>() where T : SI - { - var t = (T)Activator.CreateInstance(typeof(T), Val); - Contract.Assert(HasEqualUnit(t), string.Format("SI Unit Conversion failed: From {0} to {1}", this, t)); - return t; - } - - public SI ToBasicUnits() - { - var numerator = new List<string>(); - var denominator = new List<string>(); - Numerator.ToList().ForEach(unit => ConvertToBasicUnits(unit, numerator, denominator)); - Denominator.ToList().ForEach(unit => ConvertToBasicUnits(unit, denominator, numerator)); - return new SI(Val, numerator, denominator); - } - - private static void ConvertToBasicUnits(string unit, ICollection<string> numerator, ICollection<string> denominator) - { - switch (unit) - { - case "W": - numerator.Add("k"); - numerator.Add("g"); - numerator.Add("m"); - numerator.Add("m"); - denominator.Add("s"); - denominator.Add("s"); - denominator.Add("s"); - break; - case "N": - numerator.Add("k"); - numerator.Add("g"); - numerator.Add("m"); - denominator.Add("s"); - denominator.Add("s"); - break; - default: - numerator.Add(unit); - break; - } - } - - /// <summary> - /// Gets the basic scalar value. - /// </summary> - protected double ScalarValue() { return Val; } - - public SI Value() - { - return new SI(Val, Numerator, Denominator); - } - - #region Operators - public static SI operator +(SI si1, SI si2) - { - Contract.Requires(si1.HasEqualUnit(si2)); - - return new SI(si1.Val + si2.Val, si1.Numerator, si1.Denominator); - } - - public static SI operator -(SI si1, SI si2) - { - Contract.Requires(si1.HasEqualUnit(si2)); - - return new SI(si1.Val - si2.Val, si1.Numerator, si1.Denominator); - } - - public static SI operator *(SI si1, SI si2) - { - var numerator = si1.Numerator.Concat(si2.Numerator).Where(d => d != "rad"); - var denominator = si1.Denominator.Concat(si2.Denominator).Where(d => d != "rad"); - return new SI(si1.Val * si2.Val, numerator, denominator); - } - - public static SI operator /(SI si1, SI si2) - { - var numerator = si1.Numerator.Concat(si2.Denominator).Where(d => d != "rad"); - var denominator = si1.Denominator.Concat(si2.Numerator).Where(d => d != "rad"); - return new SI(si1.Val / si2.Val, numerator, denominator); - } - - public static SI operator +(SI si1, double d) - { - return new SI(si1.Val + d, si1); - } - - public static SI operator -(SI si1, double d) - { - return new SI(si1.Val - d, si1); - } - - public static SI operator *(SI si1, double d) - { - return new SI(si1.Val * d, si1); - } - - public static SI operator *(double d, SI si1) - { - return new SI(d * si1.Val, si1); - } - - public static SI operator /(SI si1, double d) - { - return new SI(si1.Val / d, si1); - } - - public static SI operator /(double d, SI si1) - { - return new SI(d / si1.Val, si1); - } - - public static bool operator <(SI si1, SI si2) - { - Contract.Requires(si1.HasEqualUnit(si2)); - return si1.Val < si2.Val; - } - - public static bool operator >(SI si1, SI si2) - { - Contract.Requires(si1.HasEqualUnit(si2)); - return si1.Val > si2.Val; - } - - public static bool operator <=(SI si1, SI si2) - { - Contract.Requires(si1.HasEqualUnit(si2)); - return si1.Val <= si2.Val; - } - - public static bool operator >=(SI si1, SI si2) - { - Contract.Requires(si1.HasEqualUnit(si2)); - return si1.Val >= si2.Val; - } - - public static bool operator <(SI si1, double d) - { - return si1.Val < d; - } - - public static bool operator >(SI si1, double d) - { - return si1.Val > d; - } - - public static bool operator <=(SI si1, double d) - { - return si1.Val <= d; - } - - public static bool operator >=(SI si1, double d) - { - return si1.Val >= d; - } - - - - - - #endregion - - #region Double Conversion - /// <summary> - /// Casts an SI Unit to an double. - /// </summary> - /// <param name="si"></param> - /// <returns></returns> - public static explicit operator double(SI si) - { - return si.Val; - } - - /// <summary> - /// Casts a double to an SI Unit. - /// </summary> - /// <param name="d"></param> - /// <returns></returns> - public static explicit operator SI(double d) - { - return new SI(d); - } - #endregion - - #region ToString - /// <summary> - /// Returns the Unit Part of the SI Unit Expression. - /// </summary> - private string GetUnitString() - { - if (Denominator.Any()) - if (Numerator.Any()) - return string.Format("{0}/{1}", string.Join("", Numerator), string.Join("", Denominator)); - else - return string.Format("1/{0}", string.Join("", Denominator)); - - if (Numerator.Any()) - return string.Format("{0}", string.Join("", Numerator)); - - return "-"; - } - - /// <summary> - /// Returns the String representation. - /// </summary> - public override string ToString() { return string.Format("{0} [{1}]", Val, GetUnitString()); } - #endregion - - #region Equality members - /// <summary> - /// Compares the Unit-Parts of two SI Units. - /// </summary> - [Pure] - public bool HasEqualUnit(SI si) - { - return ToBasicUnits().Denominator.OrderBy(x => x).SequenceEqual(si.ToBasicUnits().Denominator.OrderBy(x => x)) - && ToBasicUnits().Numerator.OrderBy(x => x).SequenceEqual(si.ToBasicUnits().Numerator.OrderBy(x => x)); - } - - protected bool Equals(SI other) - { - return Val.Equals(other.Val) && HasEqualUnit(other); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - var other = obj as SI; - return other != null && Equals(other); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = Val.GetHashCode(); - hashCode = (hashCode * 397) ^ (Numerator != null ? Numerator.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (Denominator != null ? Denominator.GetHashCode() : 0); - return hashCode; - } - } - - public static bool operator ==(SI left, SI right) - { - return Equals(left, right); - } - - public static bool operator !=(SI left, SI right) - { - return !Equals(left, right); - } - #endregion - - public SI Abs() - { - return new SI(Math.Abs(Val), this); - } - } + public class MeterPerSecond : SI + { + public MeterPerSecond(double val = 0) : base(val, new SI().Meter.Per.Second) {} + } + + public class Second : SI + { + public Second(double val = 0) : base(val, new SI().Second) {} + } + + public class Watt : SI + { + public Watt(double val = 0) : base(val, new SI().Watt) {} + } + + public class RadianPerSecond : SI + { + public RadianPerSecond(double val = 0) : base(val, new SI().Radian.Per.Second) {} + } + + public class RoundsPerMinute : SI + { + public RoundsPerMinute(double val = 0) : base(val, new SI().Rounds.Per.Minute) {} + } + + public class NewtonMeter : SI + { + public NewtonMeter(double val = 0) : base(val, new SI().Newton.Meter) {} + } + + [DataContract] + public class SI + { + [DataMember] protected readonly string[] Denominator; + [DataMember] protected readonly int Exponent; + [DataMember] protected readonly string[] Numerator; + [DataMember] protected readonly bool Reciproc; + [DataMember] protected readonly bool Reverse; + [DataMember] protected readonly double Val; + + public SI(double val = 0.0) + { + Val = val; + Reciproc = false; + Reverse = false; + Numerator = new string[0]; + Denominator = new string[0]; + Exponent = 1; + } + + protected SI(double val, IEnumerable<string> numerator, IEnumerable<string> denominator, bool reciproc = false, + bool reverse = false, int exponent = 1) + { + Contract.Requires(numerator != null); + Contract.Requires(denominator != null); + + Val = val; + Reciproc = reciproc; + Reverse = reverse; + Exponent = exponent; + + var tmpNumerator = numerator.ToList(); + var tmpDenominator = denominator.ToList(); + + foreach (var v in tmpDenominator.ToArray().Where(v => tmpNumerator.Contains(v))) { + tmpNumerator.Remove(v); + tmpDenominator.Remove(v); + } + + Numerator = tmpNumerator.ToArray(); + Denominator = tmpDenominator.ToArray(); + } + + protected SI(double val, SI unit) + : this(val, unit.Numerator, unit.Denominator) {} + + protected SI(SI si, double? factor = null, string fromUnit = null, string toUnit = null, + bool? reciproc = null, bool? reverse = null, int? exponent = null) + { + Contract.Requires(si != null); + Contract.Requires(si.Denominator != null); + Contract.Requires(si.Numerator != null); + + var numerator = si.Denominator.ToList(); + var denominator = si.Numerator.ToList(); + + Val = si.Val; + Reciproc = reciproc ?? si.Reciproc; + Reverse = reverse ?? si.Reverse; + Exponent = exponent ?? si.Exponent; + + if (Reverse) { + var tmp = fromUnit; + fromUnit = toUnit; + toUnit = tmp; + factor = 1 / factor; + } + + for (var i = 0; i < Exponent; i++) { + if (!Reciproc) { + UpdateUnit(fromUnit, toUnit, denominator); + if (factor.HasValue) { + Val *= factor.Value; + } + } else { + UpdateUnit(fromUnit, toUnit, numerator); + if (factor.HasValue) { + Val /= factor.Value; + } + } + } + + foreach (var v in numerator.ToArray().Where(v => denominator.Contains(v))) { + denominator.Remove(v); + numerator.Remove(v); + } + + Numerator = denominator.ToArray(); + Denominator = numerator.ToArray(); + } + + private void UpdateUnit(string fromUnit, string toUnit, ICollection<string> units) + { + if (Reverse && !string.IsNullOrEmpty(fromUnit)) { + if (units.Contains(fromUnit)) { + units.Remove(fromUnit); + } else { + throw new VectoException("Unit missing. Conversion not possible."); + } + } + + if (!string.IsNullOrEmpty(toUnit)) { + units.Add(toUnit); + } + } + + /// <summary> + /// Convert an SI unit into another SI unit, defined by term following after the To(). + /// </summary> + /// <returns></returns> + public SI To() + { + return new SI(Linear, reciproc: false, reverse: true); + } + + public T To<T>() where T : SI + { + var t = (T) Activator.CreateInstance(typeof (T), Val); + Contract.Assert(HasEqualUnit(t), string.Format("SI Unit Conversion failed: From {0} to {1}", this, t)); + return t; + } + + public SI ToBasicUnits() + { + var numerator = new List<string>(); + var denominator = new List<string>(); + Numerator.ToList().ForEach(unit => ConvertToBasicUnits(unit, numerator, denominator)); + Denominator.ToList().ForEach(unit => ConvertToBasicUnits(unit, denominator, numerator)); + return new SI(Val, numerator, denominator); + } + + private static void ConvertToBasicUnits(string unit, ICollection<string> numerator, ICollection<string> denominator) + { + switch (unit) { + case "W": + numerator.Add("k"); + numerator.Add("g"); + numerator.Add("m"); + numerator.Add("m"); + denominator.Add("s"); + denominator.Add("s"); + denominator.Add("s"); + break; + case "N": + numerator.Add("k"); + numerator.Add("g"); + numerator.Add("m"); + denominator.Add("s"); + denominator.Add("s"); + break; + default: + numerator.Add(unit); + break; + } + } + + /// <summary> + /// Gets the basic scalar value. + /// </summary> + protected double ScalarValue() + { + return Val; + } + + public SI Value() + { + return new SI(Val, Numerator, Denominator); + } + + public SI Abs() + { + return new SI(Math.Abs(Val), this); + } + + #region Unit Definitions + + /// <summary> + /// Defines the denominator by the terms following after the Per. + /// </summary> + [DebuggerHidden] + public SI Per + { + get { return new SI(Linear, reciproc: !Reciproc); } + } + + /// <summary> + /// Takes all following terms as cubic terms (=to the power of 3). + /// </summary> + [DebuggerHidden] + public SI Cubic + { + get { return new SI(this, exponent: 3); } + } + + /// <summary> + /// Takes all following terms as quadratic terms (=to the power of 2). + /// </summary> + [DebuggerHidden] + public SI Square + { + get { return new SI(this, exponent: 2); } + } + + /// <summary> + /// Takes all following terms as linear terms (=to the power of 1). + /// </summary> + [DebuggerHidden] + public SI Linear + { + get { return new SI(this, exponent: 1); } + } + + /// <summary> + /// [g] (to basic unit: [kg]) + /// </summary> + [DebuggerHidden] + public SI Gramm + { + get { return new SI(new SI(this, toUnit: "k"), 0.001, "g", "g"); } + } + + /// <summary> + /// [N] + /// </summary> + [DebuggerHidden] + public SI Newton + { + get { return new SI(this, fromUnit: "N", toUnit: "N"); } + } + + /// <summary> + /// [W] + /// </summary> + [DebuggerHidden] + public SI Watt + { + get { return new SI(this, fromUnit: "W", toUnit: "W"); } + } + + /// <summary> + /// [m] + /// </summary> + [DebuggerHidden] + public SI Meter + { + get { return new SI(this, fromUnit: "m", toUnit: "m"); } + } + + /// <summary> + /// [s] + /// </summary> + [DebuggerHidden] + public SI Second + { + get { return new SI(this, fromUnit: "s", toUnit: "s"); } + } + + /// <summary> + /// [rad] + /// </summary> + [DebuggerHidden] + public SI Radian + { + get { return new SI(this, fromUnit: "rad", toUnit: "rad"); } + } + + /// <summary> + /// Converts to/from Radiant + /// </summary> + [DebuggerHidden] + public SI Rounds + { + get { return new SI(this, 2 * Math.PI, toUnit: "rad"); } + } + + /// <summary> + /// Converts to/from Second + /// </summary> + [DebuggerHidden] + public SI Hour + { + get { return new SI(this, 3600.0, "h", "s"); } + } + + /// <summary> + /// Converts to/from Second + /// </summary> + [DebuggerHidden] + public SI Minute + { + get { return new SI(this, 60.0, "min", "s"); } + } + + /// <summary> + /// Converts to/from 1000 * Basic Unit + /// </summary> + [DebuggerHidden] + public SI Kilo + { + get { return new SI(this, 1000.0, "k"); } + } + + /// <summary> + /// Converts to/from Basic Unit / 100 + /// </summary> + [DebuggerHidden] + public SI Centi + { + get { return new SI(this, 1.0 / 100.0, "c"); } + } + + #endregion + + #region Operators + + public static SI operator +(SI si1, SI si2) + { + Contract.Requires(si1.HasEqualUnit(si2)); + + return new SI(si1.Val + si2.Val, si1.Numerator, si1.Denominator); + } + + public static SI operator -(SI si1, SI si2) + { + Contract.Requires(si1.HasEqualUnit(si2)); + + return new SI(si1.Val - si2.Val, si1.Numerator, si1.Denominator); + } + + public static SI operator *(SI si1, SI si2) + { + var numerator = si1.Numerator.Concat(si2.Numerator).Where(d => d != "rad"); + var denominator = si1.Denominator.Concat(si2.Denominator).Where(d => d != "rad"); + return new SI(si1.Val * si2.Val, numerator, denominator); + } + + public static SI operator /(SI si1, SI si2) + { + var numerator = si1.Numerator.Concat(si2.Denominator).Where(d => d != "rad"); + var denominator = si1.Denominator.Concat(si2.Numerator).Where(d => d != "rad"); + return new SI(si1.Val / si2.Val, numerator, denominator); + } + + public static SI operator +(SI si1, double d) + { + return new SI(si1.Val + d, si1); + } + + public static SI operator -(SI si1, double d) + { + return new SI(si1.Val - d, si1); + } + + public static SI operator *(SI si1, double d) + { + return new SI(si1.Val * d, si1); + } + + public static SI operator *(double d, SI si1) + { + return new SI(d * si1.Val, si1); + } + + public static SI operator /(SI si1, double d) + { + return new SI(si1.Val / d, si1); + } + + public static SI operator /(double d, SI si1) + { + return new SI(d / si1.Val, si1); + } + + public static bool operator <(SI si1, SI si2) + { + Contract.Requires(si1.HasEqualUnit(si2)); + return si1.Val < si2.Val; + } + + public static bool operator >(SI si1, SI si2) + { + Contract.Requires(si1.HasEqualUnit(si2)); + return si1.Val > si2.Val; + } + + public static bool operator <=(SI si1, SI si2) + { + Contract.Requires(si1.HasEqualUnit(si2)); + return si1.Val <= si2.Val; + } + + public static bool operator >=(SI si1, SI si2) + { + Contract.Requires(si1.HasEqualUnit(si2)); + return si1.Val >= si2.Val; + } + + public static bool operator <(SI si1, double d) + { + return si1.Val < d; + } + + public static bool operator >(SI si1, double d) + { + return si1.Val > d; + } + + public static bool operator <=(SI si1, double d) + { + return si1.Val <= d; + } + + public static bool operator >=(SI si1, double d) + { + return si1.Val >= d; + } + + #endregion + + #region Double Conversion + + /// <summary> + /// Casts an SI Unit to an double. + /// </summary> + /// <param name="si"></param> + /// <returns></returns> + public static explicit operator double(SI si) + { + return si.Val; + } + + /// <summary> + /// Casts a double to an SI Unit. + /// </summary> + /// <param name="d"></param> + /// <returns></returns> + public static explicit operator SI(double d) + { + return new SI(d); + } + + #endregion + + #region ToString + + /// <summary> + /// Returns the Unit Part of the SI Unit Expression. + /// </summary> + private string GetUnitString() + { + if (Denominator.Any()) { + if (Numerator.Any()) { + return string.Format("{0}/{1}", string.Join("", Numerator), string.Join("", Denominator)); + } else { + return string.Format("1/{0}", string.Join("", Denominator)); + } + } + + if (Numerator.Any()) { + return string.Format("{0}", string.Join("", Numerator)); + } + + return "-"; + } + + /// <summary> + /// Returns the String representation. + /// </summary> + public override string ToString() + { + return string.Format("{0} [{1}]", Val, GetUnitString()); + } + + #endregion + + #region Equality members + + /// <summary> + /// Compares the Unit-Parts of two SI Units. + /// </summary> + [Pure] + public bool HasEqualUnit(SI si) + { + return ToBasicUnits().Denominator.OrderBy(x => x).SequenceEqual(si.ToBasicUnits().Denominator.OrderBy(x => x)) + && ToBasicUnits().Numerator.OrderBy(x => x).SequenceEqual(si.ToBasicUnits().Numerator.OrderBy(x => x)); + } + + protected bool Equals(SI other) + { + return Val.Equals(other.Val) && HasEqualUnit(other); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) { + return false; + } + if (ReferenceEquals(this, obj)) { + return true; + } + var other = obj as SI; + return other != null && Equals(other); + } + + public override int GetHashCode() + { + unchecked { + var hashCode = Val.GetHashCode(); + hashCode = (hashCode * 397) ^ (Numerator != null ? Numerator.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Denominator != null ? Denominator.GetHashCode() : 0); + return hashCode; + } + } + + public static bool operator ==(SI left, SI right) + { + return Equals(left, right); + } + + public static bool operator !=(SI left, SI right) + { + return !Equals(left, right); + } + + #endregion + } } \ No newline at end of file diff --git a/VectoCore/Utils/VectoCSVFile.cs b/VectoCore/Utils/VectoCSVFile.cs index 61cc5ce75224d6370b893f070ce1ac62cde929b9..b17f6b5b9aa88e25a0fa4e995e108c44a35a2103 100644 --- a/VectoCore/Utils/VectoCSVFile.cs +++ b/VectoCore/Utils/VectoCSVFile.cs @@ -12,134 +12,124 @@ using TUGraz.VectoCore.Exceptions; namespace TUGraz.VectoCore.Utils { - /// <summary> - /// Class for Reading and Writing VECTO CSV Files. - /// </summary> - /// <remarks> - /// The following format applies to all CSV (Comma-separated values) Input Files used in VECTO: - /// List Separator: Comma "," - /// Decimal-Mark: Dot "." - /// Comments: "#" at the beginning of the comment line. Number and position of comment lines is not limited. - /// Header: One header line (not a comment line) at the beginning of the file. - /// All Combinations between max-format and min-format possible. Only "id"-field is used. - /// max: id (name) [unit], id (name) [unit], ... - /// min: id,id,... - /// </remarks> - public static class VectoCSVFile - { - private const char Separator = ','; - private const char Comment = '#'; - - /// <summary> - /// Reads a CSV file which is stored in Vecto-CSV-Format. - /// </summary> - /// <param name="fileName"></param> - /// <exception cref="FileIOException"></exception> - /// <returns>A DataTable which represents the CSV File.</returns> - - public static DataTable Read(string fileName) - { - try - { - var lines = File.ReadAllLines(fileName); - lines = RemoveComments(lines); - - var validColumns = GetValidHeaderColumns(lines.First()); - - if (validColumns.Length > 0) - { - // Valid Columns found => header was valid => skip header line - lines = lines.Skip(1).ToArray(); - } - else - { - var log = LogManager.GetLogger(typeof(VectoCSVFile)); - log.Warn("No valid Data Header found. Interpreting the first line as data line."); - // set the validColumns to: {"0", "1", "2", "3", ...} for all columns in first line. - validColumns = GetColumns(lines.First()).Select((_, index) => index.ToString()).ToArray(); - } - - var table = new DataTable(); - foreach (var col in validColumns) - table.Columns.Add(col); - - for (var i = 0; i < lines.Length; i++) - { - var line = lines[i]; - - var cells = line.Split(Separator); - if (cells.Length != table.Columns.Count) - throw new CSVReadException(string.Format("Line {0}: The number of values is not correct.", i)); - - try - { - table.Rows.Add(line.Split(Separator)); - } - catch (InvalidCastException e) - { - throw new CSVReadException(string.Format("Line {0}: The data format of a value is not correct. {1}", i, e.Message), e); - } - } - - return table; - } - catch (Exception e) - { - throw new VectoException(string.Format("File {0}: {1}", fileName, e.Message)); - } - } - - private static string[] GetValidHeaderColumns(string line) - { - Contract.Requires(line != null); - double test; - var validColumns = GetColumns(line). - Where(col => !double.TryParse(col, NumberStyles.Any, CultureInfo.InvariantCulture, out test)); - return validColumns.ToArray(); - } - - private static IEnumerable<string> GetColumns(string line) - { - Contract.Requires(line != null); - - line = Regex.Replace(line, @"\[.*?\]", ""); - line = Regex.Replace(line, @"\(.*?\)", ""); - line = line.Replace("<", ""); - line = line.Replace(">", ""); - return line.Split(Separator).Select(col => col.Trim()); - } - - private static string[] RemoveComments(string[] lines) - { - Contract.Requires(lines != null); - - lines = lines. - Select(line => line.Contains('#') ? line.Substring(0, line.IndexOf(Comment)) : line). - Where(line => !string.IsNullOrEmpty(line)). - ToArray(); - return lines; - } - - public static void Write(string fileName, DataTable table) - { - var sb = new StringBuilder(); - - var header = table.Columns.Cast<DataColumn>().Select(col => col.Caption ?? col.ColumnName); - sb.AppendLine(string.Join(", ", header)); - - foreach (DataRow row in table.Rows) - { - var formattedList = new List<string>(); - foreach (var item in row.ItemArray) - { - var formattable = item as IFormattable; - var formattedValue = formattable != null ? formattable.ToString("", CultureInfo.InvariantCulture) : item.ToString(); - formattedList.Add(formattedValue); - } - sb.AppendLine(string.Join(Separator.ToString(), formattedList)); - } - - File.WriteAllText(fileName, sb.ToString()); - } - } + /// <summary> + /// Class for Reading and Writing VECTO CSV Files. + /// </summary> + /// <remarks> + /// The following format applies to all CSV (Comma-separated values) Input Files used in VECTO: + /// List Separator: Comma "," + /// Decimal-Mark: Dot "." + /// Comments: "#" at the beginning of the comment line. Number and position of comment lines is not limited. + /// Header: One header line (not a comment line) at the beginning of the file. + /// All Combinations between max-format and min-format possible. Only "id"-field is used. + /// max: id (name) [unit], id (name) [unit], ... + /// min: id,id,... + /// </remarks> + public static class VectoCSVFile + { + private const char Separator = ','; + private const char Comment = '#'; + + /// <summary> + /// Reads a CSV file which is stored in Vecto-CSV-Format. + /// </summary> + /// <param name="fileName"></param> + /// <exception cref="FileIOException"></exception> + /// <returns>A DataTable which represents the CSV File.</returns> + public static DataTable Read(string fileName) + { + try { + var lines = File.ReadAllLines(fileName); + lines = RemoveComments(lines); + + var validColumns = GetValidHeaderColumns(lines.First()); + + if (validColumns.Length > 0) { + // Valid Columns found => header was valid => skip header line + lines = lines.Skip(1).ToArray(); + } else { + var log = LogManager.GetLogger(typeof (VectoCSVFile)); + log.Warn("No valid Data Header found. Interpreting the first line as data line."); + // set the validColumns to: {"0", "1", "2", "3", ...} for all columns in first line. + validColumns = GetColumns(lines.First()).Select((_, index) => index.ToString()).ToArray(); + } + + var table = new DataTable(); + foreach (var col in validColumns) { + table.Columns.Add(col); + } + + for (var i = 0; i < lines.Length; i++) { + var line = lines[i]; + + var cells = line.Split(Separator); + if (cells.Length != table.Columns.Count) { + throw new CSVReadException(string.Format("Line {0}: The number of values is not correct.", i)); + } + + try { + table.Rows.Add(line.Split(Separator)); + } catch (InvalidCastException e) { + throw new CSVReadException( + string.Format("Line {0}: The data format of a value is not correct. {1}", i, e.Message), e); + } + } + + return table; + } catch (Exception e) { + throw new VectoException(string.Format("File {0}: {1}", fileName, e.Message)); + } + } + + private static string[] GetValidHeaderColumns(string line) + { + Contract.Requires(line != null); + double test; + var validColumns = GetColumns(line). + Where(col => !double.TryParse(col, NumberStyles.Any, CultureInfo.InvariantCulture, out test)); + return validColumns.ToArray(); + } + + private static IEnumerable<string> GetColumns(string line) + { + Contract.Requires(line != null); + + line = Regex.Replace(line, @"\[.*?\]", ""); + line = Regex.Replace(line, @"\(.*?\)", ""); + line = line.Replace("<", ""); + line = line.Replace(">", ""); + return line.Split(Separator).Select(col => col.Trim()); + } + + private static string[] RemoveComments(string[] lines) + { + Contract.Requires(lines != null); + + lines = lines. + Select(line => line.Contains('#') ? line.Substring(0, line.IndexOf(Comment)) : line). + Where(line => !string.IsNullOrEmpty(line)). + ToArray(); + return lines; + } + + public static void Write(string fileName, DataTable table) + { + var sb = new StringBuilder(); + + var header = table.Columns.Cast<DataColumn>().Select(col => col.Caption ?? col.ColumnName); + sb.AppendLine(string.Join(", ", header)); + + foreach (DataRow row in table.Rows) { + var formattedList = new List<string>(); + foreach (var item in row.ItemArray) { + var formattable = item as IFormattable; + var formattedValue = formattable != null ? formattable.ToString("", CultureInfo.InvariantCulture) : item.ToString(); + formattedList.Add(formattedValue); + } + sb.AppendLine(string.Join(Separator.ToString(), formattedList)); + } + + File.WriteAllText(fileName, sb.ToString()); + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/VectoMath.cs b/VectoCore/Utils/VectoMath.cs index f53f12886d6aad3f200efb61ac28fa1a44c29fa4..61f2f91eb4350b906c8ecdbe49164db7898b615d 100644 --- a/VectoCore/Utils/VectoMath.cs +++ b/VectoCore/Utils/VectoMath.cs @@ -1,10 +1,10 @@ namespace TUGraz.VectoCore.Utils { - public class VectoMath - { - public static double Interpolate(double x1, double x2, double y1, double y2, double xint) - { - return (xint - x1) * (y2 - y1) / (x2 - x1) + y1; - } - } + public class VectoMath + { + public static double Interpolate(double x1, double x2, double y1, double y2, double xint) + { + return (xint - x1) * (y2 - y1) / (x2 - x1) + y1; + } + } } \ No newline at end of file diff --git a/VectoCore/app.config b/VectoCore/app.config index 204238d72820cc8e3bb43c964e2fe8a386cbd611..275e46a27e77b434708c616ce57bc44e44093d6f 100644 --- a/VectoCore/app.config +++ b/VectoCore/app.config @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> + <configuration> <configSections> <sectionGroup name="common"> @@ -6,25 +7,26 @@ </sectionGroup> <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" /> </configSections> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" /> - </dependentAssembly> - </assemblyBinding> - </runtime> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> <common> <logging> <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog31"> - <arg key="configType" value="INLINE"/> + <arg key="configType" value="INLINE" /> </factoryAdapter> </logging> </common> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target xsi:type="Console" name="ConsoleLogger" error="true" /> - <target xsi:type="File" name="LogFile" filename="${basedir}/logs/log.txt" layout="${longdate} [${processid}@${machinename}] ${callsite} ${level:uppercase=true}: ${message}" /> + <target xsi:type="File" name="LogFile" filename="${basedir}/logs/log.txt" + layout="${longdate} [${processid}@${machinename}] ${callsite} ${level:uppercase=true}: ${message}" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="LogFile" /> diff --git a/VectoCore/packages.config b/VectoCore/packages.config index d4a3fcac5d0e232c1e87c07329653f01d5301fc5..3229bd6e1e32bfc7e0c7e84bf89f6373ad829be4 100644 --- a/VectoCore/packages.config +++ b/VectoCore/packages.config @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> + <packages> - <package id="Common.Logging" version="3.0.0" targetFramework="net45" /> - <package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" /> - <package id="Common.Logging.NLog31" version="3.0.0" targetFramework="net45" /> - <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" /> - <package id="NLog" version="3.2.0.0" targetFramework="net45" /> + <package id="Common.Logging" version="3.0.0" targetFramework="net45" /> + <package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" /> + <package id="Common.Logging.NLog31" version="3.0.0" targetFramework="net45" /> + <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" /> + <package id="NLog" version="3.2.0.0" targetFramework="net45" /> </packages> \ No newline at end of file diff --git a/VectoCoreTest/Exceptions/ExceptionTests.cs b/VectoCoreTest/Exceptions/ExceptionTests.cs index a2cf4f25ea51aeb94d83f856bdfc183ed489518a..04bff1cabffd637fdbfe8fdd98160c549a9b5b46 100644 --- a/VectoCoreTest/Exceptions/ExceptionTests.cs +++ b/VectoCoreTest/Exceptions/ExceptionTests.cs @@ -1,29 +1,28 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Exceptions; -using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Exceptions { - [TestClass] - public class ExceptionTests - { - [TestMethod] - public void Test_VectoExceptions() - { - new CSVReadException("Test"); - new CSVReadException("Test", new Exception("Inner")); - new InvalidFileFormatException("Test"); - new CSVReadException("Test", new Exception("Inner")); - new UnsupportedFileVersionException("Test"); - new UnsupportedFileVersionException("Test", new Exception("Inner")); - new InvalidFileFormatException("Test"); - new InvalidFileFormatException("Test", new Exception("Inner")); - new VectoException("Test"); - new VectoException("Test", new Exception("Inner")); + [TestClass] + public class ExceptionTests + { + [TestMethod] + public void Test_VectoExceptions() + { + new CSVReadException("Test"); + new CSVReadException("Test", new Exception("Inner")); + new InvalidFileFormatException("Test"); + new CSVReadException("Test", new Exception("Inner")); + new UnsupportedFileVersionException("Test"); + new UnsupportedFileVersionException("Test", new Exception("Inner")); + new InvalidFileFormatException("Test"); + new InvalidFileFormatException("Test", new Exception("Inner")); + new VectoException("Test"); + new VectoException("Test", new Exception("Inner")); - new VectoSimulationException("Test"); - new VectoSimulationException("Test", new Exception("Inner")); - } - } -} + new VectoSimulationException("Test"); + new VectoSimulationException("Test", new Exception("Inner")); + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs index 489a8f689728962dc6cd9e774036dad5655979be..9312ca5488afd9b8059f40868f5b6fe7ab261028 100644 --- a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs +++ b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs @@ -1,6 +1,5 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; @@ -13,12 +12,11 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle [TestClass] public class EngineOnlyCycleTest { - - public TestContext TestContext { get; set; } - private const string EngineFile = @"TestData\Components\24t Coach.veng"; + public TestContext TestContext { get; set; } - [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData\\EngineTests.csv", "EngineTests#csv", DataAccessMethod.Sequential)] + [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData\\EngineTests.csv", + "EngineTests#csv", DataAccessMethod.Sequential)] [TestMethod] public void TestEngineOnlyDrivingCycle() { @@ -31,7 +29,7 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle var aux = new EngineOnlyAuxiliary(vehicle, new AuxiliariesDemandAdapter(data)); var gearbox = new EngineOnlyGearbox(vehicle); - + var engine = new CombustionEngine(vehicle, engineData); aux.Connect(engine); @@ -47,15 +45,16 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle var dataWriter = new TestModalDataWriter(); var i = 0; - var results = new[] { ModalResultField.n, ModalResultField.PaEng, ModalResultField.Tq_drag, ModalResultField.Pe_drag, ModalResultField.Pe_eng, ModalResultField.Tq_eng, ModalResultField.Tq_full, ModalResultField.Pe_full, }; + var results = new[] { + ModalResultField.n, ModalResultField.PaEng, ModalResultField.Tq_drag, ModalResultField.Pe_drag, + ModalResultField.Pe_eng, ModalResultField.Tq_eng, ModalResultField.Tq_full, ModalResultField.Pe_full + }; //, ModalResultField.FC }; - var siFactor = new[] {1, 1000, 1, 1000, 1000, 1, 1, 1000, 1 }; - var tolerances = new[] {0.0001, 0.1, 0.0001, 0.1, 0.1, 0.001, 0.001, 0.1, 0.01 }; - foreach (var cycle in data.Entries) - { + var siFactor = new[] { 1, 1000, 1, 1000, 1000, 1, 1, 1000, 1 }; + var tolerances = new[] { 0.0001, 0.1, 0.0001, 0.1, 0.1, 0.001, 0.001, 0.1, 0.01 }; + foreach (var cycle in data.Entries) { port.Request(absTime, dt, cycle.EngineTorque, cycle.EngineSpeed); - foreach (var sc in vehicle.SimulationComponents()) - { + foreach (var sc in vehicle.SimulationComponents()) { sc.CommitSimulationStep(dataWriter); } @@ -65,12 +64,13 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle for (var j = 0; j < results.Length; j++) { var field = results[j]; // if (!Double.IsNaN(dataWriter.GetDouble(field))) - Assert.AreEqual((double) row[field.GetName()] * siFactor[j], dataWriter.GetDouble(field), tolerances[j],String.Format("t: {0} field: {1}", i, field)); + Assert.AreEqual((double) row[field.GetName()] * siFactor[j], dataWriter.GetDouble(field), tolerances[j], + String.Format("t: {0} field: {1}", i, field)); } if (row[ModalResultField.FC.GetName()] is double) { - Assert.AreEqual((double) row[ModalResultField.FC.GetName()], dataWriter.GetDouble(ModalResultField.FC), 0.01, "t: {0} field: {1}", i, ModalResultField.FC); - } - else { + Assert.AreEqual((double) row[ModalResultField.FC.GetName()], dataWriter.GetDouble(ModalResultField.FC), 0.01, + "t: {0} field: {1}", i, ModalResultField.FC); + } else { Assert.IsTrue(Double.IsNaN(dataWriter.GetDouble(ModalResultField.FC)), String.Format("t: {0}", i)); } } @@ -81,7 +81,6 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle dataWriter.Data.WriteToFile("test2.csv"); } - [TestMethod] public void AssembleEngineOnlyPowerTrain() { @@ -97,17 +96,16 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle var absTime = new TimeSpan(); var dt = TimeSpan.FromSeconds(1); - var angularVelocity = 644.4445.RPMtoRad(); - var power = 2329.973.SI<Watt>(); + var angularVelocity = 644.4445.RPMtoRad(); + var power = 2329.973.SI<Watt>(); - gearbox.Request(absTime, dt, Formulas.PowerToTorque(power, angularVelocity), angularVelocity); + gearbox.Request(absTime, dt, Formulas.PowerToTorque(power, angularVelocity), angularVelocity); - foreach (var sc in vehicleContainer.SimulationComponents()) - { + foreach (var sc in vehicleContainer.SimulationComponents()) { sc.CommitSimulationStep(dataWriter); } Assert.IsNotNull(dataWriter.CurrentRow); } } -} +} \ No newline at end of file diff --git a/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs b/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs index 056d1432e3d1c8ebeb7c7a3c8b5408065c2fb7a0..e5c4f3a179a8dbe84adcdb5ed85cf1e44493b69b 100644 --- a/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs +++ b/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs @@ -1,10 +1,7 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation.Impl; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Models.SimulationComponent; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Tests.Models.SimulationComponent; @@ -13,89 +10,88 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Models.Simulation { - [TestClass] - public class DrivingCycleTests - { - [TestMethod] - public void TestEngineOnly() - { - var container = new VehicleContainer(); + [TestClass] + public class DrivingCycleTests + { + [TestMethod] + public void TestEngineOnly() + { + var container = new VehicleContainer(); - var cycleData = DrivingCycleData.ReadFromFileEngineOnly(@"TestData\Cycles\Coach Engine Only.vdri"); - var cycle = new EngineOnlyDrivingCycle(container, cycleData); + var cycleData = DrivingCycleData.ReadFromFileEngineOnly(@"TestData\Cycles\Coach Engine Only.vdri"); + var cycle = new EngineOnlyDrivingCycle(container, cycleData); - var outPort = new MockTnOutPort(); - var inPort = cycle.InShaft(); + var outPort = new MockTnOutPort(); + var inPort = cycle.InShaft(); - inPort.Connect(outPort); + inPort.Connect(outPort); - var absTime = new TimeSpan(); - var dt = TimeSpan.FromSeconds(1); + var absTime = new TimeSpan(); + var dt = TimeSpan.FromSeconds(1); - var response = cycle.Request(absTime, dt); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + var response = cycle.Request(absTime, dt); + Assert.IsInstanceOfType(response, typeof (ResponseSuccess)); - var dataWriter = new TestModalDataWriter(); - container.CommitSimulationStep(dataWriter); + var dataWriter = new TestModalDataWriter(); + container.CommitSimulationStep(dataWriter); - Assert.AreEqual(absTime, outPort.AbsTime); - Assert.AreEqual(dt, outPort.Dt); - Assert.AreEqual(600.0.RPMtoRad(), outPort.AngularFrequency); - Assert.AreEqual(0.SI<NewtonMeter>(), outPort.Torque); - } + Assert.AreEqual(absTime, outPort.AbsTime); + Assert.AreEqual(dt, outPort.Dt); + Assert.AreEqual(600.0.RPMtoRad(), outPort.AngularFrequency); + Assert.AreEqual(0.SI<NewtonMeter>(), outPort.Torque); + } - [TestMethod] - public void Test_TimeBased_FirstCycle() - { - var container = new VehicleContainer(); + [TestMethod] + public void Test_TimeBased_FirstCycle() + { + var container = new VehicleContainer(); - var cycleData = DrivingCycleData.ReadFromFileTimeBased(@"TestData\Cycles\Coach time based.vdri"); - var cycle = new TimeBasedDrivingCycle(container, cycleData); + var cycleData = DrivingCycleData.ReadFromFileTimeBased(@"TestData\Cycles\Coach time based.vdri"); + var cycle = new TimeBasedDrivingCycle(container, cycleData); - var outPort = new MockDriverDemandOutPort(); + var outPort = new MockDriverDemandOutPort(); - var inPort = cycle.InPort(); + var inPort = cycle.InPort(); - inPort.Connect(outPort); + inPort.Connect(outPort); - var absTime = new TimeSpan(); - var dt = TimeSpan.FromSeconds(1); + var absTime = new TimeSpan(); + var dt = TimeSpan.FromSeconds(1); - var response = cycle.Request(absTime, dt); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + var response = cycle.Request(absTime, dt); + Assert.IsInstanceOfType(response, typeof (ResponseSuccess)); - Assert.AreEqual(absTime, outPort.AbsTime); - Assert.AreEqual(dt, outPort.Dt); - Assert.AreEqual(0.0.SI<MeterPerSecond>(), outPort.Velocity); - Assert.AreEqual(-0.020237973, outPort.Gradient); - } + Assert.AreEqual(absTime, outPort.AbsTime); + Assert.AreEqual(dt, outPort.Dt); + Assert.AreEqual(0.0.SI<MeterPerSecond>(), outPort.Velocity); + Assert.AreEqual(-0.020237973, outPort.Gradient); + } - [TestMethod] - public void Test_TimeBased_TimeFieldMissing() - { - var container = new VehicleContainer(); + [TestMethod] + public void Test_TimeBased_TimeFieldMissing() + { + var container = new VehicleContainer(); - var cycleData = DrivingCycleData.ReadFromFileTimeBased(@"TestData\Cycles\Cycle time field missing.vdri"); - var cycle = new TimeBasedDrivingCycle(container, cycleData); + var cycleData = DrivingCycleData.ReadFromFileTimeBased(@"TestData\Cycles\Cycle time field missing.vdri"); + var cycle = new TimeBasedDrivingCycle(container, cycleData); - var outPort = new MockDriverDemandOutPort(); + var outPort = new MockDriverDemandOutPort(); - var inPort = cycle.InPort(); + var inPort = cycle.InPort(); - inPort.Connect(outPort); + inPort.Connect(outPort); - var dataWriter = new TestModalDataWriter(); - var absTime = new TimeSpan(); - var dt = TimeSpan.FromSeconds(1); + var dataWriter = new TestModalDataWriter(); + var absTime = new TimeSpan(); + var dt = TimeSpan.FromSeconds(1); - while (cycle.Request(absTime, dt) is ResponseSuccess) - { - Assert.AreEqual(absTime, outPort.AbsTime); - Assert.AreEqual(dt, outPort.Dt); - container.CommitSimulationStep(dataWriter); + while (cycle.Request(absTime, dt) is ResponseSuccess) { + Assert.AreEqual(absTime, outPort.AbsTime); + Assert.AreEqual(dt, outPort.Dt); + container.CommitSimulationStep(dataWriter); - absTime += dt; - } - } - } -} + absTime += dt; + } + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Models/Simulation/SimulationTests.cs b/VectoCoreTest/Models/Simulation/SimulationTests.cs index 21370fc7df7f74d7c42f981c27b96f0ce1ac37f0..e20a04cab733b2b64beb3c37de71134681a74bec 100644 --- a/VectoCoreTest/Models/Simulation/SimulationTests.cs +++ b/VectoCoreTest/Models/Simulation/SimulationTests.cs @@ -1,97 +1,94 @@ using System.Data; using Microsoft.VisualStudio.TestTools.UnitTesting; -using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Models.Simulation { - [TestClass] - public class SimulationTests - { - private const string EngineFile = @"TestData\Components\24t Coach.veng"; - private const string CycleFile = @"TestData\Cycles\Coach Engine Only.vdri"; - - [TestMethod] - public void TestSimulationEngineOnly() - { - var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, "TestEngineOnly-result.vmod"); - - var container = job.GetContainer(); - - Assert.AreEqual(560.0.RPMtoRad(), container.EngineSpeed()); - Assert.AreEqual(0U, container.Gear()); - - try - { - container.VehicleSpeed(); - Assert.Fail("Access to Vehicle speed should fail, because there should be no vehicle in EngineOnly Mode."); - } - catch (VectoException ex) - { - Assert.AreEqual(ex.Message, "no vehicle available!", "Vehicle speed wrong exception message."); - } - } - - [TestMethod] - public void TestEngineOnly_JobRun() - { - var resultFileName = "TestEngineOnly_JobRun-result.vmod"; - var expectedResultsName = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly.vmod"; - - var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, resultFileName); - job.Run(); - - var results = ModalResults.ReadFromFile(resultFileName); - var expectedResults = ModalResults.ReadFromFile(expectedResultsName); - - Assert.AreEqual(expectedResults.Rows.Count, results.Rows.Count, "Moddata: Row count differs."); - - for (var i = 0; i < expectedResults.Rows.Count; i++) - { - var row = results.Rows[i]; - var expectedRow = expectedResults.Rows[i]; - - foreach (DataColumn col in expectedResults.Columns) - Assert.AreEqual(expectedRow[col], row[col], "Moddata: Value differs (Row {0}, Col {1}): {2} != {3}"); - } - } - - [TestMethod] - public void TestEngineOnly_SimulatorRun() - { - var sim = new JobContainer(); - var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, - "TestEngineOnly-SimulatorRun-result.vmod"); - sim.AddJob(job); - sim.RunSimulation(); - - // todo: Add additional assertions. - Assert.Fail("Todo: Add additional assertions."); - } - - [TestMethod] - public void TestEngineOnly_MultipleJobs() - { - var simulation = new JobContainer(); - - var sim1 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, - "TestEngineOnly-MultipleJobs-result1.vmod"); - simulation.AddJob(sim1); - - var sim2 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, - "TestEngineOnly-MultipleJobs-result2.vmod"); - simulation.AddJob(sim2); - - var sim3 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, - "TestEngineOnly-MultipleJobs-result3.vmod"); - simulation.AddJob(sim3); - - simulation.RunSimulation(); - - // todo: Add additional assertions. - Assert.Fail("Todo: Add additional assertions."); - } - } -} + [TestClass] + public class SimulationTests + { + private const string EngineFile = @"TestData\Components\24t Coach.veng"; + private const string CycleFile = @"TestData\Cycles\Coach Engine Only.vdri"; + + [TestMethod] + public void TestSimulationEngineOnly() + { + var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, "TestEngineOnly-result.vmod"); + + var container = job.GetContainer(); + + Assert.AreEqual(560.0.RPMtoRad(), container.EngineSpeed()); + Assert.AreEqual(0U, container.Gear()); + + try { + container.VehicleSpeed(); + Assert.Fail("Access to Vehicle speed should fail, because there should be no vehicle in EngineOnly Mode."); + } catch (VectoException ex) { + Assert.AreEqual(ex.Message, "no vehicle available!", "Vehicle speed wrong exception message."); + } + } + + [TestMethod] + public void TestEngineOnly_JobRun() + { + var resultFileName = "TestEngineOnly_JobRun-result.vmod"; + var expectedResultsName = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly.vmod"; + + var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, resultFileName); + job.Run(); + + var results = ModalResults.ReadFromFile(resultFileName); + var expectedResults = ModalResults.ReadFromFile(expectedResultsName); + + Assert.AreEqual(expectedResults.Rows.Count, results.Rows.Count, "Moddata: Row count differs."); + + for (var i = 0; i < expectedResults.Rows.Count; i++) { + var row = results.Rows[i]; + var expectedRow = expectedResults.Rows[i]; + + foreach (DataColumn col in expectedResults.Columns) { + Assert.AreEqual(expectedRow[col], row[col], "Moddata: Value differs (Row {0}, Col {1}): {2} != {3}"); + } + } + } + + [TestMethod] + public void TestEngineOnly_SimulatorRun() + { + var sim = new JobContainer(); + var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + "TestEngineOnly-SimulatorRun-result.vmod"); + sim.AddJob(job); + sim.RunSimulation(); + + // todo: Add additional assertions. + Assert.Fail("Todo: Add additional assertions."); + } + + [TestMethod] + public void TestEngineOnly_MultipleJobs() + { + var simulation = new JobContainer(); + + var sim1 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + "TestEngineOnly-MultipleJobs-result1.vmod"); + simulation.AddJob(sim1); + + var sim2 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + "TestEngineOnly-MultipleJobs-result2.vmod"); + simulation.AddJob(sim2); + + var sim3 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + "TestEngineOnly-MultipleJobs-result3.vmod"); + simulation.AddJob(sim3); + + simulation.RunSimulation(); + + // todo: Add additional assertions. + Assert.Fail("Todo: Add additional assertions."); + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Models/Simulation/VechicleContainerTests.cs b/VectoCoreTest/Models/Simulation/VechicleContainerTests.cs index bd8437c406278142ff8bac65fc3dff994e47d4be..f5c166a59bfb22e6ef0b5926033bd8fb7bb55e5d 100644 --- a/VectoCoreTest/Models/Simulation/VechicleContainerTests.cs +++ b/VectoCoreTest/Models/Simulation/VechicleContainerTests.cs @@ -20,4 +20,4 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation Assert.IsNotNull(vehicle.EngineSpeed()); } } -} +} \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs index 9b63520caca373daaef0f56ccd53c2d1fc43e371..9ba69f9cdf8ea0d23c3826618a656bc0c731252b 100644 --- a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs @@ -11,95 +11,93 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Models.SimulationComponent { - - [TestClass] - public class CombustionEngineTest - { - private const string CoachEngine = @"TestData\Components\24t Coach.veng"; - - public TestContext TestContext { get; set; } - - [ClassInitialize] - public static void ClassInitialize(TestContext ctx) - { - AppDomain.CurrentDomain.SetData("DataDirectory", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); - } - - - [TestMethod] - public void TestEngineHasOutPort() - { - var vehicle = new VehicleContainer(); - var engineData = CombustionEngineData.ReadFromFile(CoachEngine); - var engine = new CombustionEngine(vehicle, engineData); - - var port = engine.OutShaft(); - Assert.IsNotNull(port); - } - - [TestMethod] - public void TestOutPortRequestNotFailing() - { - var vehicle = new VehicleContainer(); - var engineData = CombustionEngineData.ReadFromFile(CoachEngine); - var engine = new CombustionEngine(vehicle, engineData); - - new EngineOnlyGearbox(vehicle); - - var port = engine.OutShaft(); - - var absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); - var dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); - var torque = 400.SI<NewtonMeter>(); - var engineSpeed = 1500.0.RPMtoRad(); - - port.Request(absTime, dt, torque, engineSpeed); - } - - [TestMethod] - public void TestSimpleModalData() - { - var vehicle = new VehicleContainer(); - var engineData = CombustionEngineData.ReadFromFile(CoachEngine); - var engine = new CombustionEngine(vehicle, engineData); - var gearbox = new EngineOnlyGearbox(vehicle); - var port = engine.OutShaft(); - - var absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); - var dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); - - var torque = new NewtonMeter(); - var engineSpeed = 600.0.RPMtoRad(); - var dataWriter = new TestModalDataWriter(); - - for (var i = 0; i < 21; i++) - { - port.Request(absTime, dt, torque, engineSpeed); - engine.CommitSimulationStep(dataWriter); - if (i > 0) + [TestClass] + public class CombustionEngineTest + { + private const string CoachEngine = @"TestData\Components\24t Coach.veng"; + public TestContext TestContext { get; set; } + + [ClassInitialize] + public static void ClassInitialize(TestContext ctx) + { + AppDomain.CurrentDomain.SetData("DataDirectory", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); + } + + [TestMethod] + public void TestEngineHasOutPort() + { + var vehicle = new VehicleContainer(); + var engineData = CombustionEngineData.ReadFromFile(CoachEngine); + var engine = new CombustionEngine(vehicle, engineData); + + var port = engine.OutShaft(); + Assert.IsNotNull(port); + } + + [TestMethod] + public void TestOutPortRequestNotFailing() + { + var vehicle = new VehicleContainer(); + var engineData = CombustionEngineData.ReadFromFile(CoachEngine); + var engine = new CombustionEngine(vehicle, engineData); + + new EngineOnlyGearbox(vehicle); + + var port = engine.OutShaft(); + + var absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); + var dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); + var torque = 400.SI<NewtonMeter>(); + var engineSpeed = 1500.0.RPMtoRad(); + + port.Request(absTime, dt, torque, engineSpeed); + } + + [TestMethod] + public void TestSimpleModalData() + { + var vehicle = new VehicleContainer(); + var engineData = CombustionEngineData.ReadFromFile(CoachEngine); + var engine = new CombustionEngine(vehicle, engineData); + var gearbox = new EngineOnlyGearbox(vehicle); + var port = engine.OutShaft(); + + var absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); + var dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); + + var torque = new NewtonMeter(); + var engineSpeed = 600.0.RPMtoRad(); + var dataWriter = new TestModalDataWriter(); + + for (var i = 0; i < 21; i++) { + port.Request(absTime, dt, torque, engineSpeed); + engine.CommitSimulationStep(dataWriter); + if (i > 0) { dataWriter.CommitSimulationStep(absTime, dt); - absTime += dt; - } + } + absTime += dt; + } - engineSpeed = 644.4445.RPMtoRad(); - port.Request(absTime, dt, Formulas.PowerToTorque(2329.973.SI<Watt>(), engineSpeed), engineSpeed); - engine.CommitSimulationStep(dataWriter); + engineSpeed = 644.4445.RPMtoRad(); + port.Request(absTime, dt, Formulas.PowerToTorque(2329.973.SI<Watt>(), engineSpeed), engineSpeed); + engine.CommitSimulationStep(dataWriter); Assert.AreEqual(1152.40304, dataWriter.GetDouble(ModalResultField.PaEng), 0.001); dataWriter.CommitSimulationStep(absTime, dt); absTime += dt; - var power = new[] {569.3641, 4264.177}; -; for (var i = 0; i < 2; i++) { + var power = new[] { 569.3641, 4264.177 }; + ; + for (var i = 0; i < 2; i++) { port.Request(absTime, dt, Formulas.PowerToTorque(power[i].SI<Watt>(), engineSpeed), engineSpeed); engine.CommitSimulationStep(dataWriter); dataWriter.CommitSimulationStep(absTime, dt); absTime += dt; - } + } engineSpeed = 869.7512.RPMtoRad(); - port.Request(absTime, dt, Formulas.PowerToTorque(7984.56.SI<Watt>(), engineSpeed), engineSpeed); + port.Request(absTime, dt, Formulas.PowerToTorque(7984.56.SI<Watt>(), engineSpeed), engineSpeed); engine.CommitSimulationStep(dataWriter); @@ -107,8 +105,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent dataWriter.CommitSimulationStep(absTime, dt); absTime += dt; - engineSpeed = 644.4445.RPMtoRad(); - port.Request(absTime, dt, Formulas.PowerToTorque(1351.656.SI<Watt>(), engineSpeed), engineSpeed); + engineSpeed = 644.4445.RPMtoRad(); + port.Request(absTime, dt, Formulas.PowerToTorque(1351.656.SI<Watt>(), engineSpeed), engineSpeed); engine.CommitSimulationStep(dataWriter); Assert.AreEqual(-7108.32, dataWriter.GetDouble(ModalResultField.PaEng), 0.001); @@ -116,47 +114,44 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent absTime += dt; dataWriter.Data.WriteToFile(@"test1.csv"); - } - - + } - [TestMethod] - public void TestEngineMemento() - { - var vehicle = new VehicleContainer(); - var engineData = CombustionEngineData.ReadFromFile(CoachEngine); - var origin = new CombustionEngine(vehicle, engineData); + [TestMethod] + public void TestEngineMemento() + { + var vehicle = new VehicleContainer(); + var engineData = CombustionEngineData.ReadFromFile(CoachEngine); + var origin = new CombustionEngine(vehicle, engineData); - var data = Memento.Serialize(origin); + var data = Memento.Serialize(origin); var restored = new CombustionEngine(vehicle, engineData); - Memento.Deserialize<CombustionEngine>(restored, data); + Memento.Deserialize(restored, data); - Assert.AreEqual(origin, restored, "Serialized with Memento, Deserialized with Memento"); + Assert.AreEqual(origin, restored, "Serialized with Memento, Deserialized with Memento"); - data = origin.Serialize(); + data = origin.Serialize(); restored = new CombustionEngine(vehicle, engineData); - Memento.Deserialize<CombustionEngine>(restored, data); + Memento.Deserialize(restored, data); - Assert.AreEqual(origin, restored, "Serialized with Object, Deserialized with Memento"); + Assert.AreEqual(origin, restored, "Serialized with Object, Deserialized with Memento"); - data = origin.Serialize(); - restored = new CombustionEngine(vehicle, engineData); - restored.Deserialize(data); - - Assert.AreEqual(origin, restored, "Serialized with Object, Deserialized with Object"); - } - - [TestMethod] - public void TestWriteToFile() - { - var vehicle = new VehicleContainer(); - var engineData = CombustionEngineData.ReadFromFile(CoachEngine); - var engine = new CombustionEngine(vehicle, engineData); - - engineData.WriteToFile("engineData test output.veng"); - - } - } -} + data = origin.Serialize(); + restored = new CombustionEngine(vehicle, engineData); + restored.Deserialize(data); + + Assert.AreEqual(origin, restored, "Serialized with Object, Deserialized with Object"); + } + + [TestMethod] + public void TestWriteToFile() + { + var vehicle = new VehicleContainer(); + var engineData = CombustionEngineData.ReadFromFile(CoachEngine); + var engine = new CombustionEngine(vehicle, engineData); + + engineData.WriteToFile("engineData test output.veng"); + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponent/MockPorts.cs b/VectoCoreTest/Models/SimulationComponent/MockPorts.cs index d17ea03f20e81d6de3c006a771f2ced354386014..77617c0b32204491d9cfb0f62f67aec8a4cbd752 100644 --- a/VectoCoreTest/Models/SimulationComponent/MockPorts.cs +++ b/VectoCoreTest/Models/SimulationComponent/MockPorts.cs @@ -6,41 +6,41 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Models.SimulationComponent { - public class MockTnOutPort : ITnOutPort - { - public TimeSpan AbsTime { get; set; } - public TimeSpan Dt { get; set; } - public NewtonMeter Torque { get; set; } - public RadianPerSecond AngularFrequency { get; set; } + public class MockTnOutPort : ITnOutPort + { + public TimeSpan AbsTime { get; set; } + public TimeSpan Dt { get; set; } + public NewtonMeter Torque { get; set; } + public RadianPerSecond AngularFrequency { get; set; } - public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularFrequency) - { - AbsTime = absTime; - Dt = dt; - Torque = torque; - AngularFrequency = angularFrequency; - LogManager.GetLogger(GetType()).DebugFormat("Request: absTime: {0}, dt: {1}, torque: {3}, engineSpeed: {4}", - absTime, dt, torque, angularFrequency); - return new ResponseSuccess(); - } - } + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularFrequency) + { + AbsTime = absTime; + Dt = dt; + Torque = torque; + AngularFrequency = angularFrequency; + LogManager.GetLogger(GetType()).DebugFormat("Request: absTime: {0}, dt: {1}, torque: {3}, engineSpeed: {4}", + absTime, dt, torque, angularFrequency); + return new ResponseSuccess(); + } + } - public class MockDriverDemandOutPort : IDriverDemandOutPort - { - public TimeSpan AbsTime { get; set; } + public class MockDriverDemandOutPort : IDriverDemandOutPort + { + public TimeSpan AbsTime { get; set; } + public TimeSpan Dt { get; set; } + public MeterPerSecond Velocity { get; set; } + public double Gradient { get; set; } - public TimeSpan Dt { get; set; } - public MeterPerSecond Velocity { get; set; } - public double Gradient { get; set; } - public IResponse Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient) - { - AbsTime = absTime; - Dt = dt; - Velocity = velocity; - Gradient = gradient; - LogManager.GetLogger(GetType()).DebugFormat("Request: absTime: {0}, dt: {1}, velocity: {3}, gradient: {4}", - absTime, dt, velocity, gradient); - return new ResponseSuccess(); - } - } + public IResponse Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient) + { + AbsTime = absTime; + Dt = dt; + Velocity = velocity; + Gradient = gradient; + LogManager.GetLogger(GetType()).DebugFormat("Request: absTime: {0}, dt: {1}, velocity: {3}, gradient: {4}", + absTime, dt, velocity, gradient); + return new ResponseSuccess(); + } + } } \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs b/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs index 4f2eeb202a5688d7cde28adc911e13209b286528..5061ea58ae918e3592f0fe39222cae9914ede78c 100644 --- a/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs +++ b/VectoCoreTest/Models/SimulationComponentData/FuelConsumptionMapTest.cs @@ -1,7 +1,6 @@ -using System; +using System.Globalization; using System.IO; using System.Linq; -using System.Globalization; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; @@ -9,46 +8,41 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData { - [TestClass] - public class FuelConsumptionMapTest - { - private const double Tolerance = 0.0001; + [TestClass] + public class FuelConsumptionMapTest + { + private const double Tolerance = 0.0001; - [TestMethod] - public void TestFuelConsumption_FixedPoints() - { - var map = FuelConsumptionMap.ReadFromFile(@"TestData\Components\24t Coach.vmap"); - var lines = File.ReadAllLines(@"TestData\Components\24t Coach.vmap").Skip(1).ToArray(); - AssertMapValuesEqual(lines, map); - } + [TestMethod] + public void TestFuelConsumption_FixedPoints() + { + var map = FuelConsumptionMap.ReadFromFile(@"TestData\Components\24t Coach.vmap"); + var lines = File.ReadAllLines(@"TestData\Components\24t Coach.vmap").Skip(1).ToArray(); + AssertMapValuesEqual(lines, map); + } - [TestMethod] - public void TestFuelConsumption_InterpolatedPoints() - { - var map = FuelConsumptionMap.ReadFromFile(@"TestData\Components\24t Coach.vmap"); - var lines = File.ReadAllLines(@"TestData\Components\24t CoachInterpolated.vmap").Skip(1).ToArray(); - AssertMapValuesEqual(lines, map); - } + [TestMethod] + public void TestFuelConsumption_InterpolatedPoints() + { + var map = FuelConsumptionMap.ReadFromFile(@"TestData\Components\24t Coach.vmap"); + var lines = File.ReadAllLines(@"TestData\Components\24t CoachInterpolated.vmap").Skip(1).ToArray(); + AssertMapValuesEqual(lines, map); + } - private static void AssertMapValuesEqual(string[] lines, FuelConsumptionMap map) - { - for (var i = 1; i < lines.Count(); i++) - { - var entry = lines[i].Split(',').Select(x => double.Parse(x, CultureInfo.InvariantCulture)).ToArray(); - try - { - Assert.AreEqual((double)entry[2].SI().Gramm.Per.Hour.To().Kilo.Gramm.Per.Second, - (double)map.GetFuelConsumption(entry[1].SI<NewtonMeter>(), entry[0].RPMtoRad()), - Tolerance, - string.Format("Line: {0}, n={1}, T={2}", (i + 2), entry[0].SI().Rounds.Per.Minute, entry[1])); - - } - catch (VectoException ex) - { - throw new VectoException(string.Format("Row {0}: Error in ConsumptionMap n={1}, T={2}: {3}", - i + 2, entry[0], entry[1], ex.Message)); - } - } - } - } -} + private static void AssertMapValuesEqual(string[] lines, FuelConsumptionMap map) + { + for (var i = 1; i < lines.Count(); i++) { + var entry = lines[i].Split(',').Select(x => double.Parse(x, CultureInfo.InvariantCulture)).ToArray(); + try { + Assert.AreEqual((double) entry[2].SI().Gramm.Per.Hour.To().Kilo.Gramm.Per.Second, + (double) map.GetFuelConsumption(entry[1].SI<NewtonMeter>(), entry[0].RPMtoRad()), + Tolerance, + string.Format("Line: {0}, n={1}, T={2}", (i + 2), entry[0].SI().Rounds.Per.Minute, entry[1])); + } catch (VectoException ex) { + throw new VectoException(string.Format("Row {0}: Error in ConsumptionMap n={1}, T={2}: {3}", + i + 2, entry[0], entry[1], ex.Message)); + } + } + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs index 78e6060784b097d318a8832fceee92584cb78abe..7f0de7ba188499ef119b8e5b93fa57dfff8ba21a 100644 --- a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs +++ b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs @@ -5,121 +5,113 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData { - [TestClass] - public class FullLoadCurveTest - { - private const string CoachEngineFLD = @"TestData\Components\24t Coach.vfld"; - private const double Tolerance = 0.0001; - - [TestMethod] - public void TestFullLoadStaticTorque() - { - var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - - Assert.AreEqual(1180, (double)fldCurve.FullLoadStationaryTorque(560.0.RPMtoRad()), Tolerance); - Assert.AreEqual(1352, (double)fldCurve.FullLoadStationaryTorque(2000.0.RPMtoRad()), Tolerance); - Assert.AreEqual(1231, (double)fldCurve.FullLoadStationaryTorque(580.0.RPMtoRad()), Tolerance); - } - - [TestMethod] - public void TestFullLoadStaticPower() - { - var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - - Assert.AreEqual(69198.814183, (double)fldCurve.FullLoadStationaryPower(560.0.RPMtoRad()), Tolerance); - Assert.AreEqual(283162.218372, (double)fldCurve.FullLoadStationaryPower(2000.0.RPMtoRad()), Tolerance); - Assert.AreEqual(74767.810760, (double)fldCurve.FullLoadStationaryPower(580.0.RPMtoRad()), Tolerance); - - } - - [TestMethod] - public void TestDragLoadStaticTorque() - { - var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - - Assert.AreEqual(-149, (double)fldCurve.DragLoadStationaryTorque(560.0.RPMtoRad()), Tolerance); - Assert.AreEqual(-301, (double)fldCurve.DragLoadStationaryTorque(2000.0.RPMtoRad()), Tolerance); - Assert.AreEqual(-148.5, (double)fldCurve.DragLoadStationaryTorque(580.0.RPMtoRad()), Tolerance); - Assert.AreEqual(-150, (double)fldCurve.DragLoadStationaryTorque(520.0.RPMtoRad()), Tolerance); - Assert.AreEqual(-339, (double)fldCurve.DragLoadStationaryTorque(2200.0.RPMtoRad()), Tolerance); - } - - [TestMethod] - public void TestDragLoadStaticPower() - { - var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - - Assert.AreEqual(-8737.81636, (double)fldCurve.DragLoadStationaryPower(560.0.RPMtoRad()), Tolerance); - Assert.AreEqual(-63041.29254, (double)fldCurve.DragLoadStationaryPower(2000.0.RPMtoRad()), Tolerance); - Assert.AreEqual(-9019.51251, (double)fldCurve.DragLoadStationaryPower(580.0.RPMtoRad()), Tolerance); - } - - [TestMethod] - public void TestPT1() - { - var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - - Assert.AreEqual(0.6, (double)fldCurve.PT1(560.0.RPMtoRad()), Tolerance); - Assert.AreEqual(0.25, (double)fldCurve.PT1(2000.0.RPMtoRad()), Tolerance); - Assert.AreEqual(0.37, (double)fldCurve.PT1(1700.0.RPMtoRad()), Tolerance); - - } - - /// <summary> - /// [VECTO-78] - /// </summary> - [TestMethod] - public void Test_FileRead_WrongFileFormat_InsufficientColumns() - { - try - { - var curve = FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve insufficient columns.vfld"); - Assert.Fail("this should not be reached."); - } - catch (VectoException ex) - { - Assert.AreEqual("FullLoadCurve Data File must consist of 4 columns.", ex.Message); - } - } - - /// <summary> - /// [VECTO-78] - /// </summary> - [TestMethod] - public void Test_FileRead_HeaderColumnsNotNamedCorrectly() - { - FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve wrong header.vfld"); - //todo: check log file: ensure header warning was written! - } - - /// <summary> - /// [VECTO-78] - /// </summary> - [TestMethod] - public void Test_FileRead_NoHeader() - { - var curve = FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve no header.vfld"); - var result = curve.FullLoadStationaryTorque(1.SI<RadianPerSecond>()); - Assert.AreNotEqual((double)result, 0.0); - } - - /// <summary> - /// [VECTO-78] - /// </summary> - [TestMethod] - public void Test_FileRead_InsufficientEntries() - { - try - { - FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve insufficient entries.vfld"); - Assert.Fail("this should not be reached."); - } - catch (VectoException ex) - { - Assert.AreEqual( - "FullLoadCurve must consist of at least two lines with numeric values (below file header)", - ex.Message); - } - } - } -} + [TestClass] + public class FullLoadCurveTest + { + private const string CoachEngineFLD = @"TestData\Components\24t Coach.vfld"; + private const double Tolerance = 0.0001; + + [TestMethod] + public void TestFullLoadStaticTorque() + { + var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(1180, (double) fldCurve.FullLoadStationaryTorque(560.0.RPMtoRad()), Tolerance); + Assert.AreEqual(1352, (double) fldCurve.FullLoadStationaryTorque(2000.0.RPMtoRad()), Tolerance); + Assert.AreEqual(1231, (double) fldCurve.FullLoadStationaryTorque(580.0.RPMtoRad()), Tolerance); + } + + [TestMethod] + public void TestFullLoadStaticPower() + { + var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(69198.814183, (double) fldCurve.FullLoadStationaryPower(560.0.RPMtoRad()), Tolerance); + Assert.AreEqual(283162.218372, (double) fldCurve.FullLoadStationaryPower(2000.0.RPMtoRad()), Tolerance); + Assert.AreEqual(74767.810760, (double) fldCurve.FullLoadStationaryPower(580.0.RPMtoRad()), Tolerance); + } + + [TestMethod] + public void TestDragLoadStaticTorque() + { + var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(-149, (double) fldCurve.DragLoadStationaryTorque(560.0.RPMtoRad()), Tolerance); + Assert.AreEqual(-301, (double) fldCurve.DragLoadStationaryTorque(2000.0.RPMtoRad()), Tolerance); + Assert.AreEqual(-148.5, (double) fldCurve.DragLoadStationaryTorque(580.0.RPMtoRad()), Tolerance); + Assert.AreEqual(-150, (double) fldCurve.DragLoadStationaryTorque(520.0.RPMtoRad()), Tolerance); + Assert.AreEqual(-339, (double) fldCurve.DragLoadStationaryTorque(2200.0.RPMtoRad()), Tolerance); + } + + [TestMethod] + public void TestDragLoadStaticPower() + { + var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(-8737.81636, (double) fldCurve.DragLoadStationaryPower(560.0.RPMtoRad()), Tolerance); + Assert.AreEqual(-63041.29254, (double) fldCurve.DragLoadStationaryPower(2000.0.RPMtoRad()), Tolerance); + Assert.AreEqual(-9019.51251, (double) fldCurve.DragLoadStationaryPower(580.0.RPMtoRad()), Tolerance); + } + + [TestMethod] + public void TestPT1() + { + var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(0.6, (double) fldCurve.PT1(560.0.RPMtoRad()), Tolerance); + Assert.AreEqual(0.25, (double) fldCurve.PT1(2000.0.RPMtoRad()), Tolerance); + Assert.AreEqual(0.37, (double) fldCurve.PT1(1700.0.RPMtoRad()), Tolerance); + } + + /// <summary> + /// [VECTO-78] + /// </summary> + [TestMethod] + public void Test_FileRead_WrongFileFormat_InsufficientColumns() + { + try { + var curve = FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve insufficient columns.vfld"); + Assert.Fail("this should not be reached."); + } catch (VectoException ex) { + Assert.AreEqual("FullLoadCurve Data File must consist of 4 columns.", ex.Message); + } + } + + /// <summary> + /// [VECTO-78] + /// </summary> + [TestMethod] + public void Test_FileRead_HeaderColumnsNotNamedCorrectly() + { + FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve wrong header.vfld"); + //todo: check log file: ensure header warning was written! + } + + /// <summary> + /// [VECTO-78] + /// </summary> + [TestMethod] + public void Test_FileRead_NoHeader() + { + var curve = FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve no header.vfld"); + var result = curve.FullLoadStationaryTorque(1.SI<RadianPerSecond>()); + Assert.AreNotEqual((double) result, 0.0); + } + + /// <summary> + /// [VECTO-78] + /// </summary> + [TestMethod] + public void Test_FileRead_InsufficientEntries() + { + try { + FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve insufficient entries.vfld"); + Assert.Fail("this should not be reached."); + } catch (VectoException ex) { + Assert.AreEqual( + "FullLoadCurve must consist of at least two lines with numeric values (below file header)", + ex.Message); + } + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Properties/AssemblyInfo.cs b/VectoCoreTest/Properties/AssemblyInfo.cs index f2fb860463db702440a14a395ec387054b3a4b85..38abdb56e451d0b5ed94e2072f2dc0dfa3d4c3a0 100644 --- a/VectoCoreTest/Properties/AssemblyInfo.cs +++ b/VectoCoreTest/Properties/AssemblyInfo.cs @@ -4,6 +4,7 @@ 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("VectoCoreTest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -16,9 +17,11 @@ using System.Runtime.InteropServices; // 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("292ab9c6-e15b-44b5-8145-e655e38b9ac3")] // Version information for an assembly consists of the following four values: @@ -31,5 +34,6 @@ using System.Runtime.InteropServices; // 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")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/VectoCoreTest/Properties/Settings.settings b/VectoCoreTest/Properties/Settings.settings index 049245f401462e7e3dfbb96385e122ca467a9dab..783d16005d7463c59b1edb3063c1a821b57a30e2 100644 --- a/VectoCoreTest/Properties/Settings.settings +++ b/VectoCoreTest/Properties/Settings.settings @@ -1,6 +1,7 @@ <?xml version='1.0' encoding='utf-8'?> + <SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"> - <Profiles> - <Profile Name="(Default)" /> - </Profiles> -</SettingsFile> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> +</SettingsFile> \ No newline at end of file diff --git a/VectoCoreTest/TestData/Cycles/Coach Engine Only Paux.vdri b/VectoCoreTest/TestData/Cycles/Coach Engine Only Paux.vdri index 7d12d2fd1b18211c969b027fb15e9c99f110951f..5e32d4c50afc7a4f6bf2d531cd66f5c16b940233 100644 --- a/VectoCoreTest/TestData/Cycles/Coach Engine Only Paux.vdri +++ b/VectoCoreTest/TestData/Cycles/Coach Engine Only Paux.vdri @@ -1,3952 +1,3956 @@ -<n>,<Pe>,<Padd> -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,-2.38E-07,2 -600,-2.38E-07,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,-2.38E-07,2 -600,2.38E-07,2 -600,0,2 -644.4445,2.329973,2 -644.4445,0.5693641,2 -644.4445,4.264177,2 -869.7512,7.98456,2 -644.4445,1.351656,2 -1015.31,-0.2716608,2 -948.6478,-0.4653716,2 -872.4501,-0.5719776,2 -644.4445,1.012361,2 -816.044,0.1606398,2 -644.4445,3.967641,2 -644.4445,4.3916,2 -645.3466,1.254886,2 -602.9238,0.36098,2 -644.4445,1.097353,2 -644.4445,1.476951,2 -645.6951,2.961375,2 -656.8193,3.33839,2 -688.8293,2.509675,2 -715.7259,3.104633,2 -743.2361,2.779576,2 -759.3434,2.025352,2 -763.0762,1.467997,2 -761.0308,1.383811,2 -757.7582,1.320618,2 -755.406,1.475238,2 -756.3265,1.681716,2 -753.872,1.098228,2 -749.1166,1.411724,2 -747.787,1.465289,2 -743.7986,1.110595,2 -691.6417,-3.012229,2 -627.2637,-0.1685431,2 -1049.495,-0.09707546,2 -644.4445,1.615664,2 -1026.825,0.4667768,2 -977.9754,-0.4151859,2 -906.5457,-0.4785028,2 -764.8557,-2.495939,2 -615.8789,-0.5095253,2 -600,-0.2679868,2 -644.4445,0.5701756,2 -644.4445,1.185031,2 -600,0.2967396,2 -646.6069,3.811063,2 -895.4804,7.923037,2 -653.8535,6.359474,2 -791.9158,11.55912,2 -900.8318,4.931076,2 -1007.856,14.46236,2 -1156.708,13.49057,2 -1345.086,27.20026,2 -1602.138,35.01208,2 -1888.49,46.58702,2 -2103.714,24.29906,2 -2146.359,-1.109985,2 -1286.033,8.800848,2 -1351.937,37.56419,2 -1494.108,56.84015,2 -1650.18,55.71647,2 -1797.949,62.99876,2 -1974.041,90.22348,2 -2191.804,115.1789,2 -2403.877,105.9852,2 -2503.301,18.33513,2 -1611.144,-1.709167,2 -1619.774,43.61679,2 -1655.685,42.16265,2 -1690.462,44.19933,2 -1723.907,42.2117,2 -1766.618,62.7349,2 -1823.327,70.33007,2 -1898.131,102.0343,2 -1980.033,91.64824,2 -2027.516,42.57878,2 -2040.799,27.31307,2 -1396.846,69.06043,2 -1435.803,91.8233,2 -1479.637,89.72998,2 -1511.026,58.87632,2 -1535.129,70.88527,2 -1563.544,76.08076,2 -1591.288,72.46291,2 -1615.981,69.52535,2 -1637.034,63.16708,2 -1654.957,61.31534,2 -1674.975,72.86595,2 -1695.262,64.75288,2 -1709.799,54.75394,2 -1712.769,24.54955,2 -1702.061,5.766651,2 -1685.925,4.414207,2 -1669.991,5.575367,2 -1656.502,12.07608,2 -1644.88,11.30247,2 -1634.482,15.56817,2 -1624.607,12.47053,2 -1610.151,-0.5362444,2 -1594.136,6.376687,2 -1580.163,5.485111,2 -1564.78,1.025784,2 -1550.539,8.4501,2 -1539.777,11.6633,2 -1532.066,17.71403,2 -1521.599,2.418658,2 -1504.309,-4.049212,2 -1481.361,-14.07779,2 -1453.792,-17.15281,2 -1423.724,-18.15207,2 -1385.246,-16.81612,2 -1337.242,-15.72801,2 -1293.188,-15.42869,2 -1281.755,38.3059,2 -1286.484,11.6914,2 -1283.596,17.9171,2 -1285.597,24.78118,2 -1291.778,29.405,2 -1303.359,40.06316,2 -1321.147,47.6144,2 -1343.046,53.40984,2 -1367.31,56.75732,2 -1398.372,76.35516,2 -1441.017,95.91759,2 -1491.115,106.3325,2 -1533.099,77.92695,2 -1561.824,69.6596,2 -1584.033,60.08042,2 -1597.119,41.62484,2 -1603.93,40.29163,2 -1607.558,31.45644,2 -1604.965,19.52167,2 -1600.142,23.70411,2 -1596.299,22.48869,2 -1589.192,12.48158,2 -1578.793,11.02395,2 -1566.889,6.910674,2 -1551.426,-1.123854,2 -1528.707,-15.20682,2 -1502.589,-11.37927,2 -1476.041,-16.47795,2 -1439.148,-17.79036,2 -1386.845,-16.22873,2 -1331.801,-15.54598,2 -1276.609,-14.19835,2 -1222.116,-13.53877,2 -1183.826,-13.63705,2 -1165.594,4.323093,2 -1154.524,-0.2198782,2 -1145.307,8.251244,2 -1136.212,-0.1459947,2 -1127.318,8.395197,2 -1127.425,20.90548,2 -1132.316,19.78157,2 -1134.976,15.85121,2 -1140.847,27.66578,2 -1153.503,32.64259,2 -1173.508,46.8272,2 -1195.77,39.98267,2 -1214.31,39.54551,2 -1235.31,48.15401,2 -1262.019,56.77373,2 -1290.77,56.59818,2 -1317.063,53.30949,2 -1343.879,61.21212,2 -1364.448,38.20493,2 -1372.416,26.90753,2 -1376.097,26.42333,2 -1374.269,11.18833,2 -1368.546,15.03598,2 -1362.863,11.02519,2 -1356.038,11.46854,2 -1346.136,1.988382,2 -1325.11,-16.2194,2 -1284.63,-14.65078,2 -1238.373,-14.2102,2 -1193.929,-12.98282,2 -1155.988,-13.10039,2 -1137.273,2.958799,2 -1132.786,15.8914,2 -1141.075,33.33242,2 -1156.7,34.19608,2 -1179.433,52.38899,2 -1213.827,66.11726,2 -1258.176,83.05579,2 -1305.898,81.63163,2 -1353.754,91.2124,2 -1396.935,75.19558,2 -1438.893,94.76639,2 -1487.004,100.8023,2 -1529.298,83.95088,2 -1563.974,82.77102,2 -1596.393,81.57443,2 -1624.446,72.54066,2 -1640.138,42.54347,2 -1643,29.84203,2 -1638.257,16.47232,2 -1629.605,16.00256,2 -1630.478,48.60144,2 -1642.785,55.60721,2 -1656.623,55.29026,2 -1669.48,53.73763,2 -1680.188,49.11893,2 -1689.163,48.75134,2 -1695.907,42.08216,2 -1700.851,42.99605,2 -1706.79,46.16529,2 -1713.763,47.34768,2 -1720.427,45.77478,2 -1727.319,48.89489,2 -1725.733,15.54477,2 -1714.932,15.2667,2 -1703.74,13.40421,2 -1690.842,8.433504,2 -1676.749,8.346373,2 -1663.421,10.28855,2 -1648.951,3.619027,2 -1633.192,5.002003,2 -1617.433,2.826547,2 -1602.775,7.905733,2 -1589.501,6.74611,2 -1576.428,7.864722,2 -1567.118,18.46364,2 -1564.686,30.00007,2 -1567.427,35.38074,2 -1572.196,36.95614,2 -1576.469,34.14531,2 -1576.307,22.5677,2 -1570.826,16.47429,2 -1563.423,15.84486,2 -1553.562,7.964062,2 -1536.916,-5.952643,2 -1517.233,-2.275624,2 -1497.389,-6.935693,2 -1471.863,-18.41763,2 -1442.372,-18.13165,2 -1414.871,-13.40553,2 -1387.812,-17.13374,2 -1362.057,-10.3961,2 -1346.257,8.515593,2 -1345.787,31.16553,2 -1358.712,46.74545,2 -1379.066,53.84549,2 -1401.382,54.66264,2 -1424.557,58.96523,2 -1447.437,56.39186,2 -1469.605,59.47992,2 -1493.117,63.22589,2 -1515.124,57.4621,2 -1535.841,61.76757,2 -1557.969,64.56117,2 -1578.323,58.54613,2 -1596.594,60.07353,2 -1611.991,50.88236,2 -1621.194,40.61778,2 -1619.421,14.21795,2 -1605.113,-1.868717,2 -1588.762,6.50421,2 -1576.67,11.31663,2 -1569.348,21.61535,2 -1567.91,30.3064,2 -1571.135,36.95245,2 -1576.267,36.91877,2 -1582.797,42.09142,2 -1590.294,40.76203,2 -1597.817,42.91198,2 -1605.462,41.89369,2 -1612.273,40.82465,2 -1619.582,44.26139,2 -1628.167,45.92483,2 -1637.464,47.59579,2 -1648.723,53.73099,2 -1661.419,53.84293,2 -1676.91,65.1045,2 -1695.235,65.79607,2 -1711.21,58.91008,2 -1724.968,59.73791,2 -1739.437,63.20061,2 -1753.772,61.00745,2 -1768,64.61153,2 -1781.368,59.52817,2 -1794.521,65.5128,2 -1809.072,66.50668,2 -1818.449,47.4547,2 -1817.24,26.92148,2 -1805.995,8.979017,2 -1786.662,-4.010155,2 -1765.233,-0.05493259,2 -1742.89,-7.886769,2 -1721.609,2.619378,2 -1703.539,1.704347,2 -1687.591,9.187813,2 -1675.688,15.12251,2 -1669.373,28.10153,2 -1666.148,25.54206,2 -1659.176,14.7161,2 -1647.474,8.565833,2 -1631.875,0.5784202,2 -1615.068,3.583271,2 -1599,2.292942,2 -1587.324,17.45128,2 -1584.315,30.57986,2 -1586.8,35.61685,2 -1593.088,43.5732,2 -1602.506,46.77898,2 -1611.978,44.69442,2 -1618.292,36.94254,2 -1621.436,34.45127,2 -1619.475,19.75505,2 -1612.367,16.75193,2 -1602.009,8.288825,2 -1592.927,20.35848,2 -1589.178,25.61557,2 -1589.299,33.05613,2 -1592.766,36.86369,2 -1600.84,48.93576,2 -1611.79,47.39437,2 -1614.947,23.44294,2 -1610.836,22.92943,2 -1603.433,12.01165,2 -1586.975,-7.003079,2 -1563.772,-9.861372,2 -1540.355,-8.272071,2 -1519.907,-2.04369,2 -1503.677,3.384114,2 -1487.904,-1.296515,2 -1471.513,0.8036427,2 -1454.625,-3.150111,2 -1435.789,-5.048037,2 -1415.583,-7.256803,2 -1396.787,-1.866434,2 -1379.012,-5.011639,2 -1361.345,-2.060575,2 -1341.192,-11.55893,2 -1317.613,-10.92163,2 -1291.294,-15.20063,2 -1254.361,-14.80647,2 -1210.226,-14.88861,2 -1174.65,-14.81055,2 -1147.215,-14.28176,2 -1119.552,-13.7853,2 -1087.993,-13.05181,2 -1052.511,-12.44097,2 -1031.579,5.715624,2 -1037.853,32.76339,2 -1064.428,51.27643,2 -1098.567,52.62703,2 -1138.801,70.14542,2 -1186.926,77.43063,2 -1233.348,72.79241,2 -1273.076,66.44997,2 -1304.85,56.3991,2 -1335.952,68.81242,2 -1369.93,68.46135,2 -1401.744,66.97513,2 -1432.914,70.78075,2 -1462.162,65.10287,2 -1490.927,73.24111,2 -1519.369,67.75407,2 -1544.292,65.61349,2 -1569.657,72.50694,2 -1591.342,56.41633,2 -1604.709,47.0724,2 -1608.203,24.27454,2 -1601.539,12.98722,2 -1592.376,15.38727,2 -1589.407,33.14979,2 -1593.76,39.76634,2 -1602.748,49.21623,2 -1614.531,50.16054,2 -1628.221,57.05817,2 -1646.023,65.98457,2 -1665.665,65.65594,2 -1683.789,63.0876,2 -1698.339,55.09802,2 -1707.865,46.70007,2 -1711.465,34.71091,2 -1712.298,37.05171,2 -1713.763,37.07273,2 -1717.041,43.76989,2 -1723.678,49.61529,2 -1733.472,56.02866,2 -1744.677,55.90408,2 -1750.736,38.25808,2 -1755.6,52.16808,2 -1767.544,65.1767,2 -1784.929,74.09778,2 -1810.361,98.34163,2 -1843.734,108.7761,2 -1876.234,100.4823,2 -1900.229,80.1554,2 -1920.624,89.84477,2 -1923.486,11.55359,2 -1384.726,-6.716908,2 -1365.214,-9.758064,2 -1335.167,-15.65223,2 -1305.561,-9.438278,2 -1293.54,25.59272,2 -1293.716,51.81037,2 -1298.87,51.8591,2 -1307.468,70.9785,2 -1321.719,83.69244,2 -1340.242,97.09694,2 -1361.364,102.0721,2 -1381.797,98.08289,2 -1396.943,76.64746,2 -1408.093,78.5398,2 -1421.649,92.87965,2 -1436.79,90.6324,2 -1452.067,97.12432,2 -1465.261,81.55907,2 -1474.817,78.22183,2 -1481.586,66.6988,2 -1486.936,71.00793,2 -1494.076,78.64029,2 -1504.805,94.48131,2 -1519.545,105.7961,2 -1533.59,93.55258,2 -1544.594,90.03146,2 -1553.279,81.37687,2 -1560.448,82.33672,2 -1566.855,78.04972,2 -1572.087,76.19854,2 -1574.895,63.56385,2 -1574.396,55.5367,2 -1573.515,61.01888,2 -1573.036,57.94503,2 -1570.845,49.96451,2 -1566.747,45.35576,2 -1559.803,31.16218,2 -1548.662,17.72969,2 -1536.094,20.5824,2 -1523.252,14.39674,2 -1509.539,13.54565,2 -1497.577,23.35009,2 -1487.474,23.31975,2 -1479.131,32.58831,2 -1472.793,34.21489,2 -1471.189,59.98996,2 -1474.25,61.94712,2 -1479.943,76.42569,2 -1487.386,73.62328,2 -1493.87,72.10479,2 -1498.252,62.06528,2 -1504.355,83.55563,2 -1514.009,85.13411,2 -1522.518,78.52847,2 -1528.054,68.42541,2 -1531.879,68.98322,2 -1535.693,69.12019,2 -1539.86,71.95422,2 -1543.156,64.46819,2 -1544.232,58.62698,2 -1542.999,50.14769,2 -1540.877,52.80785,2 -1538.393,47.5109,2 -1535.83,51.87814,2 -1534.607,55.44809,2 -1535.527,65.06208,2 -1540.046,78.20454,2 -1545.102,69.33004,2 -1542.54,31.26162,2 -1534.764,36.16859,2 -1527.125,30.95866,2 -1517.892,25.15287,2 -1508.043,25.83571,2 -1498.927,28.26935,2 -1490.525,28.91031,2 -1483.571,35.82453,2 -1480.344,50.35513,2 -1480.471,55.54207,2 -1481.576,56.2795,2 -1481.869,50.83329,2 -1480.745,47.77131,2 -1478.28,42.57355,2 -1476.333,50.48153,2 -1475.023,46.08316,2 -1474.094,52.55144,2 -1473.565,48.33829,2 -1472.754,50.75901,2 -1472.802,53.36675,2 -1472.646,49.53503,2 -1472.675,54.45502,2 -1472.744,49.77462,2 -1473.644,59.45992,2 -1476.216,59.98241,2 -1477.918,54.67937,2 -1478.984,56.45734,2 -1479.639,52.3883,2 -1481.234,62.24279,2 -1484.403,62.18639,2 -1488.227,66.80893,2 -1491.239,57.95909,2 -1493.107,60.41497,2 -1495.973,64.38061,2 -1498.477,58.73077,2 -1499.935,58.45076,2 -1498.233,39.69763,2 -1490.447,21.17598,2 -1479.659,20.41969,2 -1469.35,22.65018,2 -1458.865,18.07665,2 -1449.143,25.79696,2 -1440.174,21.3046,2 -1431.009,23.49089,2 -1422.334,22.9997,2 -1411.819,11.86371,2 -1402.048,25.93449,2 -1394.321,22.3779,2 -1386.849,26.39423,2 -1381.039,30.80274,2 -1374.056,19.11548,2 -1365.478,21.04128,2 -1357.8,23.10369,2 -1351.413,27.2389,2 -1348.342,40.50266,2 -1348.86,46.52771,2 -1354.67,69.74982,2 -1364.49,69.70929,2 -1375.415,77.81886,2 -1386.575,73.11307,2 -1395.456,67.07029,2 -1403.241,68.56764,2 -1410.313,64.41555,2 -1416.035,62.10302,2 -1420.035,55.49044,2 -1423.057,57.14668,2 -1424.515,46.92026,2 -1424.466,48.65111,2 -1424.349,46.51535,2 -1420.514,27.12698,2 -1412.171,19.98239,2 -1399.202,-0.2213111,2 -1381.088,-8.825974,2 -1360.959,-10.97501,2 -1339.52,-15.13851,2 -1315.038,-15.79168,2 -1271.67,-13.71585,2 -1205.943,-12.13631,2 -1122.19,-10.03683,2 -1048.169,-10.36391,2 -990.1788,-9.246284,2 -928.2859,-9.212884,2 -867.8992,-9.020022,2 -804.412,-8.525709,2 -729.0021,-8.260065,2 -887.2314,-7.793596,2 -782.4908,-7.821894,2 -665.2287,-6.784316,2 -772.3559,-4.63562,2 -600,-6.277975,2 -614.9388,-5.288214,2 -696.7551,-3.49948,2 -600,-1.283326,2 -664.3683,-1.597912,2 -600,-1.778763,2 -600,-0.7596555,2 -600,-0.1736608,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,-2.38E-07,2 -600,-2.38E-07,2 -600,0,2 -600,0,2 -600,0,2 -600,2.38E-07,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,0,2 -600,2.38E-07,2 -600,0,2 -600,0,2 -600,-2.38E-07,2 -600,0,2 -644.4445,1.612164,2 -644.4445,6.538949,2 -785.0072,0.8882241,2 -841.1434,3.194654,2 -644.4445,4.281434,2 -1009.552,-0.1017489,2 -970.5985,0.5266633,2 -942.8003,0.3860083,2 -644.4445,2.60547,3 -644.4445,3.600683,3 -614.3267,0.6870103,3 -645.5776,1.867147,3 -654.6205,4.423994,3 -692.8177,1.993502,3 -708.7716,2.477404,3 -728.2538,2.476002,3 -755.4572,3.501919,3 -778.621,2.18979,3 -785.3195,1.743106,3 -784.5526,1.346341,3 -785.7797,1.974449,3 -787.5695,1.416916,3 -784.4503,1.4051,3 -782.5583,1.548533,3 -779.4391,1.255069,3 -775.604,1.452504,3 -776.0643,1.739155,3 -781.2288,2.003658,3 -791.558,2.376166,3 -794.8305,1.215703,3 -790.2285,1.457595,3 -788.5922,1.549223,3 -777.0869,0.305099,3 -717.4133,-3.12269,3 -620.5139,-2.686603,3 -644.4445,1.54447,3 -1016.479,0.8481472,3 -962.2321,-0.9291403,3 -847.3507,-1.475364,3 -747.673,-0.2668786,3 -676.963,-0.3898878,3 -602.3846,-0.3104959,3 -600,-0.1901872,3 -600,0.1421087,3 -644.4445,0.9691319,3 -658.5208,5.586625,3 -644.4445,10.10435,3 -770.7463,12.22105,3 -927.217,10.38821,3 -1058.376,12.88986,3 -1195.672,14.52883,3 -1370.653,24.36733,3 -1588.996,29.57337,3 -1850.804,44.95491,3 -2070.22,25.92677,3 -2149.734,8.226243,3 -1319.83,16.38028,3 -1416.364,49.23381,3 -1559.182,49.06653,3 -1710.518,65.96037,3 -1919.854,106.5468,3 -2084.814,43.9015,3 -2166.125,47.40614,3 -1477.623,84.04178,3 -1568.573,75.32056,3 -1632.52,51.08742,3 -1672.844,42.69801,3 -1694.081,22.06184,3 -1716.868,46.75986,3 -1754.409,48.50185,3 -1799.228,62.44069,3 -1858.482,78.40761,3 -1900.06,34.26859,3 -1927.36,55.25987,3 -1337.101,81.45631,3 -1385.247,97.38922,3 -1429.335,76.56412,3 -1463.264,73.28956,3 -1495.965,77.56803,3 -1528.196,76.33263,3 -1558.654,76.35077,3 -1587.647,75.73126,3 -1612.448,66.08598,3 -1634.75,70.53711,3 -1654.379,59.56525,3 -1669.87,58.48478,3 -1687.604,69.47137,3 -1707.072,66.88885,3 -1722.079,55.75189,3 -1724.041,21.08878,3 -1712.486,6.930377,3 -1696.472,4.276927,3 -1677.568,-3.706191,3 -1660.694,10.34586,3 -1651.074,20.23409,3 -1643.645,17.34347,3 -1632.816,8.011366,3 -1618.776,5.67132,3 -1603.688,3.707242,3 -1588.144,3.373533,3 -1571.404,-0.8783412,3 -1555.752,6.147068,3 -1543.593,9.695271,3 -1532.576,9.228716,3 -1522.379,11.73368,3 -1509.777,1.065055,3 -1489.946,-10.28071,3 -1465.427,-12.51891,3 -1440.021,-12.71381,3 -1402.846,-16.25399,3 -1355.514,-15.46913,3 -1313.435,-14.94506,3 -1291.697,11.92974,3 -1290.622,22.9257,3 -1291.334,16.68974,3 -1292.651,24.62087,3 -1298.683,29.66311,3 -1308.639,35.86757,3 -1329.033,59.74829,3 -1361.923,73.65525,3 -1400.414,80.50338,3 -1437.67,75.37047,3 -1474.187,83.83059,3 -1510.207,79.0104,3 -1541.698,74.4771,3 -1566.836,62.39557,3 -1586.464,59.38128,3 -1599.685,43.04843,3 -1606.496,39.10833,3 -1607.544,24.1147,3 -1602.614,18.94668,3 -1599.308,29.22934,3 -1598.395,26.77416,3 -1592.524,12.49185,3 -1582.703,13.13161,3 -1570.221,3.125345,3 -1548.953,-14.38402,3 -1520.766,-17.64579,3 -1492.177,-15.95768,3 -1453.188,-19.0262,3 -1405.211,-17.32,3 -1359.907,-15.5539,3 -1311.877,-14.40117,3 -1259.963,-13.38175,3 -1212.524,-12.87038,3 -1177.001,-12.74935,3 -1155.424,-1.723226,3 -1141.801,-0.260747,3 -1134.492,12.46988,3 -1133.995,15.73124,3 -1130.65,5.669389,3 -1126.767,14.28826,3 -1128.648,19.20252,3 -1133.216,20.79155,3 -1142.795,31.54515,3 -1160.919,42.30621,3 -1179.715,34.65625,3 -1197.906,42.59779,3 -1221.082,49.09034,3 -1245.937,49.3044,3 -1271.692,54.20898,3 -1300.591,60.77997,3 -1329.168,56.62835,3 -1354.789,55.80923,3 -1375.788,46.10873,3 -1385.73,25.64256,3 -1386.025,18.74092,3 -1383.688,17.9726,3 -1379.388,12.89893,3 -1372.698,10.80366,3 -1364.207,7.388607,3 -1349.334,-6.829912,3 -1327.031,-12.3538,3 -1289.95,-14.04064,3 -1243.626,-13.43234,3 -1200.889,-12.65873,3 -1162.021,-12.30316,3 -1138.523,0.8973355,3 -1130.394,9.3073,3 -1135.07,31.08614,3 -1156.795,50.95563,3 -1189.187,59.67162,3 -1226.563,67.66388,3 -1268.951,78.01559,3 -1312.414,76.58404,3 -1356.025,85.13309,3 -1401.126,87.58305,3 -1444.898,88.26737,3 -1487.286,90.28471,3 -1527.847,89.14961,3 -1565.344,86.64429,3 -1597.481,76.86526,3 -1626.864,82.09353,3 -1642.073,31.50566,3 -1639.99,23.92768,3 -1637.76,30.81757,3 -1638.123,32.71453,3 -1642.126,43.46971,3 -1650.376,47.85925,3 -1656.905,38.26996,3 -1663.717,49.5445,3 -1672.006,44.13668,3 -1679.073,46.09537,3 -1685.71,43.32407,3 -1691.084,42.26889,3 -1696.646,44.54321,3 -1703.364,46.98836,3 -1710.511,46.79175,3 -1716.906,45.01366,3 -1717.444,26.1797,3 -1711.129,20.26562,3 -1704.439,24.31491,3 -1696.458,15.16069,3 -1684.38,9.138308,3 -1669.212,3.496205,3 -1653.412,6.050759,3 -1636.148,-2.083723,3 -1620.402,10.29929,3 -1606.523,3.2822,3 -1590.468,2.226402,3 -1576.711,10.1251,3 -1568.824,20.93763,3 -1567.413,31.03271,3 -1569.711,33.10635,3 -1572.452,32.69432,3 -1574.655,31.5523,3 -1572.747,19.22354,3 -1565.035,12.21235,3 -1556.195,15.0088,3 -1543.351,-1.151437,3 -1523.306,-7.844097,3 -1498.451,-15.2105,3 -1471.473,-14.222,3 -1443.514,-17.75576,3 -1418.028,-8.075694,3 -1395.819,-9.842525,3 -1378.085,3.328753,3 -1367.149,8.02681,3 -1360.404,14.89146,3 -1361.842,31.14586,3 -1371.771,39.49014,3 -1387.436,48.75327,3 -1406.608,51.37,3 -1428.548,59.16101,3 -1453.08,61.76308,3 -1479.238,67.222,3 -1503.811,59.92773,3 -1525.214,60.14183,3 -1544.184,54.53143,3 -1562.268,59.49051,3 -1582.313,63.16959,3 -1599.873,53.45661,3 -1613.429,51.63828,3 -1621.181,35.03048,3 -1616.371,9.457516,3 -1600.061,-3.788047,3 -1581.856,2.248221,3 -1572.667,24.77247,3 -1572.022,30.03358,3 -1574.01,33.46582,3 -1578.242,37.671,3 -1584.06,39.13469,3 -1589.837,38.06779,3 -1595.385,38.90419,3 -1601.216,39.5349,3 -1606.859,38.81017,3 -1614.638,47.36164,3 -1624.701,47.38615,3 -1636,52.69853,3 -1647.057,47.73088,3 -1657.59,52.09483,3 -1669.158,52.50356,3 -1683.198,62.20206,3 -1702.491,73.03305,3 -1723.463,70.75262,3 -1743.683,73.13956,3 -1762.667,68.86513,3 -1777.58,60.39309,3 -1789.188,58.30213,3 -1797.921,50.87263,3 -1806.855,60.13579,3 -1817.388,58.0382,3 -1823.299,43.58347,3 -1816.582,10.14859,3 -1802.529,14.92394,3 -1786.299,1.025387,3 -1768.927,9.511108,3 -1751.623,0.3174438,3 -1732.894,3.221305,3 -1714.636,1.037209,3 -1696.606,3.044764,3 -1683.345,16.9832,3 -1676.05,23.35215,3 -1669.494,19.07921,3 -1660.667,14.90462,3 -1649.65,10.84701,3 -1637.733,11.08645,3 -1623.559,2.431441,3 -1610.325,13.43634,3 -1600.115,11.95773,3 -1593.007,23.21765,3 -1593.733,37.80044,3 -1600.921,45.08272,3 -1610.755,47.47602,3 -1621.087,47.78857,3 -1627.616,35.45415,3 -1628.436,28.78426,3 -1624.513,19.24914,3 -1617.298,17.2322,3 -1609.13,15.51832,3 -1601.445,18.32353,3 -1596.178,23.1551,3 -1595.479,33.32108,3 -1600.276,41.6428,3 -1609.909,50.18336,3 -1618.373,38.57851,3 -1622.498,36.17999,3 -1621.987,23.06949,3 -1614.45,12.16186,3 -1598.261,-5.880579,3 -1576.576,-6.21808,3 -1557.216,0.2066689,3 -1540.557,1.06763,3 -1523.776,-0.7704601,3 -1505.168,-4.783222,3 -1484.424,-7.280366,3 -1461.786,-10.48103,3 -1437.992,-10.87021,3 -1412.439,-15.4868,3 -1386.16,-13.11512,3 -1361.533,-11.51401,3 -1337.054,-12.97312,3 -1311.675,-13.94429,3 -1284.644,-14.70514,3 -1260.877,-6.438118,3 -1239.233,-12.14887,3 -1213.585,-13.36887,3 -1189.711,-8.318381,3 -1167.449,-12.13369,3 -1133.834,-11.54234,3 -1098.11,-11.47418,3 -1073.161,-9.736206,3 -1051.866,-8.969399,3 -1043.845,17.9187,3 -1059.793,42.8426,3 -1091.15,54.27356,3 -1132.423,69.97617,3 -1179.849,74.85709,3 -1224.723,70.31767,3 -1266.425,73.1416,3 -1304.474,66.09874,3 -1339.956,71.33346,3 -1376.07,72.68569,3 -1408.422,65.08088,3 -1436.595,64.42775,3 -1462.377,61.2652,3 -1487.568,65.8431,3 -1513.982,68.2971,3 -1540.825,70.66122,3 -1565.277,63.87906,3 -1586.142,61.8507,3 -1603.258,53.73509,3 -1610.003,28.49205,3 -1602.412,5.785827,3 -1591.718,17.46236,3 -1587.728,27.60659,3 -1590.347,39.33879,3 -1599.711,50.57925,3 -1614.356,58.24709,3 -1631.714,61.5585,3 -1649.959,63.41554,3 -1667.223,60.33664,3 -1682.902,59.92071,3 -1697.641,58.86283,3 -1708.402,47.30275,3 -1712.889,37.3675,3 -1714.622,37.78582,3 -1716.933,39.62757,3 -1720.386,42.15772,3 -1725.639,46.5316,3 -1733.472,52.14337,3 -1742.568,52.02161,3 -1752.026,54.51895,3 -1760.92,50.98923,3 -1773.2,68.27187,3 -1792.224,77.96797,3 -1821.486,110.3905,3 -1859.212,115.6734,3 -1886.512,75.2928,3 -1904.73,83.84886,3 -1920.543,68.10039,3 -1923.083,32.01192,3 -1906.866,-6.502386,3 -1369.067,-8.091158,3 -1347.198,-16.18642,3 -1322.599,-15.63903,3 -1300.348,-10.72464,3 -1291.3,42.13477,3 -1295.232,54.72806,3 -1305.844,78.21381,3 -1323.205,92.89117,3 -1342.943,94.77242,3 -1363.46,101.6814,3 -1385.072,105.6614,3 -1401.614,77.6887,3 -1414.802,90.22686,3 -1429.796,90.92907,3 -1445.416,97.26785,3 -1460.968,94.02265,3 -1474.025,85.8418,3 -1482.309,68.04903,3 -1486.554,63.08653,3 -1491.151,71.01434,3 -1497.039,71.83271,3 -1507.27,98.90955,3 -1520.142,90.28288,3 -1531.712,93.81809,3 -1542.735,89.45779,3 -1550.501,75.71756,3 -1555.763,75.2889,3 -1560.967,76.44486,3 -1565.573,72.56293,3 -1568.879,69.08176,3 -1571.598,69.47919,3 -1572.166,55.82536,3 -1571.677,62.81889,3 -1571.921,60.4342,3 -1570.689,53.40608,3 -1566.415,40.77371,3 -1555.499,10.54896,3 -1539.664,8.183149,3 -1524.034,9.895695,3 -1510.967,22.06216,3 -1500.463,23.95686,3 -1491.063,27.36668,3 -1482.349,26.82351,3 -1476.999,46.35995,3 -1477.996,64.20844,3 -1481.899,64.05076,3 -1485.909,65.5948,3 -1490.075,65.75693,3 -1495.259,72.5956,3 -1502.116,77.00091,3 -1508.6,71.68607,3 -1514.263,73.26437,3 -1521.178,80.59914,3 -1529.15,81.26859,3 -1536.368,77.57661,3 -1542.686,77.1497,3 -1547,66.23773,3 -1548.115,57.8325,3 -1546.481,49.11549,3 -1544.408,54.76034,3 -1543.166,53.98143,3 -1541.073,49.1928,3 -1539.361,55.99929,3 -1538.862,56.49809,3 -1538.393,56.0927,3 -1540.417,72.0712,3 -1545.18,73.70837,3 -1546.256,49.76416,3 -1542.735,44.97318,3 -1535.145,23.71458,3 -1523.252,17.02971,3 -1509.617,11.41548,3 -1496.003,15.4281,3 -1487.171,38.66481,3 -1482.3,38.17532,3 -1480.637,57.24352,3 -1481.762,54.72427,3 -1482.73,56.49815,3 -1483.307,52.52861,3 -1482.72,49.56577,3 -1481.508,48.64921,3 -1480.187,48.71376,3 -1478.955,48.95982,3 -1477.576,47.62597,3 -1477.849,58.67931,3 -1479.013,53.03189,3 -1479.307,53.63831,3 -1480.021,55.61882,3 -1480.793,54.11613,3 -1481.361,54.51465,3 -1483.004,60.71709,3 -1484.578,54.38765,3 -1485.42,56.56187,3 -1485.889,52.28399,3 -1486.613,58.18631,3 -1488.002,56.44076,3 -1489.87,61.34771,3 -1490.917,51.78019,3 -1491.102,56.30661,3 -1492.227,57.52043,3 -1493.675,58.47193,3 -1495.113,57.72102,3 -1495.445,51.99366,3 -1494.271,48.60529,3 -1489.625,30.71955,3 -1480.001,17.82528,3 -1467.472,12.0361,3 -1457.623,32.14432,3 -1450.424,26.50847,3 -1441.191,19.21676,3 -1431.459,22.39477,3 -1422.754,23.97624,3 -1414.069,21.42962,3 -1406.89,31.4945,3 -1401.579,31.19041,3 -1395.554,26.72908,3 -1387.563,19.29863,3 -1377.782,15.70328,3 -1368.803,22.63366,3 -1361.243,22.56006,3 -1353.398,20.18481,3 -1347.96,34.80918,3 -1349.799,59.43176,3 -1356.929,64.2579,3 -1365.889,70.86021,3 -1376.755,76.60091,3 -1387.504,72.27655,3 -1395.348,62.18171,3 -1402.557,70.15619,3 -1408.826,58.08114,3 -1414.47,67.74133,3 -1420.152,59.29419,3 -1424.652,61.93027,3 -1429.249,60.66118,3 -1431.322,48.02657,3 -1430.774,45.73412,3 -1426.217,24.6445,3 -1410.704,-15.22193,3 -1391.456,1.596369,3 -1375.386,-1.242421,3 -1360.089,4.432325,3 -1342.327,-12.48885,3 -1315.958,-15.63675,3 -1278.253,-14.49595,3 -1226.61,-12.92336,3 -1157.421,-11.01548,3 -1084.691,-10.37803,3 -1016.333,-9.222387,3 -953.2953,-8.877071,3 -891.1482,-8.744204,3 -1132.584,-10.29824,3 -1027.589,-7.797905,3 -906.3764,-7.333625,3 -778.9708,-6.812672,3 -640.4005,-6.574084,3 -725.2108,-4.330684,3 -600,-6.607558,3 -974.2606,0.2646341,3 -678.2445,-2.214189,3 -600,-2.06674,3 -600,-2.121689,3 -600,-1.457825,3 -600,-0.0909586,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,2.38E-07,3 -600,-2.38E-07,3 -600,2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,-2.38E-07,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,4.77E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,2.38E-07,3 -644.4445,0.07269168,3 -644.4445,0.5636628,3 -644.4445,6.32637,3 -909.8743,8.952326,3 -612.8438,0.4596145,3 -1049.945,0.5363288,3 -644.4445,1.307286,3 -644.4445,1.506667,3 -644.4445,1.191484,3 -644.4445,1.223324,3 -644.5549,1.372464,3 -645.5549,2.282104,3 -647.3238,2.434664,3 -660.2452,2.209997,3 -681.7216,2.61131,3 -706.7773,2.741129,3 -730.1458,2.619758,3 -748.145,2.314906,3 -760.0593,2.050172,3 -764.6102,1.540037,3 -765.2238,1.621832,3 -763.9455,1.326239,3 -764.4057,1.815315,3 -767.3715,1.615054,3 -764.6102,1.172328,3 -763.6898,1.813547,3 -765.7863,1.513745,3 -764.7125,1.459806,3 -763.4852,1.49177,3 -760.6218,1.268719,3 -717.6179,-2.408862,3 -665.5632,0.2176919,3 -624.9115,-1.213306,3 -1023.406,-0.02850914,3 -644.4445,2.188613,3 -998.4866,-0.7567296,3 -913.1129,-0.6905825,3 -792.6539,-1.726186,3 -682.2707,-0.2418582,3 -619.2075,-0.1684604,3 -644.4445,0.6611562,3 -646.427,1.844816,3 -674.444,1.06398,3 -698.6438,1.278553,3 -843.8422,6.181966,3 -645.6003,6.826957,3 -727.7936,6.854918,3 -867.4923,13.15338,3 -1035.213,14.05835,3 -1166.934,11.57775,3 -1302.747,18.54018,3 -1484.631,24.88181,3 -1734.831,42.28856,3 -2034.273,49.13046,3 -2212.783,14.95125,3 -1365.991,14.98481,3 -1435.985,36.59709,3 -1555.953,48.97858,3 -1705.628,64.5892,3 -1887.01,84.50237,3 -2010.176,29.41932,3 -1359.912,69.16082,3 -1460.599,91.42927,3 -1564.59,85.87419,3 -1639.38,57.33976,3 -1678.83,35.33801,3 -1693.723,19.23966,3 -1709.133,37.07459,3 -1753.812,70.30568,3 -1809.11,58.7817,3 -1828.497,10.1565,3 -1245.703,51.546,3 -1279.657,74.22597,3 -1325.282,88.26819,3 -1368.083,72.68974,3 -1405.977,80.60335,3 -1446.416,85.91576,3 -1481.576,70.02934,3 -1508.876,66.10561,3 -1538.958,82.82529,3 -1572.196,80.56322,3 -1601.915,75.8309,3 -1627.751,71.48734,3 -1648.79,62.65011,3 -1666.484,62.48646,3 -1683.574,62.6969,3 -1701.953,69.27721,3 -1717.592,55.01025,3 -1723.154,34.47604,3 -1716.396,10.84506,3 -1701.523,4.702551,3 -1681.102,-8.599273,3 -1661.836,7.633382,3 -1652.243,23.09983,3 -1646.547,20.57926,3 -1637.236,10.19999,3 -1622.242,0.4904656,3 -1602.922,-4.652774,3 -1584.731,3.380548,3 -1570.49,7.09161,3 -1557.458,6.66973,3 -1543.848,4.555008,3 -1531.689,10.66433,3 -1519.437,3.691454,3 -1503.61,-1.150481,3 -1485.728,-3.026744,3 -1464.379,-11.14701,3 -1436.985,-17.6633,3 -1401.435,-16.52778,3 -1357.637,-15.3913,3 -1312.307,-14.65012,3 -1287.908,11.86469,3 -1286,20.54327,3 -1286.619,18.54342,3 -1288.244,23.31835,3 -1295.069,32.82963,3 -1308.289,41.42417,3 -1326.36,47.51019,3 -1350.341,60.05747,3 -1386.146,84.80302,3 -1424.275,71.51812,3 -1459.61,82.11712,3 -1496.731,82.10949,3 -1531.165,78.98655,3 -1560.709,71.02921,3 -1584.879,65.1485,3 -1601.875,49.84313,3 -1609.842,36.42356,3 -1612.555,32.75125,3 -1610.258,19.61487,3 -1605.542,24.35468,3 -1602.197,23.91504,3 -1596.433,15.96346,3 -1585.846,7.36155,3 -1572.707,6.84079,3 -1554.569,-8.548178,3 -1529.58,-14.25133,3 -1502.374,-15.33138,3 -1473.287,-18.2294,3 -1433.115,-16.61605,3 -1379.361,-15.28753,3 -1322.517,-14.32261,3 -1269.65,-13.59477,3 -1223.823,-13.03917,3 -1191.054,-10.34762,3 -1167.623,-10.96569,3 -1146.087,-7.865382,3 -1138.617,20.75992,3 -1139.92,11.95193,3 -1135.07,6.090739,3 -1128.836,8.454925,3 -1127.815,18.23122,3 -1133.229,23.74462,3 -1145.025,33.94183,3 -1162.007,37.24741,3 -1180.266,38.54793,3 -1199.371,41.02165,3 -1220.437,45.36328,3 -1244.338,50.5095,3 -1270.631,54.25564,3 -1298.159,56.81184,3 -1326.924,60.92234,3 -1355.084,58.48366,3 -1378.461,50.37475,3 -1393.267,35.86261,3 -1398.198,22.63688,3 -1395.484,13.71113,3 -1386.67,4.619095,3 -1373.732,1.322395,3 -1360.028,1.926163,3 -1347.05,2.909883,3 -1327.864,-13.99705,3 -1303.439,-10.30259,3 -1270.98,-13.94411,3 -1227.45,-13.10693,3 -1189.361,-12.86395,3 -1163.257,-9.064267,3 -1149.096,6.519079,3 -1145.415,14.67137,3 -1153.382,34.60891,3 -1178.546,57.754,3 -1216.998,71.03598,3 -1263.134,83.27469,3 -1314.765,93.22186,3 -1365.711,89.68562,3 -1406.138,70.3726,3 -1441.432,80.56233,3 -1480.152,86.0248,3 -1517.623,82.35265,3 -1553.777,87.54527,3 -1590.871,91.02081,3 -1619.381,63.71481,3 -1634.092,47.46525,3 -1638.526,29.794,3 -1635.489,22.06191,3 -1635.758,40.95305,3 -1643.712,48.7066,3 -1653.788,49.15121,3 -1663.139,47.23022,3 -1672.597,50.53967,3 -1682.109,48.42113,3 -1690.426,47.30361,3 -1696.001,39.47346,3 -1699.468,40.3076,3 -1704.479,45.37587,3 -1710.861,45.75566,3 -1718.881,52.00259,3 -1722.791,31.61168,3 -1716.893,16.77742,3 -1706.844,16.1372,3 -1696.579,15.30738,3 -1686.61,16.48245,3 -1676.655,14.68511,3 -1666.323,14.48469,3 -1653.439,5.125021,3 -1638.015,4.899573,3 -1622.054,2.485665,3 -1605.65,2.586072,3 -1589.635,3.008597,3 -1576.482,11.31122,3 -1568.972,20.98672,3 -1568.045,32.59629,3 -1571.82,36.49885,3 -1575.689,33.22871,3 -1577.006,28.33649,3 -1576.509,27.30095,3 -1573.043,18.44022,3 -1566.083,15.48969,3 -1553.253,-1.0913,3 -1533.543,-6.647263,3 -1512.571,-5.314623,3 -1489.597,-12.72277,3 -1465.037,-10.23271,3 -1440.626,-12.70623,3 -1416.577,-9.706091,3 -1395.107,-6.353202,3 -1377.024,-1.41299,3 -1362.729,3.233414,3 -1354.829,16.14577,3 -1363.078,49.1428,3 -1386.616,61.25877,3 -1414.32,64.14809,3 -1440.303,59.41497,3 -1460.953,50.86452,3 -1479.574,55.51258,3 -1498.37,53.43364,3 -1516.938,56.92963,3 -1538.501,65.29128,3 -1562.402,67.20255,3 -1585.376,65.22421,3 -1607.168,66.15616,3 -1622.363,45.26455,3 -1626.448,29.70588,3 -1619.663,8.417274,3 -1605.892,5.471342,3 -1590.294,1.554001,3 -1574.104,2.731438,3 -1564.27,21.70022,3 -1562.819,29.79327,3 -1568.34,44.64818,3 -1577.866,43.57754,3 -1587.66,46.50829,3 -1597.844,45.86784,3 -1605.354,38.47025,3 -1610.205,37.56776,3 -1614.96,38.60074,3 -1622.027,45.92914,3 -1631.029,45.93453,3 -1640.622,48.91043,3 -1652.001,53.17495,3 -1664.657,54.63203,3 -1677.662,55.84564,3 -1692.656,63.26057,3 -1711.21,70.51211,3 -1732.478,75.57997,3 -1753.544,72.63683,3 -1769.828,60.5629,3 -1783.451,64.80178,3 -1796.429,59.79764,3 -1807.943,60.86138,3 -1820.33,64.59172,3 -1828.176,44.81462,3 -1821.163,8.214087,3 -1804.249,6.292377,3 -1787.871,9.134424,3 -1770.714,2.376011,3 -1754.109,10.06567,3 -1738.806,6.212786,3 -1721.286,1.067402,3 -1704.721,8.612881,3 -1690.95,10.14219,3 -1679.624,16.43083,3 -1669.144,12.42631,3 -1658.987,16.84797,3 -1647.85,8.391995,3 -1632.507,1.645216,3 -1616.008,3.606684,3 -1600.128,2.947272,3 -1589.487,20.32802,3 -1587.647,31.78459,3 -1590.159,34.78584,3 -1594.271,37.37839,3 -1600.692,42.96344,3 -1610.513,49.539,3 -1619.219,40.11499,3 -1623.559,35.45469,3 -1622.551,22.18125,3 -1616.573,18.38556,3 -1609.412,17.73681,3 -1601.727,16.13419,3 -1594.458,18.62502,3 -1590.616,27.14091,3 -1592.551,37.74634,3 -1599.214,43.24936,3 -1607.383,43.47301,3 -1616.519,47.3689,3 -1620.966,28.29967,3 -1614.678,11.12828,3 -1600.491,1.117563,3 -1577.759,-15.98362,3 -1550.498,-12.94688,3 -1526.638,-6.817096,3 -1505.168,-6.72456,3 -1484.263,-5.809709,3 -1462.727,-8.948511,3 -1443.058,-1.342418,3 -1426.667,-0.6651244,3 -1410.316,-1.713572,3 -1393.038,-3.54139,3 -1376.876,0.7599344,3 -1361.493,-1.957383,3 -1339.513,-15.69704,3 -1313.126,-13.22394,3 -1287.062,-14.71945,3 -1250.061,-13.29444,3 -1211.717,-13.18758,3 -1184.632,-12.68648,3 -1156.754,-13.87198,3 -1125.974,-13.35509,3 -1094.321,-12.72246,3 -1054.539,-11.65611,3 -1026.366,1.78571,3 -1031.707,34.37691,3 -1059.625,52.05185,3 -1095.194,54.60882,3 -1132.853,61.3746,3 -1177.447,76.69508,3 -1222.979,69.77629,3 -1261.898,65.92332,3 -1296.198,62.50776,3 -1331.935,74.62606,3 -1370.172,74.38905,3 -1403.021,64.03122,3 -1430.133,61.57874,3 -1454.451,58.83109,3 -1481.079,71.86363,3 -1508.285,63.87067,3 -1533.275,68.35617,3 -1556.074,59.77805,3 -1575.649,60.55231,3 -1590.562,46.38965,3 -1598.476,38.60023,3 -1600.316,26.62489,3 -1595.412,16.02007,3 -1589.635,23.31708,3 -1594.485,51.32585,3 -1609.062,56.67459,3 -1626.676,63.39441,3 -1644.746,60.32769,3 -1660.559,57.70242,3 -1675.096,57.71563,3 -1688.518,55.43426,3 -1701.389,57.32327,3 -1710.565,43.53574,3 -1713.427,35.47276,3 -1715.402,40.61037,3 -1719.432,43.12147,3 -1724.444,44.58424,3 -1731.376,50.66751,3 -1740.593,53.71496,3 -1749.258,49.65441,3 -1754.552,42.17929,3 -1757.723,42.34054,3 -1768.121,69.52338,3 -1794.468,103.9193,3 -1825.61,91.68179,3 -1855.813,105.6374,3 -1881.836,79.81264,3 -1897.179,67.01525,3 -1905.496,53.63717,3 -1906.692,39.33886,3 -1889.011,-19.16266,3 -1849.122,-24.79765,3 -1807.889,-24.43617,3 -1779.689,-0.7561536,3 -1284.092,17.17696,3 -1284.102,58.07148,3 -1292.093,58.99236,3 -1304.082,80.69597,3 -1321.862,92.27543,3 -1340.809,90.74892,3 -1359.844,96.99959,3 -1378.966,95.45564,3 -1393.216,73.59466,3 -1402.928,72.61659,3 -1413.785,82.11748,3 -1426.51,85.63467,3 -1440.927,94.76996,3 -1455.95,92.36811,3 -1470.416,94.86768,3 -1480.725,70.45586,3 -1486.985,72.58999,3 -1494.017,76.40392,3 -1505.187,99.43295,3 -1520.278,103.0791,3 -1537.327,115.3624,3 -1552.584,95.87924,3 -1562.453,84.82603,3 -1568.948,76.54655,3 -1573.946,76.64169,3 -1578.063,71.93213,3 -1579.726,61.67735,3 -1579.57,60.54532,3 -1578.23,54.0312,3 -1574.601,45.59658,3 -1570.894,52.8693,3 -1567.725,48.39549,3 -1563.177,43.51645,3 -1555.069,25.0616,3 -1541.767,9.581061,3 -1527.692,18.39748,3 -1515.007,16.44184,3 -1501.92,14.32027,3 -1490.76,26.46716,3 -1483.728,37.81801,3 -1478.436,35.96482,3 -1475.345,50.22443,3 -1478.28,71.72651,3 -1485.41,76.1095,3 -1492.481,72.78746,3 -1498.937,73.78825,3 -1505.128,72.46352,3 -1511.525,76.31317,3 -1517.471,70.96622,3 -1522.88,74.19914,3 -1528.641,74.2482,3 -1535.39,81.57578,3 -1541.278,70.22089,3 -1544.848,68.2123,3 -1547.264,63.6499,3 -1547.371,54.11656,3 -1545.171,49.12331,3 -1542.52,50.89368,3 -1539.84,48.48135,3 -1537.816,54.52997,3 -1536.886,54.98994,3 -1537.346,63.06376,3 -1541.503,78.29755,3 -1548.662,82.82697,3 -1550.482,45.99143,3 -1544.809,35.92283,3 -1533.756,11.44688,3 -1518.009,5.243145,3 -1503.915,19.64205,3 -1492.609,20.55502,3 -1483.464,31.21258,3 -1479.277,49.16108,3 -1478.886,53.42761,3 -1479.62,55.8742,3 -1479.786,50.1337,3 -1479.678,54.25177,3 -1479.933,52.29718,3 -1480.578,56.65665,3 -1480.842,50.10637,3 -1480.598,53.63382,3 -1479.004,41.93355,3 -1476.324,46.8269,3 -1474.172,44.68207,3 -1472.274,48.00023,3 -1472.079,54.57672,3 -1472.597,52.24992,3 -1474.455,62.71901,3 -1477.018,56.80586,3 -1479.698,63.90294,3 -1482.955,60.77087,3 -1485.019,57.28467,3 -1487.298,62.45473,3 -1490.075,60.72274,3 -1492.403,60.23314,3 -1493.763,55.25238,3 -1493.205,48.80926,3 -1492.892,56.64178,3 -1493.557,54.70619,3 -1494.144,56.28391,3 -1494.682,54.51154,3 -1494.007,48.99399,3 -1492.853,51.47742,3 -1488.951,32.13356,3 -1476.187,-2.118674,3 -1457.887,-2.126604,3 -1443.636,19.47982,3 -1434.912,28.30535,3 -1428.173,29.93163,3 -1421.649,28.65341,3 -1414.167,23.54668,3 -1406.841,28.56202,3 -1399.642,23.36224,3 -1392.786,29.56185,3 -1386.477,25.6082,3 -1378.163,17.51092,3 -1369.077,20.2835,3 -1360.695,20.3895,3 -1353.369,25.12762,3 -1349.398,37.92805,3 -1351.149,56.04457,3 -1358.328,68.17207,3 -1369.312,78.50098,3 -1382.037,80.05802,3 -1392.443,67.88512,3 -1400.953,71.3244,3 -1408.376,63.24284,3 -1413.912,61.8568,3 -1417.932,55.47812,3 -1421.189,58.15731,3 -1423.85,52.57276,3 -1425.894,55.04035,3 -1428.72,57.47088,3 -1430.657,50.33347,3 -1427.302,27.01298,3 -1417.443,12.22586,3 -1403.036,-0.1684303,3 -1384.237,-11.87013,3 -1363.287,-11.63743,3 -1342.004,-13.53146,3 -1318.618,-16.01462,3 -1282.605,-14.39375,3 -1220.908,-12.12208,3 -1141.722,-10.68284,3 -1074.528,-10.48296,3 -1022.054,-9.141874,3 -960.7875,-8.731186,3 -1216.514,-10.74907,3 -1109.274,-9.523954,3 -1005.743,-8.101731,3 -906.0809,-7.618393,3 -784.7748,-6.123598,3 -636.8536,-6.884468,3 -741.9532,-5.764419,3 -836.1458,-0.8582449,3 -600,-4.675195,3 -952.2463,0.009875298,3 -664.0984,-1.178708,3 -600,-1.123972,3 -600,-0.2031865,3 -600,-0.6548967,3 -600,-0.000296116,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,2.38E-07,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -644.4445,0.2542183,3 -644.4445,3.043099,3 -644.4944,3.76886,3 -862.1945,7.244804,3 -644.4445,2.008217,3 -644.4445,1.282092,3 -644.4445,1.102336,3 -644.4445,1.300048,3 -644.4445,1.259131,3 -644.4445,1.073095,3 -645.6724,3.006216,3 -618.264,-0.3244839,3 -647.7556,5.489882,3 -701.8685,2.742796,3 -722.4244,2.271123,3 -743.2361,2.935951,3 -762.5648,2.234797,3 -772.9451,2.039693,3 -780.2573,1.936579,3 -786.3934,1.940598,3 -781.9448,0.7246585,3 -771.7178,1.247691,3 -769.2634,1.590314,3 -768.7009,1.456245,3 -766.1954,1.364901,3 -764.2012,1.504721,3 -766.3488,1.831629,3 -768.0362,1.460694,3 -768.0362,1.645372,3 -773.3542,2.075679,3 -774.5814,1.194392,3 -764.559,0.7873244,3 -745.3326,0.1385179,3 -715.4191,-0.332602,3 -677.2729,-0.594053,3 -635.803,-0.5641029,3 -981.9337,-3.01793,3 -839.9738,-0.6091862,3 -727.9713,-1.361682,3 -620.287,-0.3443129,3 -600,-0.198132,3 -600,-0.2130547,3 -644.4445,1.156704,3 -644.4445,2.928335,3 -840.5137,7.855536,3 -645.6799,4.915875,3 -718.7428,7.940886,3 -919.598,20.71529,3 -1104.653,9.702165,3 -1177.315,7.127035,3 -1343.756,30.38393,3 -1513.062,9.906143,3 -1007.81,36.38819,3 -1161.267,39.11203,3 -1278.037,27.3871,3 -1383.305,40.41537,3 -1511.207,46.64371,3 -1596.608,19.454,3 -1075.369,38.91386,3 -1144.645,51.12838,3 -1236.03,71.91323,3 -1345.194,84.24624,3 -1462.489,97.86935,3 -1569.923,84.68086,3 -1640.951,52.99866,3 -1686.982,50.89439,3 -1708.258,14.60182,3 -1146.06,-3.260405,3 -1143.091,26.43259,3 -1164.452,55.55766,3 -1202.272,69.78938,3 -1248.732,83.18002,3 -1301.019,92.7276,3 -1354.342,94.76001,3 -1401.919,84.77892,3 -1438.704,69.75992,3 -1467.953,66.90834,3 -1497.591,74.95674,3 -1527.323,71.09368,3 -1554.516,70.7477,3 -1580.204,69.72466,3 -1607.732,80.51578,3 -1633.071,65.80466,3 -1652.807,64.51868,3 -1671.334,64.05013,3 -1689.244,64.65747,3 -1706.105,62.52456,3 -1720.534,57.92768,3 -1723.772,23.39667,3 -1706.911,-12.77224,3 -1685.898,7.341925,3 -1671.979,9.75246,3 -1662.279,21.29147,3 -1658.504,29.84188,3 -1653.587,17.03524,3 -1638.794,-4.186825,3 -1617.648,-4.962307,3 -1597.884,-0.8135309,3 -1580.257,0.750226,3 -1562.563,-1.659951,3 -1548.537,11.91162,3 -1540.033,15.42424,3 -1535.115,23.01572,3 -1531.448,19.15309,3 -1516.118,-12.86069,3 -1492.284,-7.591835,3 -1467.55,-15.70515,3 -1435.373,-17.46522,3 -1392.904,-16.13951,3 -1347.977,-15.4994,3 -1312.535,-15.2666,3 -1292.543,4.540256,3 -1286.511,16.9544,3 -1287.236,22.45613,3 -1293.9,33.18174,3 -1303.345,30.53206,3 -1313.502,35.92642,3 -1331.949,54.6626,3 -1359.692,64.28005,3 -1396.867,85.87479,3 -1437.925,80.98814,3 -1474.281,77.60077,3 -1509.642,83.28379,3 -1543.23,76.9175,3 -1570.127,65.98427,3 -1588.654,52.43436,3 -1600.84,46.78295,3 -1606.805,32.59529,3 -1605.65,23.18912,3 -1600.504,19.00929,3 -1594.781,20.86993,3 -1590.656,23.9784,3 -1587.486,23.77216,3 -1582.017,16.08064,3 -1572.358,9.474892,3 -1555.805,-6.293793,3 -1535.33,-3.614192,3 -1510.986,-17.70457,3 -1482.517,-15.38637,3 -1448.754,-17.3886,3 -1398.587,-15.64723,3 -1329.799,-13.74466,3 -1273.492,-14.25001,3 -1241.248,-13.40315,3 -1205.269,-12.6376,3 -1165.85,-12.21276,3 -1135.151,-12.03583,3 -1120.372,9.679996,3 -1120.828,20.11432,3 -1124.12,16.3987,3 -1126.471,18.06844,3 -1130.287,20.00859,3 -1140.336,33.27053,3 -1156.029,34.36275,3 -1172.272,35.92491,3 -1186.231,29.97521,3 -1199.088,34.3232,3 -1218.381,47.54738,3 -1244.808,54.75484,3 -1274.137,58.20295,3 -1304.004,59.67457,3 -1330.377,51.92756,3 -1355.218,58.4916,3 -1371.65,30.14645,3 -1375.962,24.95364,3 -1378.676,25.82015,3 -1379.214,18.80646,3 -1374.31,10.07271,3 -1365.201,6.415627,3 -1355.783,8.765409,3 -1346.029,5.078839,3 -1331.237,-5.104489,3 -1306.892,-15.03027,3 -1262.704,-13.15916,3 -1218.341,-13.36216,3 -1187.789,-12.82549,3 -1158.756,-12.40262,3 -1140.404,3.783212,3 -1146.194,39.93061,3 -1168.859,45.34202,3 -1196.469,54.62985,3 -1230.943,66.16975,3 -1267.379,64.01351,3 -1307.698,81.99072,3 -1350.247,75.75098,3 -1391.923,86.11143,3 -1438.113,95.74863,3 -1481.187,83.65627,3 -1522.688,98.04447,3 -1564.162,89.97185,3 -1600.074,86.14787,3 -1628.449,69.52667,3 -1645.015,49.09846,3 -1644.383,11.60987,3 -1636.161,22.72835,3 -1636.631,41.04108,3 -1644.504,48.4262,3 -1655.387,52.34411,3 -1667.573,54.19073,3 -1678.724,50.02793,3 -1685.71,40.58485,3 -1688.384,35.37016,3 -1693.812,50.70958,3 -1703.243,50.27459,3 -1708.913,38.13729,3 -1712.647,43.88169,3 -1719.594,50.16351,3 -1728.071,50.19448,3 -1728.891,23.06607,3 -1720.413,16.42023,3 -1711.479,20.75814,3 -1701.872,13.39018,3 -1689.687,10.86072,3 -1670.811,-9.679937,3 -1650.241,3.8373,3 -1635.127,7.068507,3 -1619.717,2.065735,3 -1602.99,1.803795,3 -1589.608,12.44946,3 -1580.634,15.81511,3 -1574.991,22.96172,3 -1575.542,36.00331,3 -1579.236,33.46876,3 -1581.762,32.42493,3 -1582.434,27.48787,3 -1578.618,17.52039,3 -1570.772,13.83211,3 -1562.375,15.1992,3 -1551.869,6.441697,3 -1534.793,-5.906759,3 -1512.289,-10.30744,3 -1486.695,-15.03363,3 -1458.857,-16.87653,3 -1432.135,-12.41042,3 -1407.629,-11.31777,3 -1384.171,-10.03571,3 -1369.003,10.59928,3 -1365.08,20.52546,3 -1370.091,36.15165,3 -1380.638,36.95204,3 -1393.63,44.27267,3 -1412.734,56.37016,3 -1440.572,72.8304,3 -1467.684,57.35134,3 -1491.37,65.70872,3 -1518.066,69.83893,3 -1541.604,58.79247,3 -1561.153,59.73059,3 -1579.048,55.58046,3 -1595.762,57.87779,3 -1611.924,55.62059,3 -1625.601,51.2132,3 -1629.645,23.90257,3 -1619.246,2.099785,3 -1602.936,3.149794,3 -1587.781,5.188667,3 -1575.542,12.07873,3 -1570.329,27.7652,3 -1573.903,40.86924,3 -1581.722,42.21673,3 -1589.689,42.11393,3 -1595.95,37.23134,3 -1600.491,36.9001,3 -1604.898,37.1901,3 -1610.715,42.10384,3 -1618.87,45.72244,3 -1628.409,47.67087,3 -1640.151,54.35364,3 -1653.022,52.86154,3 -1665.678,55.06348,3 -1679.879,59.78596,3 -1695.907,63.27319,3 -1713.198,66.3249,3 -1731.269,68.31712,3 -1748.775,66.57999,3 -1763.997,62.08349,3 -1779.34,69.02579,3 -1793.984,61.35672,3 -1805.202,57.85924,3 -1812.82,48.92445,3 -1819.578,55.46923,3 -1825.906,48.01827,3 -1821.056,13.10841,3 -1805.565,6.840103,3 -1788.691,6.806072,3 -1772.488,8.286536,3 -1756.487,6.550629,3 -1737.798,-2.249373,3 -1717.807,0.735312,3 -1700.731,6.919925,3 -1685.226,5.433849,3 -1672.436,15.57636,3 -1664.362,21.22834,3 -1658.961,24.37656,3 -1650.268,9.386177,3 -1634.71,0.04979086,3 -1614.544,-6.336586,3 -1598.381,12.57801,3 -1590.025,18.29753,3 -1584.288,20.81376,3 -1584.234,36.87918,3 -1596.608,62.62403,3 -1613.859,54.64594,3 -1622.457,34.95087,3 -1624.271,32.25559,3 -1624.661,30.22398,3 -1624.849,31.59747,3 -1621.624,18.55824,3 -1611.064,6.372733,3 -1598.986,12.73059,3 -1591.785,22.058,3 -1592.013,37.18653,3 -1598.704,43.85127,3 -1607.947,46.47419,3 -1618.319,48.64143,3 -1621.906,24.24795,3 -1615.068,13.35699,3 -1603.111,6.432739,3 -1588.722,4.500189,3 -1572.573,-0.115675,3 -1553.629,-4.783992,3 -1532.751,-6.315992,3 -1514.761,3.077488,3 -1500.399,3.732917,3 -1482.651,-7.154562,3 -1463.519,-1.135713,3 -1440.935,-16.81416,3 -1414.158,-12.81345,3 -1390.943,-7.845296,3 -1368.922,-10.04424,3 -1346.889,-8.254794,3 -1323.471,-13.71456,3 -1296.762,-14.93286,3 -1265.673,-14.07961,3 -1236.546,-11.97013,3 -1207.23,-12.98112,3 -1174.139,-12.54039,3 -1146.973,-10.93499,3 -1124.362,-10.41155,3 -1093.918,-11.0197,3 -1057.509,-10.56761,3 -1037.759,6.854196,3 -1046.344,37.0987,3 -1073.335,48.63685,3 -1107.407,56.2469,3 -1148.129,68.77713,3 -1192.304,70.15498,3 -1231.884,63.05749,3 -1264.786,57.78709,3 -1296.44,63.90317,3 -1332.419,73.914,3 -1371.166,76.68737,3 -1406.42,69.01247,3 -1434.862,60.98241,3 -1458.468,57.80101,3 -1482.987,66.75755,3 -1509.669,67.63638,3 -1535.465,67.33713,3 -1560.091,67.14167,3 -1583.253,65.62291,3 -1599.443,46.44219,3 -1606.684,37.13651,3 -1604.884,16.46138,3 -1593.343,4.168659,3 -1584.033,23.15694,3 -1588.211,48.71681,3 -1600.585,51.11957,3 -1617.836,66.74638,3 -1638.794,65.8931,3 -1658.92,66.52989,3 -1676.91,60.87619,3 -1691.756,57.56428,3 -1704.331,54.48838,3 -1710.861,37.12782,3 -1711.546,34.04327,3 -1710.229,29.95877,3 -1712.661,47.48108,3 -1721.461,53.3045,3 -1730.906,50.78699,3 -1740.176,53.73991,3 -1751.045,57.7492,3 -1757.951,40.23434,3 -1759.778,39.63506,3 -1772.192,80.07209,3 -1797.208,88.74728,3 -1826.631,100.872,3 -1858.271,102.1546,3 -1885.397,88.15533,3 -1904.448,74.06339,3 -1916.432,62.34672,3 -1919.401,39.03856,3 -1902.46,-15.46535,3 -1863.511,-25.07789,3 -1823.273,-21.13098,3 -1791.996,-14.05958,3 -1770.969,13.06777,3 -1286.498,48.0114,3 -1294.058,67.24074,3 -1306.597,75.67068,3 -1322.628,88.41093,3 -1342.258,98.59779,3 -1363.062,99.24053,3 -1378.535,73.31172,3 -1388.825,73.33134,3 -1401.598,89.55661,3 -1416.387,87.50754,3 -1432.163,98.61768,3 -1449.387,99.54861,3 -1465.027,93.16014,3 -1475.385,71.32512,3 -1479.141,55.54146,3 -1483.825,77.69683,3 -1492.922,83.2123,3 -1504.218,93.1139,3 -1517.188,96.03044,3 -1530.509,98.30925,3 -1543.136,94.77704,3 -1552.281,79.19598,3 -1557.964,74.84485,3 -1563.461,79.22526,3 -1569.339,78.43729,3 -1574.591,76.46247,3 -1577.222,62.67551,3 -1577.242,60.19896,3 -1575.687,52.56088,3 -1572.498,49.43146,3 -1569.329,52.1115,3 -1564.947,41.14471,3 -1554.462,12.68271,3 -1539.967,14.31148,3 -1525.981,14.02893,3 -1511.818,11.48827,3 -1497.929,13.95845,3 -1487.532,30.92048,3 -1481.38,38.22163,3 -1478.329,48.67535,3 -1478.162,55.10718,3 -1479.678,58.7858,3 -1483.914,71.81812,3 -1490.819,75.78394,3 -1498.35,77.02534,3 -1505.099,72.51969,3 -1511.202,74.43957,3 -1517.911,77.50984,3 -1525.814,83.25037,3 -1532.593,72.12448,3 -1537.16,70.83592,3 -1542.236,76.25439,3 -1544.985,57.17952,3 -1544.32,55.29839,3 -1544.476,62.22943,3 -1544.496,54.4649,3 -1542.745,51.09521,3 -1539.38,44.02723,3 -1535.742,48.7935,3 -1534.999,61.51359,3 -1537.258,67.46387,3 -1540.965,71.03705,3 -1547.939,88.8294,3 -1549.738,39.71848,3 -1538.647,8.12237,3 -1524.67,20.05622,3 -1512.2,15.72904,3 -1500.873,25.39976,3 -1490.78,21.78333,3 -1482.358,34.10342,3 -1478.485,47.99138,3 -1477.977,53.7555,3 -1477.801,49.90863,3 -1479.15,62.92201,3 -1481.243,54.62078,3 -1481.116,49.8967,3 -1480.324,50.58609,3 -1479.63,50.35303,3 -1477.321,40.75677,3 -1473.565,41.27589,3 -1470.426,43.86224,3 -1468.401,47.451,3 -1466.954,46.9868,3 -1467.658,60.07456,3 -1470.602,60.51458,3 -1475.668,73.382,3 -1481.801,67.88359,3 -1484.911,56.28338,3 -1485.674,54.24988,3 -1486.251,55.29283,3 -1486.691,53.52103,3 -1486.77,53.17738,3 -1486.721,52.76431,3 -1487.024,55.30242,3 -1487.669,54.89172,3 -1489.019,59.68992,3 -1490.731,57.32771,3 -1492.951,63.0985,3 -1495.279,58.38214,3 -1494.584,45.10869,3 -1487.405,18.9328,3 -1470.866,-10.28922,3 -1452.928,8.639071,3 -1440.017,15.75091,3 -1429.552,21.4329,3 -1422.607,34.86482,3 -1417.512,31.21866,3 -1412.484,34.53926,3 -1407.31,29.69863,3 -1401.344,29.30284,3 -1395.877,31.73983,3 -1390.937,31.57141,3 -1385.724,29.53498,3 -1378.741,20.95574,3 -1371.111,25.03376,3 -1363.707,21.31329,3 -1355.785,21.27985,3 -1349.271,28.11312,3 -1347.491,46.42329,3 -1354.044,73.73386,3 -1364.627,69.82935,3 -1374.183,70.02986,3 -1382.281,63.41209,3 -1390.106,70.01546,3 -1398.41,67.56463,3 -1404.523,59.0325,3 -1409.433,61.78816,3 -1413.688,56.11639,3 -1417.443,59.66835,3 -1421.248,57.04577,3 -1423.116,49.10121,3 -1423.185,46.9263,3 -1420.573,33.6044,3 -1411.956,11.98207,3 -1397.891,1.452831,3 -1383.142,6.65378,3 -1367.718,-3.068421,3 -1348.968,-9.861969,3 -1325.562,-16.11518,3 -1284.092,-14.13637,3 -1214.697,-11.85796,3 -1141.781,-11.37294,3 -1079.028,-10.51758,3 -1008.215,-8.903414,3 -930.7995,-8.72839,3 -857.0523,-8.130159,3 -789.291,-8.076338,3 -726.7427,-8.857965,3 -898.0064,-7.569747,3 -769.9961,-6.515765,3 -649.1603,-7.147186,3 -784.9226,-4.621058,3 -892.3317,-0.6631382,3 -608.6652,-4.717086,3 -600,-6.420379,3 -606.6129,-1.587289,3 -600,-0.7637906,3 -600,-0.8728795,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,-2.38E-07,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,-2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,0,3 -600,2.38E-07,3 -600,0,3 -600,0,3 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -644.4445,0.1401868,4 -644.4445,4.115141,4 -723.5632,6.148651,4 -878.7474,0.996314,4 -644.4445,5.992946,4 -614.2244,0.8715067,4 -1054.623,0.2505918,4 -1032.132,1.002764,4 -644.4445,1.849404,4 -644.4445,1.160477,4 -644.4445,1.181648,4 -646.017,3.313942,4 -655.8477,2.47095,4 -673.5912,1.926634,4 -697.6755,3.281785,4 -729.89,2.964346,4 -753.4118,2.586441,4 -769.7236,2.314295,4 -781.3311,2.144838,4 -788.3876,1.845007,4 -788.5922,1.371453,4 -785.2173,1.424252,4 -785.7797,1.820931,4 -787.4161,1.552712,4 -785.6775,1.431036,4 -786.0355,1.792017,4 -787.007,1.504555,4 -785.3195,1.483458,4 -784.6548,1.617746,4 -783.939,1.474823,4 -778.5699,1.072223,4 -772.178,1.335513,4 -761.5421,0.5722067,4 -687.8577,-4.410039,4 -1043.288,-1.19836,4 -644.4445,2.357286,4 -1002.265,-0.5849216,4 -866.3327,-2.573789,4 -732.1096,-0.3810852,4 -661.4896,-0.2707293,4 -600,-0.2227266,4 -644.5211,1.784207,4 -615.0692,-0.02452826,4 -600,-0.1297612,4 -644.4445,0.6420181,4 -666.7973,4.922177,4 -644.4445,8.587686,4 -693.5847,6.82707,4 -836.9651,12.78135,4 -995.8392,12.11045,4 -1190.252,24.46093,4 -1341.456,7.883049,4 -1453.439,21.57428,4 -1009.962,38.10797,4 -1173.415,42.39235,4 -1323.306,42.99743,4 -1399.727,9.089857,4 -937.9701,32.31821,4 -1005.795,44.4572,4 -1088.015,53.16226,4 -1172.164,54.589,4 -1265.583,73.96272,4 -1376.655,88.71164,4 -1496.45,101.4458,4 -1616.172,105.6161,4 -1668.748,5.478724,4 -1119.606,4.928539,4 -1124.671,35.79109,4 -1140.175,30.06963,4 -1160.328,48.58438,4 -1189.106,53.33678,4 -1224.844,69.88008,4 -1267.755,76.89536,4 -1310.533,75.63843,4 -1352.249,80.32765,4 -1392.649,77.89688,4 -1429.045,74.28435,4 -1463.412,76.94868,4 -1497.873,79.46665,4 -1531.421,78.96201,4 -1561.273,72.11664,4 -1587.056,69.5541,4 -1609.479,64.13884,4 -1630.585,67.9769,4 -1650.429,62.38124,4 -1668.137,63.00897,4 -1684.42,59.49305,4 -1702.746,72.43027,4 -1718.317,51.68219,4 -1722.2,31.7786,4 -1710.807,-2.869109,4 -1690.453,-1.062667,4 -1673.296,7.073107,4 -1662.924,21.68794,4 -1658.853,28.46225,4 -1655.051,22.32484,4 -1643,-0.4019394,4 -1623.586,-3.330098,4 -1604.414,-0.449111,4 -1587.123,1.748246,4 -1569.496,-2.081304,4 -1552.944,4.46729,4 -1542.894,18.06239,4 -1538.031,20.74931,4 -1530.547,9.303829,4 -1514.237,-7.018807,4 -1492.526,-7.514885,4 -1469.149,-12.08818,4 -1442.722,-15.80163,4 -1404.525,-18.5696,4 -1361.667,-17.84917,4 -1327.529,-17.22158,4 -1306.449,4.262201,4 -1300.712,18.62459,4 -1305.858,33.81105,4 -1310.184,16.66183,4 -1310.09,21.90794,4 -1317.331,37.01147,4 -1331.747,42.52515,4 -1353.015,57.90654,4 -1383.016,70.18417,4 -1420.392,83.79029,4 -1463.21,92.30715,4 -1502.401,78.82739,4 -1533.557,72.45618,4 -1561.099,71.36134,4 -1584.785,63.23337,4 -1600.343,46.89187,4 -1607.934,37.95928,4 -1609.116,25.84165,4 -1606.496,25.15568,4 -1602.882,22.27899,4 -1597.401,18.59029,4 -1590.777,18.05532,4 -1581.158,8.168066,4 -1565.438,-2.385445,4 -1544.224,-9.294456,4 -1521.841,-6.390518,4 -1499.485,-9.735824,4 -1475.06,-12.31793,4 -1438.369,-16.93306,4 -1388.027,-15.79407,4 -1334.837,-14.71431,4 -1282.574,-13.81453,4 -1232.73,-12.99281,4 -1186.607,-12.35547,4 -1153.933,-9.757157,4 -1138.281,3.688477,4 -1130.166,6.484842,4 -1124.469,9.161757,4 -1119.579,8.190273,4 -1116.717,13.7386,4 -1121.178,25.33872,4 -1131.012,26.74716,4 -1139.974,23.89797,4 -1153.758,39.14996,4 -1173.145,38.69012,4 -1197.14,52.6565,4 -1222.573,44.61408,4 -1247.831,55.10344,4 -1274.231,50.24755,4 -1302.956,64.64877,4 -1334.958,62.68685,4 -1361.681,53.49527,4 -1382.828,49.63818,4 -1393.616,25.17934,4 -1392.595,15.85793,4 -1388.47,16.01408,4 -1382.331,9.760792,4 -1375.264,12.98514,4 -1368.573,10.51227,4 -1357.852,1.127345,4 -1330.887,-15.09141,4 -1287.693,-14.09798,4 -1235.995,-12.79959,4 -1189.24,-12.6493,4 -1159.75,-9.993802,4 -1143.158,2.208033,4 -1140.753,21.87768,4 -1152.361,35.92246,4 -1169.356,35.89918,4 -1193.446,55.35715,4 -1227.665,64.36838,4 -1263.591,64.05273,4 -1304.172,82.13965,4 -1350.765,86.74195,4 -1399.89,97.1329,4 -1448.015,91.67886,4 -1490.363,87.14861,4 -1527.78,82.59544,4 -1565.411,93.79819,4 -1601.888,84.35611,4 -1629.712,69.70103,4 -1643.765,40.32787,4 -1644.598,25.34709,4 -1642.677,30.8411,4 -1647.957,50.22522,4 -1657.926,47.7007,4 -1664.052,37.76743,4 -1668.701,43.12788,4 -1677.555,53.11346,4 -1688.478,51.41099,4 -1698.5,51.11005,4 -1706.414,44.9026,4 -1708.993,32.6828,4 -1711.102,43.46721,4 -1718.371,51.58891,4 -1728.098,53.19771,4 -1735.42,43.84155,4 -1735.339,26.82102,4 -1726.916,13.36045,4 -1716.691,19.60794,4 -1707.085,14.90211,4 -1695.128,10.50889,4 -1682.271,10.91309,4 -1663.878,-8.54956,4 -1641.629,-3.117419,4 -1624.07,5.537962,4 -1609.197,4.835527,4 -1592.752,-0.4371243,4 -1577.893,9.274105,4 -1570.101,22.16969,4 -1571.847,40.37538,4 -1576.751,32.78808,4 -1579.035,32.08871,4 -1581.749,34.41856,4 -1583.133,27.87005,4 -1576.012,6.219936,4 -1561.421,2.702191,4 -1547.059,6.234878,4 -1534.363,7.427535,4 -1520.672,2.441157,4 -1500.385,-12.44278,4 -1474.039,-15.19112,4 -1448.391,-10.99723,4 -1411.539,-16.18276,4 -1375.237,-10.13539,4 -1357.798,3.94146,4 -1352.424,22.40654,4 -1358.053,35.1076,4 -1371.085,44.18404,4 -1390.486,54.94989,4 -1412.506,53.94309,4 -1436.112,62.30517,4 -1459.811,56.89755,4 -1483.336,64.70206,4 -1510.018,69.77424,4 -1535.801,65.16431,4 -1559.043,64.80313,4 -1580.728,62.89471,4 -1598.556,54.45824,4 -1613.254,54.38581,4 -1626.582,51.40335,4 -1634.75,38.01902,4 -1625.87,-5.708029,4 -1605.435,-1.783062,4 -1588.211,3.508634,4 -1575.972,13.76913,4 -1574.601,38.87314,4 -1576.764,25.41134,4 -1576.509,31.0111,4 -1580.378,39.14088,4 -1587.109,40.92192,4 -1594.552,42.17134,4 -1602.21,42.3647,4 -1609.64,42.14173,4 -1617.876,45.85305,4 -1627.146,46.51075,4 -1637.773,51.51218,4 -1651.907,59.8804,4 -1668.016,60.05737,4 -1682.956,57.66072,4 -1698.594,64.39252,4 -1714.26,59.62116,4 -1729.025,63.08392,4 -1743.723,61.17331,4 -1759.321,68.29936,4 -1774.275,60.68742,4 -1787.293,62.94482,4 -1799.157,57.8984,4 -1810.375,61.97612,4 -1821.647,59.47066,4 -1829.144,48.76117,4 -1827.075,23.35892,4 -1814.029,6.402053,4 -1794.32,-2.592016,4 -1771.735,-4.909734,4 -1752.711,9.03825,4 -1737.462,7.341007,4 -1721.273,4.683862,4 -1704.694,4.982325,4 -1688.128,3.812349,4 -1674.545,14.56831,4 -1666.793,23.51281,4 -1662.064,24.63626,4 -1654.984,14.94999,4 -1635.731,-15.84564,4 -1610.997,-4.315684,4 -1594.74,9.832749,4 -1588.036,26.32848,4 -1590.885,41.41418,4 -1599,44.31393,4 -1604.347,32.80503,4 -1609.748,45.03335,4 -1620.321,50.97161,4 -1629.86,42.54122,4 -1630.612,21.65488,4 -1626.286,25.14294,4 -1622.995,24.88023,4 -1619.287,23.46855,4 -1613.268,16.73643,4 -1607.706,24.57117,4 -1610.003,43.01642,4 -1616.519,39.12624,4 -1621.208,37.39355,4 -1624.634,35.22969,4 -1627.952,37.3392,4 -1624.594,12.60667,4 -1610.554,0.67381,4 -1592.725,-0.8326931,4 -1573.647,-3.764307,4 -1556.383,4.200647,4 -1540.61,-0.05308342,4 -1524.676,2.95549,4 -1506.149,-7.869933,4 -1484.451,-6.838203,4 -1463.063,-7.529763,4 -1441.418,-8.017014,4 -1419.842,-7.811407,4 -1398.13,-8.783758,4 -1377.628,-5.129324,4 -1358.174,-6.480177,4 -1330.162,-16.99247,4 -1294.518,-16.31282,4 -1264.088,-13.97139,4 -1238.279,-14.27002,4 -1205.672,-13.58043,4 -1175.577,-8.778869,4 -1153.073,-12.24656,4 -1128.594,-11.99461,4 -1095.57,-10.9451,4 -1059.322,-10.66192,4 -1040.862,6.466439,4 -1046.922,32.05039,4 -1070.836,46.81862,4 -1105.593,59.44982,4 -1144.421,60.56117,4 -1185.277,69.68872,4 -1225.22,63.52172,4 -1258.217,56.72657,4 -1292.812,72.29202,4 -1331.452,72.35333,4 -1366.88,68.45086,4 -1393.737,51.85317,4 -1417.343,62.23331,4 -1449.023,79.29785,4 -1486.588,84.81449,4 -1520.337,72.50204,4 -1545.353,61.22117,4 -1565.129,58.47639,4 -1583.576,59.16581,4 -1597.441,45.13127,4 -1602.506,30.88554,4 -1600.343,21.15592,4 -1593.612,15.33718,4 -1586.666,19.96346,4 -1587.996,42.56586,4 -1600.719,58.4817,4 -1618.574,61.39739,4 -1637.37,63.87596,4 -1655.736,62.19775,4 -1672.167,59.32374,4 -1687.886,61.68731,4 -1702.047,55.59766,4 -1710.914,44.22459,4 -1715.953,42.70472,4 -1719.231,38.34271,4 -1721.891,40.7861,4 -1725.048,40.4108,4 -1728.743,43.06327,4 -1735.541,52.16247,4 -1744.341,51.14399,4 -1753.557,54.70576,4 -1763.137,53.5337,4 -1773.912,60.3172,4 -1790.531,76.9442,4 -1814.647,91.22339,4 -1844.93,104.5918,4 -1876.086,99.57632,4 -1900.511,82.78519,4 -1919.052,79.66685,4 -1921.161,18.51604,4 -1896.575,-24.33028,4 -1849.753,-24.22952,4 -1809.65,-2.914296,4 -1783.061,-16.90625,4 -1283.055,17.62789,4 -1281.148,47.45848,4 -1288.122,63.8209,4 -1299.731,73.06547,4 -1314.197,81.21303,4 -1332.148,94.84081,4 -1352.77,99.70914,4 -1374.041,103.1989,4 -1391.799,84.65783,4 -1404.758,79.80271,4 -1417.834,88.10941,4 -1433.956,100.3611,4 -1452.571,106.4864,4 -1469.02,91.7476,4 -1477.869,64.48682,4 -1482.045,65.40362,4 -1486.32,65.86734,4 -1494.467,89.83578,4 -1506.898,93.77473,4 -1519.525,93.85491,4 -1531.702,93.87712,4 -1542.725,89.39608,4 -1552.242,86.8752,4 -1559.959,80.07738,4 -1564.449,67.961,4 -1567.041,68.89693,4 -1570.2,72.11388,4 -1572.977,67.08501,4 -1574.21,62.75511,4 -1574.21,59.41563,4 -1573.936,60.99732,4 -1572.4,51.27596,4 -1568.263,44.06831,4 -1559.519,21.27699,4 -1545.63,10.24199,4 -1530.617,12.39669,4 -1515.183,5.857883,4 -1498.36,2.09445,4 -1486.505,33.94199,4 -1482.349,47.08876,4 -1480.05,44.51606,4 -1479.463,57.02282,4 -1482.084,63.77707,4 -1487.796,76.23621,4 -1495.289,75.71186,4 -1501.538,70.15787,4 -1507.818,77.17599,4 -1514.703,75.15352,4 -1520.865,74.11327,4 -1527.096,76.84986,4 -1532.231,68.53654,4 -1536.417,71.96849,4 -1540.564,69.12055,4 -1543.713,66.52328,4 -1546.735,68.94624,4 -1547.489,52.78967,4 -1545.386,51.08469,4 -1542.256,45.96298,4 -1539.361,52.00807,4 -1537.405,51.35246,4 -1535.859,54.2338,4 -1536.554,65.10095,4 -1540.671,75.84949,4 -1547.195,81.08743,4 -1550.257,55.29021,4 -1545.806,34.30048,4 -1535.243,16.24277,4 -1523.33,24.33566,4 -1512.464,21.15258,4 -1502.918,30.91319,4 -1494.076,24.17211,4 -1485.987,34.19572,4 -1480.725,40.09128,4 -1478.27,50.29652,4 -1478.016,52.946,4 -1478.182,52.7861,4 -1478.378,53.15138,4 -1480.079,61.90357,4 -1482.192,55.92644,4 -1482.075,48.81292,4 -1479.982,43.98728,4 -1478.104,49.7599,4 -1476.93,47.92091,4 -1476.646,54.91663,4 -1477.908,57.17506,4 -1478.681,52.18999,4 -1479.786,59.31868,4 -1481.165,54.03209,4 -1482.339,58.32693,4 -1484.236,58.61423,4 -1487.024,64.06499,4 -1489.743,58.70241,4 -1491.484,58.62561,4 -1492.824,56.57703,4 -1493.381,54.10405,4 -1492.256,46.44337,4 -1490.926,52.65959,4 -1491.445,57.45026,4 -1492.804,57.86545,4 -1494.702,60.97232,4 -1495.856,53.67446,4 -1488.354,8.644087,4 -1473.771,9.854107,4 -1459.911,11.31598,4 -1449.71,29.82105,4 -1444.35,38.53183,4 -1441.259,42.37823,4 -1436.486,28.24177,4 -1429.513,28.8433,4 -1421.864,23.41715,4 -1414.392,28.83934,4 -1409.071,34.798,4 -1403.584,27.19031,4 -1396.982,27.69853,4 -1388.531,15.91847,4 -1377.224,10.64097,4 -1366.25,16.52416,4 -1358.612,27.90209,4 -1355.629,41.29479,4 -1355.726,44.49744,4 -1358.876,58.18682,4 -1366.27,68.5884,4 -1376.618,76.04653,4 -1388.952,81.80117,4 -1400.522,74.14407,4 -1408.504,63.53102,4 -1415.252,68.5932,4 -1420.651,56.93834,4 -1423.263,53.41837,4 -1425.219,53.58304,4 -1426.207,48.11959,4 -1426.852,51.75898,4 -1427.38,47.54124,4 -1423.742,27.67442,4 -1415.125,18.26986,4 -1402.381,3.03742,4 -1388.482,10.29751,4 -1373.977,-1.384802,4 -1355.462,-10.03899,4 -1330.062,-15.91993,4 -1282.331,-13.68837,4 -1209.601,-11.78776,4 -1130.279,-10.6761,4 -1056.59,-9.85384,4 -995.0887,-9.493731,4 -932.1101,-8.854118,4 -860.5636,-8.522646,4 -799.4923,-8.632871,4 -742.3431,-8.777902,4 -916.95,-7.472395,4 -784.6405,-6.526037,4 -659.1023,-7.239723,4 -802.2018,-4.796231,4 -600,-4.862612,4 -980.1921,3.036931,4 -655.1318,-1.243356,4 -600,-3.643281,4 -600,-2.117112,4 -600,-0.4603643,4 -600,-2.24E-05,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,-2.38E-07,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,-2.38E-07,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,2.38E-07,4 -600,0,4 -600,2.38E-07,4 -600,0,4 -600,0,4 -600,-2.38E-07,4 -600,-2.38E-07,4 -644.4445,1.714838,4 -644.4445,1.621784,4 -644.4445,3.298661,4 -755.8596,3.870013,4 -644.4445,3.134853,4 -644.4445,1.420932,4 -644.4445,1.825752,4 -644.4445,1.360866,4 -991.1098,0.8516321,4 -644.4445,2.159252,4 -644.4445,1.824742,4 -644.4445,1.209069,4 -645.8011,2.986922,4 -651.5524,2.650311,4 -659.7339,0.760689,4 -685.8124,4.595871,4 -737.2534,3.604281,4 -762.7693,2.212489,4 -770.3373,1.737349,4 -772.536,1.632224,4 -772.3826,1.47518,4 -768.9055,1.248654,4 -770.1327,2.003068,4 -775.6552,1.749856,4 -776.7802,1.519026,4 -774.1212,1.315794,4 -769.7236,1.307899,4 -770.2861,1.870355,4 -770.2861,1.245239,4 -768.343,1.646059,4 -768.3942,1.467183,4 -762.5137,0.9683771,4 -717.0042,-2.388535,4 -628.3375,-2.716046,4 -644.4445,1.232642,4 -1006.313,0.3278913,4 -950.627,-0.5628872,4 -846.9909,-1.407126,4 -722.4837,-1.039502,4 -621.8163,-0.4376612,4 -600,0.0385704,4 -644.4445,1.879608,4 -602.8344,0.04388237,4 -600,-0.00674057,4 -644.4445,1.93153,4 -794.813,7.284958,4 -644.8845,6.377717,4 -738.2761,9.556376,4 -924.2001,17.0417,4 -1082.921,9.743132,4 -1157.014,6.99104,4 -775.9276,22.85481,4 -919.729,33.17456,4 -1086.138,42.19983,4 -1261.492,50.43425,4 -1375.494,19.51903,4 -1401.449,6.091826,4 -926.2782,23.43933,4 -980.7605,39.51251,4 -1054.848,47.15857,4 -1133.927,51.68547,4 -1226.62,71.72372,4 -1337.942,86.13082,4 -1457.344,97.89137,4 -1580.828,109.5713,4 -1657.092,36.67658,4 -1123.368,1.461304,4 -1122.441,25.1924,4 -1136.454,37.02988,4 -1161.309,52.76898,4 -1193.459,57.73195,4 -1230.285,68.77976,4 -1273.533,79.75322,4 -1318.352,79.31004,4 -1356.562,67.54053,4 -1392.273,77.71348,4 -1426.908,69.05838,4 -1460.725,80.27706,4 -1498.424,86.01363,4 -1534.793,81.56979,4 -1565.21,71.81206,4 -1590.119,67.43898,4 -1612.582,66.8174,4 -1634.24,67.57295,4 -1656.032,70.10327,4 -1677.488,69.22984,4 -1696.042,62.52128,4 -1711.774,61.43768,4 -1725.102,55.68619,4 -1731.578,37.91976,4 -1722.254,-1.090255,4 -1702.517,-0.3800182,4 -1681.747,-5.168064,4 -1664.59,11.20999,4 -1654.514,18.04026,4 -1645.996,15.99401,4 -1635.436,10.42183,4 -1621.665,4.338938,4 -1605.22,0.5969486,4 -1587.795,0.2512197,4 -1570.517,0.3162355,4 -1554.072,2.230137,4 -1541.806,13.14601,4 -1533.597,14.75539,4 -1525.832,14.09572,4 -1514.506,2.944591,4 -1496.1,-7.84253,4 -1471.352,-15.42717,4 -1440.169,-20.01007,4 -1400.468,-18.50732,4 -1353.19,-17.0692,4 -1315.531,-12.80798,4 -1294.491,-3.285613,4 -1284.173,13.58008,4 -1289.225,37.47305,4 -1302.015,35.04106,4 -1311.339,28.96468,4 -1316.942,25.44615,4 -1328.926,47.30635,4 -1352.921,60.59223,4 -1385.233,74.25334,4 -1422.945,80.9559,4 -1461.329,81.75445,4 -1495.643,73.77378,4 -1525.133,71.24657,4 -1553.333,73.6284,4 -1578.726,65.64669,4 -1596.568,51.4837,4 -1607.732,45.11185,4 -1612.851,32.04094,4 -1610.876,21.44158,4 -1605.126,19.07754,4 -1598.368,17.63783,4 -1591.677,18.84343,4 -1582.676,9.494823,4 -1569.455,4.294639,4 -1552.541,-2.913902,4 -1532.455,-5.940009,4 -1507.855,-16.18926,4 -1475.826,-18.23104,4 -1433.29,-16.7917,4 -1382.384,-15.64154,4 -1326.494,-14.32655,4 -1274.366,-13.89831,4 -1227.275,-12.87859,4 -1182.348,-12.34522,4 -1151.286,-9.173134,4 -1131.402,-6.310503,4 -1119.781,8.727276,4 -1118.289,16.43811,4 -1118.921,13.66425,4 -1120.828,19.48628,4 -1124.819,18.68554,4 -1130.757,24.36229,4 -1141.048,29.49514,4 -1158.46,42.48001,4 -1180.763,43.03611,4 -1203.146,44.87235,4 -1225.918,46.25666,4 -1248.597,46.92699,4 -1272.592,52.15644,4 -1299.516,57.51007,4 -1329.074,62.6179,4 -1359.343,63.1154,4 -1380.947,40.95043,4 -1388.403,23.98634,4 -1388.417,19.74684,4 -1385.165,14.44612,4 -1379.603,12.82719,4 -1372.187,8.792199,4 -1363.065,7.554926,4 -1349.723,-3.177336,4 -1329.396,-11.0907,4 -1300.833,-14.74182,4 -1261.575,-13.61232,4 -1217.468,-12.85518,4 -1175.268,-12.22688,4 -1141.546,-12.1833,4 -1126.955,11.26167,4 -1134.532,35.89684,4 -1157.695,49.54621,4 -1189.052,58.5972,4 -1222.466,58.37698,4 -1257.343,66.71474,4 -1300.538,85.77503,4 -1352.393,97.63816,4 -1402.304,88.47597,4 -1444.938,84.01994,4 -1484.008,84.11902,4 -1521.116,83.72038,4 -1557.216,86.50259,4 -1591.624,83.49979,4 -1623.855,84.3294,4 -1647.595,58.56056,4 -1655.346,31.51854,4 -1647.595,5.291959,4 -1637.236,21.8509,4 -1638.069,43.26761,4 -1647.353,51.25405,4 -1657.993,48.95843,4 -1668.862,53.2352,4 -1680.014,51.13348,4 -1689.217,47.52374,4 -1696.109,43.85042,4 -1700.18,38.1036,4 -1701.886,35.75303,4 -1704.895,42.96144,4 -1713.521,56.36014,4 -1723.759,49.71629,4 -1725.169,25.28842,4 -1717.766,17.81898,4 -1708.886,19.36817,4 -1699.602,15.74377,4 -1685.428,1.331335,4 -1668.258,4.265698,4 -1651.088,0.4824829,4 -1632.682,-0.7735591,4 -1616.546,7.333869,4 -1601.297,1.405253,4 -1587.109,10.06296,4 -1578.108,17.9458,4 -1571.148,16.3085,4 -1567.669,28.97894,4 -1571.471,40.18153,4 -1577.49,36.66446,4 -1581.507,34.05357,4 -1584.664,34.14597,4 -1581.897,14.52561,4 -1573.567,15.4157,4 -1560.951,-0.06234074,4 -1539.428,-12.5987,4 -1514.842,-9.453217,4 -1487.81,-18.44072,4 -1460.886,-9.728415,4 -1437.804,-9.730576,4 -1416.16,-6.372715,4 -1395.067,-8.671995,4 -1373.544,-7.898953,4 -1360.901,15.09554,4 -1358.859,20.97911,4 -1363.857,35.19839,4 -1379.617,52.60059,4 -1405.99,68.11739,4 -1434.069,60.73365,4 -1456.748,55.0891,4 -1477.304,56.83291,4 -1499.552,62.82561,4 -1522.835,62.77331,4 -1543.606,57.48309,4 -1563.611,62.81192,4 -1585.403,65.84775,4 -1604.911,57.73931,4 -1619.407,51.10355,4 -1625.279,29.70323,4 -1619.824,12.86922,4 -1606.134,1.337738,4 -1587.701,-3.369208,4 -1572.465,11.06384,4 -1564.538,19.60567,4 -1563.638,33.72519,4 -1569.052,40.41961,4 -1578.041,46.10619,4 -1586.653,40.0111,4 -1594.445,44.22099,4 -1602.896,42.9819,4 -1610.231,41.26826,4 -1616.559,40.2604,4 -1624.123,46.1275,4 -1634.065,49.20351,4 -1644.907,50.29093,4 -1656.059,51.45343,4 -1668.943,57.63499,4 -1688.625,77.20282,4 -1711.116,70.17025,4 -1728.34,61.05583,4 -1744.61,68.95058,4 -1762.868,70.50829,4 -1779.366,64.74032,4 -1794.387,67.11285,4 -1807.486,59.31385,4 -1818.275,59.92589,4 -1828.835,59.76006,4 -1834.155,40.87052,4 -1824.254,1.570856,4 -1803.939,0.1671991,4 -1785.896,8.91948,4 -1769.089,3.76696,4 -1750.548,1.465682,4 -1734.198,10.69146,4 -1720.507,10.2054,4 -1707.327,11.65767,4 -1695.45,14.03399,4 -1684.931,15.71651,4 -1675.325,16.56543,4 -1665.933,15.82545,4 -1654.339,8.25458,4 -1639.587,4.160066,4 -1622.202,-1.38369,4 -1608.431,15.49589,4 -1602.748,25.05814,4 -1601.189,29.03644,4 -1603.151,36.84112,4 -1608.673,41.2834,4 -1614.087,36.97735,4 -1619.031,40.19678,4 -1622.941,33.88109,4 -1623.505,29.08438,4 -1621.114,23.80924,4 -1615.149,16.70804,4 -1607.464,17.53648,4 -1602.546,25.54437,4 -1600.706,27.58181,4 -1600.195,29.89292,4 -1602.318,36.44426,4 -1608.995,45.53632,4 -1616.116,38.564,4 -1619.327,32.86123,4 -1617.164,20.48985,4 -1607.571,7.451408,4 -1591.973,-0.2941513,4 -1573.177,-3.498985,4 -1552.541,-6.302647,4 -1531.81,-4.429373,4 -1511.698,-5.13943,4 -1493.265,-0.3575616,4 -1477.143,0.7890692,4 -1461.141,-0.5568328,4 -1445.449,1.121991,4 -1430.375,0.6806421,4 -1410.706,-11.54041,4 -1385.824,-13.42626,4 -1360.619,-12.66673,4 -1335.24,-14.07331,4 -1309.62,-13.46232,4 -1274.366,-13.88826,4 -1237.862,-13.81937,4 -1212.241,-11.44095,4 -1184.081,-12.65552,4 -1148.102,-11.87495,4 -1115.508,-11.77358,4 -1087.442,-11.19799,4 -1054.593,-10.48865,4 -1033.607,5.6588,4 -1040.043,33.29015,4 -1064.535,46.21249,4 -1097.908,56.06443,4 -1138.16,66.53667,4 -1181.515,68.95843,4 -1223.258,68.46669,4 -1261.723,66.08852,4 -1300.779,75.51466,4 -1341.756,76.87059,4 -1377.36,65.75189,4 -1406.339,62.23019,4 -1433.908,65.22336,4 -1459.475,59.45428,4 -1483.82,64.64926,4 -1510.354,69.41556,4 -1536.862,67.94376,4 -1560.467,63.31855,4 -1581.225,61.46338,4 -1596.42,47.04777,4 -1600.343,25.01183,4 -1593.115,9.831497,4 -1584.181,18.76838,4 -1581.493,30.10958,4 -1586.962,45.85008,4 -1600.37,57.38508,4 -1617.769,60.89524,4 -1636.443,63.86408,4 -1655.078,63.03837,4 -1671.496,58.34701,4 -1686.221,59.03419,4 -1700.287,57.73484,4 -1710.955,48.39701,4 -1717.229,43.00974,4 -1721.3,41.04623,4 -1725.115,42.49238,4 -1729.374,43.04696,4 -1732.33,38.14999,4 -1734.453,40.29311,4 -1737.193,40.62325,4 -1742.259,49.12432,4 -1749.527,49.27705,4 -1758.905,57.77568,4 -1780.186,95.1664,4 -1817.066,120.4318,4 -1863.283,138.34,4 -1894.667,69.34295,4 -1907.269,68.27747,4 -1919.079,67.84028,4 -1917.762,16.49406,4 -1889.951,-25.8662,4 -1839.596,-23.89131,4 -1797.746,-6.402427,4 -1288.914,-15.27851,4 -1277.128,32.77653,4 -1281.275,63.12198,4 -1290.283,58.78977,4 -1302.49,81.71949,4 -1320.926,94.45592,4 -1342.199,101.122,4 -1364.574,105.4511,4 -1384.497,92.51437,4 -1399.036,79.38459,4 -1412.044,86.92896,4 -1425.375,83.94568,4 -1438.726,89.94231,4 -1452.996,92.26556,4 -1465.477,82.38766,4 -1473.311,67.06986,4 -1478.475,67.91246,4 -1485.547,79.625,4 -1497.763,100.7359,4 -1512.278,96.41169,4 -1525.707,97.44376,4 -1538.334,94.52263,4 -1549.249,89.58551,4 -1557.71,81.4274,4 -1564.057,77.99872,4 -1569.036,74.02861,4 -1572.312,68.13066,4 -1575.041,71.18874,4 -1576.86,62.82628,4 -1576.352,56.58434,4 -1574.357,53.18288,4 -1571.52,50.82687,4 -1567.755,46.73517,4 -1562.385,39.9514,4 -1553.406,22.98973,4 -1541.513,20.22375,4 -1527.653,9.152882,4 -1512.63,11.24,4 -1497.871,9.012047,4 -1484.578,18.34523,4 -1477.82,46.65918,4 -1476.558,50.44249,4 -1476.832,55.68708,4 -1479.131,62.68777,4 -1483.698,69.81506,4 -1490.535,77.33602,4 -1498.018,75.10793,4 -1505.011,75.88093,4 -1512.151,77.44696,4 -1520.327,83.79372,4 -1527.986,75.92196,4 -1532.671,66.83388,4 -1536.348,70.5734,4 -1539.762,65.89542,4 -1543.273,71.87601,4 -1547.303,69.85374,4 -1549.034,58.16096,4 -1547.87,51.91158,4 -1546.364,55.78762,4 -1544.672,50.47578,4 -1541.356,45.2815,4 -1538.324,51.6749,4 -1537.356,57.68959,4 -1538.872,67.07841,4 -1544.251,82.28827,4 -1545.288,40.75605,4 -1538.011,30.25864,4 -1530.314,36.96606,4 -1522.196,26.52944,4 -1511.906,22.36277,4 -1500.12,15.97792,4 -1489.616,28.55366,4 -1482.329,34.04303,4 -1478.945,50.99249,4 -1479.502,57.25879,4 -1480.607,54.3908,4 -1481.048,53.44007,4 -1481.713,55.82595,4 -1482.329,53.25982,4 -1482.818,55.16615,4 -1481.811,44.30854,4 -1479.307,45.96726,4 -1476.646,42.96669,4 -1473.575,43.07121,4 -1471.717,49.74657,4 -1470.788,48.34003,4 -1472.177,63.49163,4 -1475.942,62.85665,4 -1479.972,65.78904,4 -1484.334,65.62042,4 -1488.217,63.7094,4 -1490.124,54.34649,4 -1490.183,52.82955,4 -1489.342,48.89529,4 -1488.755,54.22676,4 -1487.777,46.42638,4 -1486.192,50.38337,4 -1485.576,52.02367,4 -1487.601,66.28146,4 -1491.67,64.79538,4 -1494.985,62.46672,4 -1496.091,51.93176,4 -1492.462,33.85468,4 -1486.104,34.78819,4 -1476.089,10.9714,4 -1464.117,21.67854,4 -1454.757,25.02648,4 -1445.866,23.2522,4 -1436.829,23.01534,4 -1428.603,26.81799,4 -1421.473,28.30663,4 -1413.345,20.16391,4 -1404.963,25.78935,4 -1396.278,17.4505,4 -1387.201,22.49283,4 -1379.914,26.44587,4 -1372.432,20.53219,4 -1364.392,22.42527,4 -1357.027,23.32439,4 -1350.679,27.14028,4 -1350.269,55.12245,4 -1357.262,67.91344,4 -1367.101,72.15673,4 -1377.987,75.64056,4 -1389.636,78.59641,4 -1399.104,65.48586,4 -1405.217,61.24613,4 -1409.795,57.77759,4 -1413.922,59.46923,4 -1417.404,54.76487,4 -1420.857,59.91445,4 -1423.595,51.20931,4 -1424.886,51.9877,4 -1425.776,49.09315,4 -1423.556,34.09339,4 -1418.059,29.80763,4 -1405.119,-7.826694,4 -1385.391,-8.599997,4 -1365.175,-11.35708,4 -1344.4,-11.20156,4 -1318.843,-15.60458,4 -1278.125,-14.10385,4 -1212.223,-11.80592,4 -1143.825,-11.62002,4 -1080.622,-10.19347,4 -1005.036,-8.704713,4 -942.2039,-9.229837,4 -877.6898,-7.629379,4 -796.7341,-8.281475,4 -1005.85,-9.090136,4 -922.6464,-8.02299,4 -814.1037,-6.777267,4 -680.4239,-6.171268,4 -600,-6.54746,4 -881.2298,-1.826855,4 -625.3334,-5.014571,4 -600,-5.152775,4 -600,-4.932726,4 -600,-1.280655,4 -600,-0.4310925,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 -600,0,4 +<n> + , + <Pe> + , + <Padd> + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,-2.38E-07,2 + 600,-2.38E-07,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,-2.38E-07,2 + 600,2.38E-07,2 + 600,0,2 + 644.4445,2.329973,2 + 644.4445,0.5693641,2 + 644.4445,4.264177,2 + 869.7512,7.98456,2 + 644.4445,1.351656,2 + 1015.31,-0.2716608,2 + 948.6478,-0.4653716,2 + 872.4501,-0.5719776,2 + 644.4445,1.012361,2 + 816.044,0.1606398,2 + 644.4445,3.967641,2 + 644.4445,4.3916,2 + 645.3466,1.254886,2 + 602.9238,0.36098,2 + 644.4445,1.097353,2 + 644.4445,1.476951,2 + 645.6951,2.961375,2 + 656.8193,3.33839,2 + 688.8293,2.509675,2 + 715.7259,3.104633,2 + 743.2361,2.779576,2 + 759.3434,2.025352,2 + 763.0762,1.467997,2 + 761.0308,1.383811,2 + 757.7582,1.320618,2 + 755.406,1.475238,2 + 756.3265,1.681716,2 + 753.872,1.098228,2 + 749.1166,1.411724,2 + 747.787,1.465289,2 + 743.7986,1.110595,2 + 691.6417,-3.012229,2 + 627.2637,-0.1685431,2 + 1049.495,-0.09707546,2 + 644.4445,1.615664,2 + 1026.825,0.4667768,2 + 977.9754,-0.4151859,2 + 906.5457,-0.4785028,2 + 764.8557,-2.495939,2 + 615.8789,-0.5095253,2 + 600,-0.2679868,2 + 644.4445,0.5701756,2 + 644.4445,1.185031,2 + 600,0.2967396,2 + 646.6069,3.811063,2 + 895.4804,7.923037,2 + 653.8535,6.359474,2 + 791.9158,11.55912,2 + 900.8318,4.931076,2 + 1007.856,14.46236,2 + 1156.708,13.49057,2 + 1345.086,27.20026,2 + 1602.138,35.01208,2 + 1888.49,46.58702,2 + 2103.714,24.29906,2 + 2146.359,-1.109985,2 + 1286.033,8.800848,2 + 1351.937,37.56419,2 + 1494.108,56.84015,2 + 1650.18,55.71647,2 + 1797.949,62.99876,2 + 1974.041,90.22348,2 + 2191.804,115.1789,2 + 2403.877,105.9852,2 + 2503.301,18.33513,2 + 1611.144,-1.709167,2 + 1619.774,43.61679,2 + 1655.685,42.16265,2 + 1690.462,44.19933,2 + 1723.907,42.2117,2 + 1766.618,62.7349,2 + 1823.327,70.33007,2 + 1898.131,102.0343,2 + 1980.033,91.64824,2 + 2027.516,42.57878,2 + 2040.799,27.31307,2 + 1396.846,69.06043,2 + 1435.803,91.8233,2 + 1479.637,89.72998,2 + 1511.026,58.87632,2 + 1535.129,70.88527,2 + 1563.544,76.08076,2 + 1591.288,72.46291,2 + 1615.981,69.52535,2 + 1637.034,63.16708,2 + 1654.957,61.31534,2 + 1674.975,72.86595,2 + 1695.262,64.75288,2 + 1709.799,54.75394,2 + 1712.769,24.54955,2 + 1702.061,5.766651,2 + 1685.925,4.414207,2 + 1669.991,5.575367,2 + 1656.502,12.07608,2 + 1644.88,11.30247,2 + 1634.482,15.56817,2 + 1624.607,12.47053,2 + 1610.151,-0.5362444,2 + 1594.136,6.376687,2 + 1580.163,5.485111,2 + 1564.78,1.025784,2 + 1550.539,8.4501,2 + 1539.777,11.6633,2 + 1532.066,17.71403,2 + 1521.599,2.418658,2 + 1504.309,-4.049212,2 + 1481.361,-14.07779,2 + 1453.792,-17.15281,2 + 1423.724,-18.15207,2 + 1385.246,-16.81612,2 + 1337.242,-15.72801,2 + 1293.188,-15.42869,2 + 1281.755,38.3059,2 + 1286.484,11.6914,2 + 1283.596,17.9171,2 + 1285.597,24.78118,2 + 1291.778,29.405,2 + 1303.359,40.06316,2 + 1321.147,47.6144,2 + 1343.046,53.40984,2 + 1367.31,56.75732,2 + 1398.372,76.35516,2 + 1441.017,95.91759,2 + 1491.115,106.3325,2 + 1533.099,77.92695,2 + 1561.824,69.6596,2 + 1584.033,60.08042,2 + 1597.119,41.62484,2 + 1603.93,40.29163,2 + 1607.558,31.45644,2 + 1604.965,19.52167,2 + 1600.142,23.70411,2 + 1596.299,22.48869,2 + 1589.192,12.48158,2 + 1578.793,11.02395,2 + 1566.889,6.910674,2 + 1551.426,-1.123854,2 + 1528.707,-15.20682,2 + 1502.589,-11.37927,2 + 1476.041,-16.47795,2 + 1439.148,-17.79036,2 + 1386.845,-16.22873,2 + 1331.801,-15.54598,2 + 1276.609,-14.19835,2 + 1222.116,-13.53877,2 + 1183.826,-13.63705,2 + 1165.594,4.323093,2 + 1154.524,-0.2198782,2 + 1145.307,8.251244,2 + 1136.212,-0.1459947,2 + 1127.318,8.395197,2 + 1127.425,20.90548,2 + 1132.316,19.78157,2 + 1134.976,15.85121,2 + 1140.847,27.66578,2 + 1153.503,32.64259,2 + 1173.508,46.8272,2 + 1195.77,39.98267,2 + 1214.31,39.54551,2 + 1235.31,48.15401,2 + 1262.019,56.77373,2 + 1290.77,56.59818,2 + 1317.063,53.30949,2 + 1343.879,61.21212,2 + 1364.448,38.20493,2 + 1372.416,26.90753,2 + 1376.097,26.42333,2 + 1374.269,11.18833,2 + 1368.546,15.03598,2 + 1362.863,11.02519,2 + 1356.038,11.46854,2 + 1346.136,1.988382,2 + 1325.11,-16.2194,2 + 1284.63,-14.65078,2 + 1238.373,-14.2102,2 + 1193.929,-12.98282,2 + 1155.988,-13.10039,2 + 1137.273,2.958799,2 + 1132.786,15.8914,2 + 1141.075,33.33242,2 + 1156.7,34.19608,2 + 1179.433,52.38899,2 + 1213.827,66.11726,2 + 1258.176,83.05579,2 + 1305.898,81.63163,2 + 1353.754,91.2124,2 + 1396.935,75.19558,2 + 1438.893,94.76639,2 + 1487.004,100.8023,2 + 1529.298,83.95088,2 + 1563.974,82.77102,2 + 1596.393,81.57443,2 + 1624.446,72.54066,2 + 1640.138,42.54347,2 + 1643,29.84203,2 + 1638.257,16.47232,2 + 1629.605,16.00256,2 + 1630.478,48.60144,2 + 1642.785,55.60721,2 + 1656.623,55.29026,2 + 1669.48,53.73763,2 + 1680.188,49.11893,2 + 1689.163,48.75134,2 + 1695.907,42.08216,2 + 1700.851,42.99605,2 + 1706.79,46.16529,2 + 1713.763,47.34768,2 + 1720.427,45.77478,2 + 1727.319,48.89489,2 + 1725.733,15.54477,2 + 1714.932,15.2667,2 + 1703.74,13.40421,2 + 1690.842,8.433504,2 + 1676.749,8.346373,2 + 1663.421,10.28855,2 + 1648.951,3.619027,2 + 1633.192,5.002003,2 + 1617.433,2.826547,2 + 1602.775,7.905733,2 + 1589.501,6.74611,2 + 1576.428,7.864722,2 + 1567.118,18.46364,2 + 1564.686,30.00007,2 + 1567.427,35.38074,2 + 1572.196,36.95614,2 + 1576.469,34.14531,2 + 1576.307,22.5677,2 + 1570.826,16.47429,2 + 1563.423,15.84486,2 + 1553.562,7.964062,2 + 1536.916,-5.952643,2 + 1517.233,-2.275624,2 + 1497.389,-6.935693,2 + 1471.863,-18.41763,2 + 1442.372,-18.13165,2 + 1414.871,-13.40553,2 + 1387.812,-17.13374,2 + 1362.057,-10.3961,2 + 1346.257,8.515593,2 + 1345.787,31.16553,2 + 1358.712,46.74545,2 + 1379.066,53.84549,2 + 1401.382,54.66264,2 + 1424.557,58.96523,2 + 1447.437,56.39186,2 + 1469.605,59.47992,2 + 1493.117,63.22589,2 + 1515.124,57.4621,2 + 1535.841,61.76757,2 + 1557.969,64.56117,2 + 1578.323,58.54613,2 + 1596.594,60.07353,2 + 1611.991,50.88236,2 + 1621.194,40.61778,2 + 1619.421,14.21795,2 + 1605.113,-1.868717,2 + 1588.762,6.50421,2 + 1576.67,11.31663,2 + 1569.348,21.61535,2 + 1567.91,30.3064,2 + 1571.135,36.95245,2 + 1576.267,36.91877,2 + 1582.797,42.09142,2 + 1590.294,40.76203,2 + 1597.817,42.91198,2 + 1605.462,41.89369,2 + 1612.273,40.82465,2 + 1619.582,44.26139,2 + 1628.167,45.92483,2 + 1637.464,47.59579,2 + 1648.723,53.73099,2 + 1661.419,53.84293,2 + 1676.91,65.1045,2 + 1695.235,65.79607,2 + 1711.21,58.91008,2 + 1724.968,59.73791,2 + 1739.437,63.20061,2 + 1753.772,61.00745,2 + 1768,64.61153,2 + 1781.368,59.52817,2 + 1794.521,65.5128,2 + 1809.072,66.50668,2 + 1818.449,47.4547,2 + 1817.24,26.92148,2 + 1805.995,8.979017,2 + 1786.662,-4.010155,2 + 1765.233,-0.05493259,2 + 1742.89,-7.886769,2 + 1721.609,2.619378,2 + 1703.539,1.704347,2 + 1687.591,9.187813,2 + 1675.688,15.12251,2 + 1669.373,28.10153,2 + 1666.148,25.54206,2 + 1659.176,14.7161,2 + 1647.474,8.565833,2 + 1631.875,0.5784202,2 + 1615.068,3.583271,2 + 1599,2.292942,2 + 1587.324,17.45128,2 + 1584.315,30.57986,2 + 1586.8,35.61685,2 + 1593.088,43.5732,2 + 1602.506,46.77898,2 + 1611.978,44.69442,2 + 1618.292,36.94254,2 + 1621.436,34.45127,2 + 1619.475,19.75505,2 + 1612.367,16.75193,2 + 1602.009,8.288825,2 + 1592.927,20.35848,2 + 1589.178,25.61557,2 + 1589.299,33.05613,2 + 1592.766,36.86369,2 + 1600.84,48.93576,2 + 1611.79,47.39437,2 + 1614.947,23.44294,2 + 1610.836,22.92943,2 + 1603.433,12.01165,2 + 1586.975,-7.003079,2 + 1563.772,-9.861372,2 + 1540.355,-8.272071,2 + 1519.907,-2.04369,2 + 1503.677,3.384114,2 + 1487.904,-1.296515,2 + 1471.513,0.8036427,2 + 1454.625,-3.150111,2 + 1435.789,-5.048037,2 + 1415.583,-7.256803,2 + 1396.787,-1.866434,2 + 1379.012,-5.011639,2 + 1361.345,-2.060575,2 + 1341.192,-11.55893,2 + 1317.613,-10.92163,2 + 1291.294,-15.20063,2 + 1254.361,-14.80647,2 + 1210.226,-14.88861,2 + 1174.65,-14.81055,2 + 1147.215,-14.28176,2 + 1119.552,-13.7853,2 + 1087.993,-13.05181,2 + 1052.511,-12.44097,2 + 1031.579,5.715624,2 + 1037.853,32.76339,2 + 1064.428,51.27643,2 + 1098.567,52.62703,2 + 1138.801,70.14542,2 + 1186.926,77.43063,2 + 1233.348,72.79241,2 + 1273.076,66.44997,2 + 1304.85,56.3991,2 + 1335.952,68.81242,2 + 1369.93,68.46135,2 + 1401.744,66.97513,2 + 1432.914,70.78075,2 + 1462.162,65.10287,2 + 1490.927,73.24111,2 + 1519.369,67.75407,2 + 1544.292,65.61349,2 + 1569.657,72.50694,2 + 1591.342,56.41633,2 + 1604.709,47.0724,2 + 1608.203,24.27454,2 + 1601.539,12.98722,2 + 1592.376,15.38727,2 + 1589.407,33.14979,2 + 1593.76,39.76634,2 + 1602.748,49.21623,2 + 1614.531,50.16054,2 + 1628.221,57.05817,2 + 1646.023,65.98457,2 + 1665.665,65.65594,2 + 1683.789,63.0876,2 + 1698.339,55.09802,2 + 1707.865,46.70007,2 + 1711.465,34.71091,2 + 1712.298,37.05171,2 + 1713.763,37.07273,2 + 1717.041,43.76989,2 + 1723.678,49.61529,2 + 1733.472,56.02866,2 + 1744.677,55.90408,2 + 1750.736,38.25808,2 + 1755.6,52.16808,2 + 1767.544,65.1767,2 + 1784.929,74.09778,2 + 1810.361,98.34163,2 + 1843.734,108.7761,2 + 1876.234,100.4823,2 + 1900.229,80.1554,2 + 1920.624,89.84477,2 + 1923.486,11.55359,2 + 1384.726,-6.716908,2 + 1365.214,-9.758064,2 + 1335.167,-15.65223,2 + 1305.561,-9.438278,2 + 1293.54,25.59272,2 + 1293.716,51.81037,2 + 1298.87,51.8591,2 + 1307.468,70.9785,2 + 1321.719,83.69244,2 + 1340.242,97.09694,2 + 1361.364,102.0721,2 + 1381.797,98.08289,2 + 1396.943,76.64746,2 + 1408.093,78.5398,2 + 1421.649,92.87965,2 + 1436.79,90.6324,2 + 1452.067,97.12432,2 + 1465.261,81.55907,2 + 1474.817,78.22183,2 + 1481.586,66.6988,2 + 1486.936,71.00793,2 + 1494.076,78.64029,2 + 1504.805,94.48131,2 + 1519.545,105.7961,2 + 1533.59,93.55258,2 + 1544.594,90.03146,2 + 1553.279,81.37687,2 + 1560.448,82.33672,2 + 1566.855,78.04972,2 + 1572.087,76.19854,2 + 1574.895,63.56385,2 + 1574.396,55.5367,2 + 1573.515,61.01888,2 + 1573.036,57.94503,2 + 1570.845,49.96451,2 + 1566.747,45.35576,2 + 1559.803,31.16218,2 + 1548.662,17.72969,2 + 1536.094,20.5824,2 + 1523.252,14.39674,2 + 1509.539,13.54565,2 + 1497.577,23.35009,2 + 1487.474,23.31975,2 + 1479.131,32.58831,2 + 1472.793,34.21489,2 + 1471.189,59.98996,2 + 1474.25,61.94712,2 + 1479.943,76.42569,2 + 1487.386,73.62328,2 + 1493.87,72.10479,2 + 1498.252,62.06528,2 + 1504.355,83.55563,2 + 1514.009,85.13411,2 + 1522.518,78.52847,2 + 1528.054,68.42541,2 + 1531.879,68.98322,2 + 1535.693,69.12019,2 + 1539.86,71.95422,2 + 1543.156,64.46819,2 + 1544.232,58.62698,2 + 1542.999,50.14769,2 + 1540.877,52.80785,2 + 1538.393,47.5109,2 + 1535.83,51.87814,2 + 1534.607,55.44809,2 + 1535.527,65.06208,2 + 1540.046,78.20454,2 + 1545.102,69.33004,2 + 1542.54,31.26162,2 + 1534.764,36.16859,2 + 1527.125,30.95866,2 + 1517.892,25.15287,2 + 1508.043,25.83571,2 + 1498.927,28.26935,2 + 1490.525,28.91031,2 + 1483.571,35.82453,2 + 1480.344,50.35513,2 + 1480.471,55.54207,2 + 1481.576,56.2795,2 + 1481.869,50.83329,2 + 1480.745,47.77131,2 + 1478.28,42.57355,2 + 1476.333,50.48153,2 + 1475.023,46.08316,2 + 1474.094,52.55144,2 + 1473.565,48.33829,2 + 1472.754,50.75901,2 + 1472.802,53.36675,2 + 1472.646,49.53503,2 + 1472.675,54.45502,2 + 1472.744,49.77462,2 + 1473.644,59.45992,2 + 1476.216,59.98241,2 + 1477.918,54.67937,2 + 1478.984,56.45734,2 + 1479.639,52.3883,2 + 1481.234,62.24279,2 + 1484.403,62.18639,2 + 1488.227,66.80893,2 + 1491.239,57.95909,2 + 1493.107,60.41497,2 + 1495.973,64.38061,2 + 1498.477,58.73077,2 + 1499.935,58.45076,2 + 1498.233,39.69763,2 + 1490.447,21.17598,2 + 1479.659,20.41969,2 + 1469.35,22.65018,2 + 1458.865,18.07665,2 + 1449.143,25.79696,2 + 1440.174,21.3046,2 + 1431.009,23.49089,2 + 1422.334,22.9997,2 + 1411.819,11.86371,2 + 1402.048,25.93449,2 + 1394.321,22.3779,2 + 1386.849,26.39423,2 + 1381.039,30.80274,2 + 1374.056,19.11548,2 + 1365.478,21.04128,2 + 1357.8,23.10369,2 + 1351.413,27.2389,2 + 1348.342,40.50266,2 + 1348.86,46.52771,2 + 1354.67,69.74982,2 + 1364.49,69.70929,2 + 1375.415,77.81886,2 + 1386.575,73.11307,2 + 1395.456,67.07029,2 + 1403.241,68.56764,2 + 1410.313,64.41555,2 + 1416.035,62.10302,2 + 1420.035,55.49044,2 + 1423.057,57.14668,2 + 1424.515,46.92026,2 + 1424.466,48.65111,2 + 1424.349,46.51535,2 + 1420.514,27.12698,2 + 1412.171,19.98239,2 + 1399.202,-0.2213111,2 + 1381.088,-8.825974,2 + 1360.959,-10.97501,2 + 1339.52,-15.13851,2 + 1315.038,-15.79168,2 + 1271.67,-13.71585,2 + 1205.943,-12.13631,2 + 1122.19,-10.03683,2 + 1048.169,-10.36391,2 + 990.1788,-9.246284,2 + 928.2859,-9.212884,2 + 867.8992,-9.020022,2 + 804.412,-8.525709,2 + 729.0021,-8.260065,2 + 887.2314,-7.793596,2 + 782.4908,-7.821894,2 + 665.2287,-6.784316,2 + 772.3559,-4.63562,2 + 600,-6.277975,2 + 614.9388,-5.288214,2 + 696.7551,-3.49948,2 + 600,-1.283326,2 + 664.3683,-1.597912,2 + 600,-1.778763,2 + 600,-0.7596555,2 + 600,-0.1736608,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,-2.38E-07,2 + 600,-2.38E-07,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,2.38E-07,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,0,2 + 600,2.38E-07,2 + 600,0,2 + 600,0,2 + 600,-2.38E-07,2 + 600,0,2 + 644.4445,1.612164,2 + 644.4445,6.538949,2 + 785.0072,0.8882241,2 + 841.1434,3.194654,2 + 644.4445,4.281434,2 + 1009.552,-0.1017489,2 + 970.5985,0.5266633,2 + 942.8003,0.3860083,2 + 644.4445,2.60547,3 + 644.4445,3.600683,3 + 614.3267,0.6870103,3 + 645.5776,1.867147,3 + 654.6205,4.423994,3 + 692.8177,1.993502,3 + 708.7716,2.477404,3 + 728.2538,2.476002,3 + 755.4572,3.501919,3 + 778.621,2.18979,3 + 785.3195,1.743106,3 + 784.5526,1.346341,3 + 785.7797,1.974449,3 + 787.5695,1.416916,3 + 784.4503,1.4051,3 + 782.5583,1.548533,3 + 779.4391,1.255069,3 + 775.604,1.452504,3 + 776.0643,1.739155,3 + 781.2288,2.003658,3 + 791.558,2.376166,3 + 794.8305,1.215703,3 + 790.2285,1.457595,3 + 788.5922,1.549223,3 + 777.0869,0.305099,3 + 717.4133,-3.12269,3 + 620.5139,-2.686603,3 + 644.4445,1.54447,3 + 1016.479,0.8481472,3 + 962.2321,-0.9291403,3 + 847.3507,-1.475364,3 + 747.673,-0.2668786,3 + 676.963,-0.3898878,3 + 602.3846,-0.3104959,3 + 600,-0.1901872,3 + 600,0.1421087,3 + 644.4445,0.9691319,3 + 658.5208,5.586625,3 + 644.4445,10.10435,3 + 770.7463,12.22105,3 + 927.217,10.38821,3 + 1058.376,12.88986,3 + 1195.672,14.52883,3 + 1370.653,24.36733,3 + 1588.996,29.57337,3 + 1850.804,44.95491,3 + 2070.22,25.92677,3 + 2149.734,8.226243,3 + 1319.83,16.38028,3 + 1416.364,49.23381,3 + 1559.182,49.06653,3 + 1710.518,65.96037,3 + 1919.854,106.5468,3 + 2084.814,43.9015,3 + 2166.125,47.40614,3 + 1477.623,84.04178,3 + 1568.573,75.32056,3 + 1632.52,51.08742,3 + 1672.844,42.69801,3 + 1694.081,22.06184,3 + 1716.868,46.75986,3 + 1754.409,48.50185,3 + 1799.228,62.44069,3 + 1858.482,78.40761,3 + 1900.06,34.26859,3 + 1927.36,55.25987,3 + 1337.101,81.45631,3 + 1385.247,97.38922,3 + 1429.335,76.56412,3 + 1463.264,73.28956,3 + 1495.965,77.56803,3 + 1528.196,76.33263,3 + 1558.654,76.35077,3 + 1587.647,75.73126,3 + 1612.448,66.08598,3 + 1634.75,70.53711,3 + 1654.379,59.56525,3 + 1669.87,58.48478,3 + 1687.604,69.47137,3 + 1707.072,66.88885,3 + 1722.079,55.75189,3 + 1724.041,21.08878,3 + 1712.486,6.930377,3 + 1696.472,4.276927,3 + 1677.568,-3.706191,3 + 1660.694,10.34586,3 + 1651.074,20.23409,3 + 1643.645,17.34347,3 + 1632.816,8.011366,3 + 1618.776,5.67132,3 + 1603.688,3.707242,3 + 1588.144,3.373533,3 + 1571.404,-0.8783412,3 + 1555.752,6.147068,3 + 1543.593,9.695271,3 + 1532.576,9.228716,3 + 1522.379,11.73368,3 + 1509.777,1.065055,3 + 1489.946,-10.28071,3 + 1465.427,-12.51891,3 + 1440.021,-12.71381,3 + 1402.846,-16.25399,3 + 1355.514,-15.46913,3 + 1313.435,-14.94506,3 + 1291.697,11.92974,3 + 1290.622,22.9257,3 + 1291.334,16.68974,3 + 1292.651,24.62087,3 + 1298.683,29.66311,3 + 1308.639,35.86757,3 + 1329.033,59.74829,3 + 1361.923,73.65525,3 + 1400.414,80.50338,3 + 1437.67,75.37047,3 + 1474.187,83.83059,3 + 1510.207,79.0104,3 + 1541.698,74.4771,3 + 1566.836,62.39557,3 + 1586.464,59.38128,3 + 1599.685,43.04843,3 + 1606.496,39.10833,3 + 1607.544,24.1147,3 + 1602.614,18.94668,3 + 1599.308,29.22934,3 + 1598.395,26.77416,3 + 1592.524,12.49185,3 + 1582.703,13.13161,3 + 1570.221,3.125345,3 + 1548.953,-14.38402,3 + 1520.766,-17.64579,3 + 1492.177,-15.95768,3 + 1453.188,-19.0262,3 + 1405.211,-17.32,3 + 1359.907,-15.5539,3 + 1311.877,-14.40117,3 + 1259.963,-13.38175,3 + 1212.524,-12.87038,3 + 1177.001,-12.74935,3 + 1155.424,-1.723226,3 + 1141.801,-0.260747,3 + 1134.492,12.46988,3 + 1133.995,15.73124,3 + 1130.65,5.669389,3 + 1126.767,14.28826,3 + 1128.648,19.20252,3 + 1133.216,20.79155,3 + 1142.795,31.54515,3 + 1160.919,42.30621,3 + 1179.715,34.65625,3 + 1197.906,42.59779,3 + 1221.082,49.09034,3 + 1245.937,49.3044,3 + 1271.692,54.20898,3 + 1300.591,60.77997,3 + 1329.168,56.62835,3 + 1354.789,55.80923,3 + 1375.788,46.10873,3 + 1385.73,25.64256,3 + 1386.025,18.74092,3 + 1383.688,17.9726,3 + 1379.388,12.89893,3 + 1372.698,10.80366,3 + 1364.207,7.388607,3 + 1349.334,-6.829912,3 + 1327.031,-12.3538,3 + 1289.95,-14.04064,3 + 1243.626,-13.43234,3 + 1200.889,-12.65873,3 + 1162.021,-12.30316,3 + 1138.523,0.8973355,3 + 1130.394,9.3073,3 + 1135.07,31.08614,3 + 1156.795,50.95563,3 + 1189.187,59.67162,3 + 1226.563,67.66388,3 + 1268.951,78.01559,3 + 1312.414,76.58404,3 + 1356.025,85.13309,3 + 1401.126,87.58305,3 + 1444.898,88.26737,3 + 1487.286,90.28471,3 + 1527.847,89.14961,3 + 1565.344,86.64429,3 + 1597.481,76.86526,3 + 1626.864,82.09353,3 + 1642.073,31.50566,3 + 1639.99,23.92768,3 + 1637.76,30.81757,3 + 1638.123,32.71453,3 + 1642.126,43.46971,3 + 1650.376,47.85925,3 + 1656.905,38.26996,3 + 1663.717,49.5445,3 + 1672.006,44.13668,3 + 1679.073,46.09537,3 + 1685.71,43.32407,3 + 1691.084,42.26889,3 + 1696.646,44.54321,3 + 1703.364,46.98836,3 + 1710.511,46.79175,3 + 1716.906,45.01366,3 + 1717.444,26.1797,3 + 1711.129,20.26562,3 + 1704.439,24.31491,3 + 1696.458,15.16069,3 + 1684.38,9.138308,3 + 1669.212,3.496205,3 + 1653.412,6.050759,3 + 1636.148,-2.083723,3 + 1620.402,10.29929,3 + 1606.523,3.2822,3 + 1590.468,2.226402,3 + 1576.711,10.1251,3 + 1568.824,20.93763,3 + 1567.413,31.03271,3 + 1569.711,33.10635,3 + 1572.452,32.69432,3 + 1574.655,31.5523,3 + 1572.747,19.22354,3 + 1565.035,12.21235,3 + 1556.195,15.0088,3 + 1543.351,-1.151437,3 + 1523.306,-7.844097,3 + 1498.451,-15.2105,3 + 1471.473,-14.222,3 + 1443.514,-17.75576,3 + 1418.028,-8.075694,3 + 1395.819,-9.842525,3 + 1378.085,3.328753,3 + 1367.149,8.02681,3 + 1360.404,14.89146,3 + 1361.842,31.14586,3 + 1371.771,39.49014,3 + 1387.436,48.75327,3 + 1406.608,51.37,3 + 1428.548,59.16101,3 + 1453.08,61.76308,3 + 1479.238,67.222,3 + 1503.811,59.92773,3 + 1525.214,60.14183,3 + 1544.184,54.53143,3 + 1562.268,59.49051,3 + 1582.313,63.16959,3 + 1599.873,53.45661,3 + 1613.429,51.63828,3 + 1621.181,35.03048,3 + 1616.371,9.457516,3 + 1600.061,-3.788047,3 + 1581.856,2.248221,3 + 1572.667,24.77247,3 + 1572.022,30.03358,3 + 1574.01,33.46582,3 + 1578.242,37.671,3 + 1584.06,39.13469,3 + 1589.837,38.06779,3 + 1595.385,38.90419,3 + 1601.216,39.5349,3 + 1606.859,38.81017,3 + 1614.638,47.36164,3 + 1624.701,47.38615,3 + 1636,52.69853,3 + 1647.057,47.73088,3 + 1657.59,52.09483,3 + 1669.158,52.50356,3 + 1683.198,62.20206,3 + 1702.491,73.03305,3 + 1723.463,70.75262,3 + 1743.683,73.13956,3 + 1762.667,68.86513,3 + 1777.58,60.39309,3 + 1789.188,58.30213,3 + 1797.921,50.87263,3 + 1806.855,60.13579,3 + 1817.388,58.0382,3 + 1823.299,43.58347,3 + 1816.582,10.14859,3 + 1802.529,14.92394,3 + 1786.299,1.025387,3 + 1768.927,9.511108,3 + 1751.623,0.3174438,3 + 1732.894,3.221305,3 + 1714.636,1.037209,3 + 1696.606,3.044764,3 + 1683.345,16.9832,3 + 1676.05,23.35215,3 + 1669.494,19.07921,3 + 1660.667,14.90462,3 + 1649.65,10.84701,3 + 1637.733,11.08645,3 + 1623.559,2.431441,3 + 1610.325,13.43634,3 + 1600.115,11.95773,3 + 1593.007,23.21765,3 + 1593.733,37.80044,3 + 1600.921,45.08272,3 + 1610.755,47.47602,3 + 1621.087,47.78857,3 + 1627.616,35.45415,3 + 1628.436,28.78426,3 + 1624.513,19.24914,3 + 1617.298,17.2322,3 + 1609.13,15.51832,3 + 1601.445,18.32353,3 + 1596.178,23.1551,3 + 1595.479,33.32108,3 + 1600.276,41.6428,3 + 1609.909,50.18336,3 + 1618.373,38.57851,3 + 1622.498,36.17999,3 + 1621.987,23.06949,3 + 1614.45,12.16186,3 + 1598.261,-5.880579,3 + 1576.576,-6.21808,3 + 1557.216,0.2066689,3 + 1540.557,1.06763,3 + 1523.776,-0.7704601,3 + 1505.168,-4.783222,3 + 1484.424,-7.280366,3 + 1461.786,-10.48103,3 + 1437.992,-10.87021,3 + 1412.439,-15.4868,3 + 1386.16,-13.11512,3 + 1361.533,-11.51401,3 + 1337.054,-12.97312,3 + 1311.675,-13.94429,3 + 1284.644,-14.70514,3 + 1260.877,-6.438118,3 + 1239.233,-12.14887,3 + 1213.585,-13.36887,3 + 1189.711,-8.318381,3 + 1167.449,-12.13369,3 + 1133.834,-11.54234,3 + 1098.11,-11.47418,3 + 1073.161,-9.736206,3 + 1051.866,-8.969399,3 + 1043.845,17.9187,3 + 1059.793,42.8426,3 + 1091.15,54.27356,3 + 1132.423,69.97617,3 + 1179.849,74.85709,3 + 1224.723,70.31767,3 + 1266.425,73.1416,3 + 1304.474,66.09874,3 + 1339.956,71.33346,3 + 1376.07,72.68569,3 + 1408.422,65.08088,3 + 1436.595,64.42775,3 + 1462.377,61.2652,3 + 1487.568,65.8431,3 + 1513.982,68.2971,3 + 1540.825,70.66122,3 + 1565.277,63.87906,3 + 1586.142,61.8507,3 + 1603.258,53.73509,3 + 1610.003,28.49205,3 + 1602.412,5.785827,3 + 1591.718,17.46236,3 + 1587.728,27.60659,3 + 1590.347,39.33879,3 + 1599.711,50.57925,3 + 1614.356,58.24709,3 + 1631.714,61.5585,3 + 1649.959,63.41554,3 + 1667.223,60.33664,3 + 1682.902,59.92071,3 + 1697.641,58.86283,3 + 1708.402,47.30275,3 + 1712.889,37.3675,3 + 1714.622,37.78582,3 + 1716.933,39.62757,3 + 1720.386,42.15772,3 + 1725.639,46.5316,3 + 1733.472,52.14337,3 + 1742.568,52.02161,3 + 1752.026,54.51895,3 + 1760.92,50.98923,3 + 1773.2,68.27187,3 + 1792.224,77.96797,3 + 1821.486,110.3905,3 + 1859.212,115.6734,3 + 1886.512,75.2928,3 + 1904.73,83.84886,3 + 1920.543,68.10039,3 + 1923.083,32.01192,3 + 1906.866,-6.502386,3 + 1369.067,-8.091158,3 + 1347.198,-16.18642,3 + 1322.599,-15.63903,3 + 1300.348,-10.72464,3 + 1291.3,42.13477,3 + 1295.232,54.72806,3 + 1305.844,78.21381,3 + 1323.205,92.89117,3 + 1342.943,94.77242,3 + 1363.46,101.6814,3 + 1385.072,105.6614,3 + 1401.614,77.6887,3 + 1414.802,90.22686,3 + 1429.796,90.92907,3 + 1445.416,97.26785,3 + 1460.968,94.02265,3 + 1474.025,85.8418,3 + 1482.309,68.04903,3 + 1486.554,63.08653,3 + 1491.151,71.01434,3 + 1497.039,71.83271,3 + 1507.27,98.90955,3 + 1520.142,90.28288,3 + 1531.712,93.81809,3 + 1542.735,89.45779,3 + 1550.501,75.71756,3 + 1555.763,75.2889,3 + 1560.967,76.44486,3 + 1565.573,72.56293,3 + 1568.879,69.08176,3 + 1571.598,69.47919,3 + 1572.166,55.82536,3 + 1571.677,62.81889,3 + 1571.921,60.4342,3 + 1570.689,53.40608,3 + 1566.415,40.77371,3 + 1555.499,10.54896,3 + 1539.664,8.183149,3 + 1524.034,9.895695,3 + 1510.967,22.06216,3 + 1500.463,23.95686,3 + 1491.063,27.36668,3 + 1482.349,26.82351,3 + 1476.999,46.35995,3 + 1477.996,64.20844,3 + 1481.899,64.05076,3 + 1485.909,65.5948,3 + 1490.075,65.75693,3 + 1495.259,72.5956,3 + 1502.116,77.00091,3 + 1508.6,71.68607,3 + 1514.263,73.26437,3 + 1521.178,80.59914,3 + 1529.15,81.26859,3 + 1536.368,77.57661,3 + 1542.686,77.1497,3 + 1547,66.23773,3 + 1548.115,57.8325,3 + 1546.481,49.11549,3 + 1544.408,54.76034,3 + 1543.166,53.98143,3 + 1541.073,49.1928,3 + 1539.361,55.99929,3 + 1538.862,56.49809,3 + 1538.393,56.0927,3 + 1540.417,72.0712,3 + 1545.18,73.70837,3 + 1546.256,49.76416,3 + 1542.735,44.97318,3 + 1535.145,23.71458,3 + 1523.252,17.02971,3 + 1509.617,11.41548,3 + 1496.003,15.4281,3 + 1487.171,38.66481,3 + 1482.3,38.17532,3 + 1480.637,57.24352,3 + 1481.762,54.72427,3 + 1482.73,56.49815,3 + 1483.307,52.52861,3 + 1482.72,49.56577,3 + 1481.508,48.64921,3 + 1480.187,48.71376,3 + 1478.955,48.95982,3 + 1477.576,47.62597,3 + 1477.849,58.67931,3 + 1479.013,53.03189,3 + 1479.307,53.63831,3 + 1480.021,55.61882,3 + 1480.793,54.11613,3 + 1481.361,54.51465,3 + 1483.004,60.71709,3 + 1484.578,54.38765,3 + 1485.42,56.56187,3 + 1485.889,52.28399,3 + 1486.613,58.18631,3 + 1488.002,56.44076,3 + 1489.87,61.34771,3 + 1490.917,51.78019,3 + 1491.102,56.30661,3 + 1492.227,57.52043,3 + 1493.675,58.47193,3 + 1495.113,57.72102,3 + 1495.445,51.99366,3 + 1494.271,48.60529,3 + 1489.625,30.71955,3 + 1480.001,17.82528,3 + 1467.472,12.0361,3 + 1457.623,32.14432,3 + 1450.424,26.50847,3 + 1441.191,19.21676,3 + 1431.459,22.39477,3 + 1422.754,23.97624,3 + 1414.069,21.42962,3 + 1406.89,31.4945,3 + 1401.579,31.19041,3 + 1395.554,26.72908,3 + 1387.563,19.29863,3 + 1377.782,15.70328,3 + 1368.803,22.63366,3 + 1361.243,22.56006,3 + 1353.398,20.18481,3 + 1347.96,34.80918,3 + 1349.799,59.43176,3 + 1356.929,64.2579,3 + 1365.889,70.86021,3 + 1376.755,76.60091,3 + 1387.504,72.27655,3 + 1395.348,62.18171,3 + 1402.557,70.15619,3 + 1408.826,58.08114,3 + 1414.47,67.74133,3 + 1420.152,59.29419,3 + 1424.652,61.93027,3 + 1429.249,60.66118,3 + 1431.322,48.02657,3 + 1430.774,45.73412,3 + 1426.217,24.6445,3 + 1410.704,-15.22193,3 + 1391.456,1.596369,3 + 1375.386,-1.242421,3 + 1360.089,4.432325,3 + 1342.327,-12.48885,3 + 1315.958,-15.63675,3 + 1278.253,-14.49595,3 + 1226.61,-12.92336,3 + 1157.421,-11.01548,3 + 1084.691,-10.37803,3 + 1016.333,-9.222387,3 + 953.2953,-8.877071,3 + 891.1482,-8.744204,3 + 1132.584,-10.29824,3 + 1027.589,-7.797905,3 + 906.3764,-7.333625,3 + 778.9708,-6.812672,3 + 640.4005,-6.574084,3 + 725.2108,-4.330684,3 + 600,-6.607558,3 + 974.2606,0.2646341,3 + 678.2445,-2.214189,3 + 600,-2.06674,3 + 600,-2.121689,3 + 600,-1.457825,3 + 600,-0.0909586,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,2.38E-07,3 + 600,-2.38E-07,3 + 600,2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,-2.38E-07,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,4.77E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,2.38E-07,3 + 644.4445,0.07269168,3 + 644.4445,0.5636628,3 + 644.4445,6.32637,3 + 909.8743,8.952326,3 + 612.8438,0.4596145,3 + 1049.945,0.5363288,3 + 644.4445,1.307286,3 + 644.4445,1.506667,3 + 644.4445,1.191484,3 + 644.4445,1.223324,3 + 644.5549,1.372464,3 + 645.5549,2.282104,3 + 647.3238,2.434664,3 + 660.2452,2.209997,3 + 681.7216,2.61131,3 + 706.7773,2.741129,3 + 730.1458,2.619758,3 + 748.145,2.314906,3 + 760.0593,2.050172,3 + 764.6102,1.540037,3 + 765.2238,1.621832,3 + 763.9455,1.326239,3 + 764.4057,1.815315,3 + 767.3715,1.615054,3 + 764.6102,1.172328,3 + 763.6898,1.813547,3 + 765.7863,1.513745,3 + 764.7125,1.459806,3 + 763.4852,1.49177,3 + 760.6218,1.268719,3 + 717.6179,-2.408862,3 + 665.5632,0.2176919,3 + 624.9115,-1.213306,3 + 1023.406,-0.02850914,3 + 644.4445,2.188613,3 + 998.4866,-0.7567296,3 + 913.1129,-0.6905825,3 + 792.6539,-1.726186,3 + 682.2707,-0.2418582,3 + 619.2075,-0.1684604,3 + 644.4445,0.6611562,3 + 646.427,1.844816,3 + 674.444,1.06398,3 + 698.6438,1.278553,3 + 843.8422,6.181966,3 + 645.6003,6.826957,3 + 727.7936,6.854918,3 + 867.4923,13.15338,3 + 1035.213,14.05835,3 + 1166.934,11.57775,3 + 1302.747,18.54018,3 + 1484.631,24.88181,3 + 1734.831,42.28856,3 + 2034.273,49.13046,3 + 2212.783,14.95125,3 + 1365.991,14.98481,3 + 1435.985,36.59709,3 + 1555.953,48.97858,3 + 1705.628,64.5892,3 + 1887.01,84.50237,3 + 2010.176,29.41932,3 + 1359.912,69.16082,3 + 1460.599,91.42927,3 + 1564.59,85.87419,3 + 1639.38,57.33976,3 + 1678.83,35.33801,3 + 1693.723,19.23966,3 + 1709.133,37.07459,3 + 1753.812,70.30568,3 + 1809.11,58.7817,3 + 1828.497,10.1565,3 + 1245.703,51.546,3 + 1279.657,74.22597,3 + 1325.282,88.26819,3 + 1368.083,72.68974,3 + 1405.977,80.60335,3 + 1446.416,85.91576,3 + 1481.576,70.02934,3 + 1508.876,66.10561,3 + 1538.958,82.82529,3 + 1572.196,80.56322,3 + 1601.915,75.8309,3 + 1627.751,71.48734,3 + 1648.79,62.65011,3 + 1666.484,62.48646,3 + 1683.574,62.6969,3 + 1701.953,69.27721,3 + 1717.592,55.01025,3 + 1723.154,34.47604,3 + 1716.396,10.84506,3 + 1701.523,4.702551,3 + 1681.102,-8.599273,3 + 1661.836,7.633382,3 + 1652.243,23.09983,3 + 1646.547,20.57926,3 + 1637.236,10.19999,3 + 1622.242,0.4904656,3 + 1602.922,-4.652774,3 + 1584.731,3.380548,3 + 1570.49,7.09161,3 + 1557.458,6.66973,3 + 1543.848,4.555008,3 + 1531.689,10.66433,3 + 1519.437,3.691454,3 + 1503.61,-1.150481,3 + 1485.728,-3.026744,3 + 1464.379,-11.14701,3 + 1436.985,-17.6633,3 + 1401.435,-16.52778,3 + 1357.637,-15.3913,3 + 1312.307,-14.65012,3 + 1287.908,11.86469,3 + 1286,20.54327,3 + 1286.619,18.54342,3 + 1288.244,23.31835,3 + 1295.069,32.82963,3 + 1308.289,41.42417,3 + 1326.36,47.51019,3 + 1350.341,60.05747,3 + 1386.146,84.80302,3 + 1424.275,71.51812,3 + 1459.61,82.11712,3 + 1496.731,82.10949,3 + 1531.165,78.98655,3 + 1560.709,71.02921,3 + 1584.879,65.1485,3 + 1601.875,49.84313,3 + 1609.842,36.42356,3 + 1612.555,32.75125,3 + 1610.258,19.61487,3 + 1605.542,24.35468,3 + 1602.197,23.91504,3 + 1596.433,15.96346,3 + 1585.846,7.36155,3 + 1572.707,6.84079,3 + 1554.569,-8.548178,3 + 1529.58,-14.25133,3 + 1502.374,-15.33138,3 + 1473.287,-18.2294,3 + 1433.115,-16.61605,3 + 1379.361,-15.28753,3 + 1322.517,-14.32261,3 + 1269.65,-13.59477,3 + 1223.823,-13.03917,3 + 1191.054,-10.34762,3 + 1167.623,-10.96569,3 + 1146.087,-7.865382,3 + 1138.617,20.75992,3 + 1139.92,11.95193,3 + 1135.07,6.090739,3 + 1128.836,8.454925,3 + 1127.815,18.23122,3 + 1133.229,23.74462,3 + 1145.025,33.94183,3 + 1162.007,37.24741,3 + 1180.266,38.54793,3 + 1199.371,41.02165,3 + 1220.437,45.36328,3 + 1244.338,50.5095,3 + 1270.631,54.25564,3 + 1298.159,56.81184,3 + 1326.924,60.92234,3 + 1355.084,58.48366,3 + 1378.461,50.37475,3 + 1393.267,35.86261,3 + 1398.198,22.63688,3 + 1395.484,13.71113,3 + 1386.67,4.619095,3 + 1373.732,1.322395,3 + 1360.028,1.926163,3 + 1347.05,2.909883,3 + 1327.864,-13.99705,3 + 1303.439,-10.30259,3 + 1270.98,-13.94411,3 + 1227.45,-13.10693,3 + 1189.361,-12.86395,3 + 1163.257,-9.064267,3 + 1149.096,6.519079,3 + 1145.415,14.67137,3 + 1153.382,34.60891,3 + 1178.546,57.754,3 + 1216.998,71.03598,3 + 1263.134,83.27469,3 + 1314.765,93.22186,3 + 1365.711,89.68562,3 + 1406.138,70.3726,3 + 1441.432,80.56233,3 + 1480.152,86.0248,3 + 1517.623,82.35265,3 + 1553.777,87.54527,3 + 1590.871,91.02081,3 + 1619.381,63.71481,3 + 1634.092,47.46525,3 + 1638.526,29.794,3 + 1635.489,22.06191,3 + 1635.758,40.95305,3 + 1643.712,48.7066,3 + 1653.788,49.15121,3 + 1663.139,47.23022,3 + 1672.597,50.53967,3 + 1682.109,48.42113,3 + 1690.426,47.30361,3 + 1696.001,39.47346,3 + 1699.468,40.3076,3 + 1704.479,45.37587,3 + 1710.861,45.75566,3 + 1718.881,52.00259,3 + 1722.791,31.61168,3 + 1716.893,16.77742,3 + 1706.844,16.1372,3 + 1696.579,15.30738,3 + 1686.61,16.48245,3 + 1676.655,14.68511,3 + 1666.323,14.48469,3 + 1653.439,5.125021,3 + 1638.015,4.899573,3 + 1622.054,2.485665,3 + 1605.65,2.586072,3 + 1589.635,3.008597,3 + 1576.482,11.31122,3 + 1568.972,20.98672,3 + 1568.045,32.59629,3 + 1571.82,36.49885,3 + 1575.689,33.22871,3 + 1577.006,28.33649,3 + 1576.509,27.30095,3 + 1573.043,18.44022,3 + 1566.083,15.48969,3 + 1553.253,-1.0913,3 + 1533.543,-6.647263,3 + 1512.571,-5.314623,3 + 1489.597,-12.72277,3 + 1465.037,-10.23271,3 + 1440.626,-12.70623,3 + 1416.577,-9.706091,3 + 1395.107,-6.353202,3 + 1377.024,-1.41299,3 + 1362.729,3.233414,3 + 1354.829,16.14577,3 + 1363.078,49.1428,3 + 1386.616,61.25877,3 + 1414.32,64.14809,3 + 1440.303,59.41497,3 + 1460.953,50.86452,3 + 1479.574,55.51258,3 + 1498.37,53.43364,3 + 1516.938,56.92963,3 + 1538.501,65.29128,3 + 1562.402,67.20255,3 + 1585.376,65.22421,3 + 1607.168,66.15616,3 + 1622.363,45.26455,3 + 1626.448,29.70588,3 + 1619.663,8.417274,3 + 1605.892,5.471342,3 + 1590.294,1.554001,3 + 1574.104,2.731438,3 + 1564.27,21.70022,3 + 1562.819,29.79327,3 + 1568.34,44.64818,3 + 1577.866,43.57754,3 + 1587.66,46.50829,3 + 1597.844,45.86784,3 + 1605.354,38.47025,3 + 1610.205,37.56776,3 + 1614.96,38.60074,3 + 1622.027,45.92914,3 + 1631.029,45.93453,3 + 1640.622,48.91043,3 + 1652.001,53.17495,3 + 1664.657,54.63203,3 + 1677.662,55.84564,3 + 1692.656,63.26057,3 + 1711.21,70.51211,3 + 1732.478,75.57997,3 + 1753.544,72.63683,3 + 1769.828,60.5629,3 + 1783.451,64.80178,3 + 1796.429,59.79764,3 + 1807.943,60.86138,3 + 1820.33,64.59172,3 + 1828.176,44.81462,3 + 1821.163,8.214087,3 + 1804.249,6.292377,3 + 1787.871,9.134424,3 + 1770.714,2.376011,3 + 1754.109,10.06567,3 + 1738.806,6.212786,3 + 1721.286,1.067402,3 + 1704.721,8.612881,3 + 1690.95,10.14219,3 + 1679.624,16.43083,3 + 1669.144,12.42631,3 + 1658.987,16.84797,3 + 1647.85,8.391995,3 + 1632.507,1.645216,3 + 1616.008,3.606684,3 + 1600.128,2.947272,3 + 1589.487,20.32802,3 + 1587.647,31.78459,3 + 1590.159,34.78584,3 + 1594.271,37.37839,3 + 1600.692,42.96344,3 + 1610.513,49.539,3 + 1619.219,40.11499,3 + 1623.559,35.45469,3 + 1622.551,22.18125,3 + 1616.573,18.38556,3 + 1609.412,17.73681,3 + 1601.727,16.13419,3 + 1594.458,18.62502,3 + 1590.616,27.14091,3 + 1592.551,37.74634,3 + 1599.214,43.24936,3 + 1607.383,43.47301,3 + 1616.519,47.3689,3 + 1620.966,28.29967,3 + 1614.678,11.12828,3 + 1600.491,1.117563,3 + 1577.759,-15.98362,3 + 1550.498,-12.94688,3 + 1526.638,-6.817096,3 + 1505.168,-6.72456,3 + 1484.263,-5.809709,3 + 1462.727,-8.948511,3 + 1443.058,-1.342418,3 + 1426.667,-0.6651244,3 + 1410.316,-1.713572,3 + 1393.038,-3.54139,3 + 1376.876,0.7599344,3 + 1361.493,-1.957383,3 + 1339.513,-15.69704,3 + 1313.126,-13.22394,3 + 1287.062,-14.71945,3 + 1250.061,-13.29444,3 + 1211.717,-13.18758,3 + 1184.632,-12.68648,3 + 1156.754,-13.87198,3 + 1125.974,-13.35509,3 + 1094.321,-12.72246,3 + 1054.539,-11.65611,3 + 1026.366,1.78571,3 + 1031.707,34.37691,3 + 1059.625,52.05185,3 + 1095.194,54.60882,3 + 1132.853,61.3746,3 + 1177.447,76.69508,3 + 1222.979,69.77629,3 + 1261.898,65.92332,3 + 1296.198,62.50776,3 + 1331.935,74.62606,3 + 1370.172,74.38905,3 + 1403.021,64.03122,3 + 1430.133,61.57874,3 + 1454.451,58.83109,3 + 1481.079,71.86363,3 + 1508.285,63.87067,3 + 1533.275,68.35617,3 + 1556.074,59.77805,3 + 1575.649,60.55231,3 + 1590.562,46.38965,3 + 1598.476,38.60023,3 + 1600.316,26.62489,3 + 1595.412,16.02007,3 + 1589.635,23.31708,3 + 1594.485,51.32585,3 + 1609.062,56.67459,3 + 1626.676,63.39441,3 + 1644.746,60.32769,3 + 1660.559,57.70242,3 + 1675.096,57.71563,3 + 1688.518,55.43426,3 + 1701.389,57.32327,3 + 1710.565,43.53574,3 + 1713.427,35.47276,3 + 1715.402,40.61037,3 + 1719.432,43.12147,3 + 1724.444,44.58424,3 + 1731.376,50.66751,3 + 1740.593,53.71496,3 + 1749.258,49.65441,3 + 1754.552,42.17929,3 + 1757.723,42.34054,3 + 1768.121,69.52338,3 + 1794.468,103.9193,3 + 1825.61,91.68179,3 + 1855.813,105.6374,3 + 1881.836,79.81264,3 + 1897.179,67.01525,3 + 1905.496,53.63717,3 + 1906.692,39.33886,3 + 1889.011,-19.16266,3 + 1849.122,-24.79765,3 + 1807.889,-24.43617,3 + 1779.689,-0.7561536,3 + 1284.092,17.17696,3 + 1284.102,58.07148,3 + 1292.093,58.99236,3 + 1304.082,80.69597,3 + 1321.862,92.27543,3 + 1340.809,90.74892,3 + 1359.844,96.99959,3 + 1378.966,95.45564,3 + 1393.216,73.59466,3 + 1402.928,72.61659,3 + 1413.785,82.11748,3 + 1426.51,85.63467,3 + 1440.927,94.76996,3 + 1455.95,92.36811,3 + 1470.416,94.86768,3 + 1480.725,70.45586,3 + 1486.985,72.58999,3 + 1494.017,76.40392,3 + 1505.187,99.43295,3 + 1520.278,103.0791,3 + 1537.327,115.3624,3 + 1552.584,95.87924,3 + 1562.453,84.82603,3 + 1568.948,76.54655,3 + 1573.946,76.64169,3 + 1578.063,71.93213,3 + 1579.726,61.67735,3 + 1579.57,60.54532,3 + 1578.23,54.0312,3 + 1574.601,45.59658,3 + 1570.894,52.8693,3 + 1567.725,48.39549,3 + 1563.177,43.51645,3 + 1555.069,25.0616,3 + 1541.767,9.581061,3 + 1527.692,18.39748,3 + 1515.007,16.44184,3 + 1501.92,14.32027,3 + 1490.76,26.46716,3 + 1483.728,37.81801,3 + 1478.436,35.96482,3 + 1475.345,50.22443,3 + 1478.28,71.72651,3 + 1485.41,76.1095,3 + 1492.481,72.78746,3 + 1498.937,73.78825,3 + 1505.128,72.46352,3 + 1511.525,76.31317,3 + 1517.471,70.96622,3 + 1522.88,74.19914,3 + 1528.641,74.2482,3 + 1535.39,81.57578,3 + 1541.278,70.22089,3 + 1544.848,68.2123,3 + 1547.264,63.6499,3 + 1547.371,54.11656,3 + 1545.171,49.12331,3 + 1542.52,50.89368,3 + 1539.84,48.48135,3 + 1537.816,54.52997,3 + 1536.886,54.98994,3 + 1537.346,63.06376,3 + 1541.503,78.29755,3 + 1548.662,82.82697,3 + 1550.482,45.99143,3 + 1544.809,35.92283,3 + 1533.756,11.44688,3 + 1518.009,5.243145,3 + 1503.915,19.64205,3 + 1492.609,20.55502,3 + 1483.464,31.21258,3 + 1479.277,49.16108,3 + 1478.886,53.42761,3 + 1479.62,55.8742,3 + 1479.786,50.1337,3 + 1479.678,54.25177,3 + 1479.933,52.29718,3 + 1480.578,56.65665,3 + 1480.842,50.10637,3 + 1480.598,53.63382,3 + 1479.004,41.93355,3 + 1476.324,46.8269,3 + 1474.172,44.68207,3 + 1472.274,48.00023,3 + 1472.079,54.57672,3 + 1472.597,52.24992,3 + 1474.455,62.71901,3 + 1477.018,56.80586,3 + 1479.698,63.90294,3 + 1482.955,60.77087,3 + 1485.019,57.28467,3 + 1487.298,62.45473,3 + 1490.075,60.72274,3 + 1492.403,60.23314,3 + 1493.763,55.25238,3 + 1493.205,48.80926,3 + 1492.892,56.64178,3 + 1493.557,54.70619,3 + 1494.144,56.28391,3 + 1494.682,54.51154,3 + 1494.007,48.99399,3 + 1492.853,51.47742,3 + 1488.951,32.13356,3 + 1476.187,-2.118674,3 + 1457.887,-2.126604,3 + 1443.636,19.47982,3 + 1434.912,28.30535,3 + 1428.173,29.93163,3 + 1421.649,28.65341,3 + 1414.167,23.54668,3 + 1406.841,28.56202,3 + 1399.642,23.36224,3 + 1392.786,29.56185,3 + 1386.477,25.6082,3 + 1378.163,17.51092,3 + 1369.077,20.2835,3 + 1360.695,20.3895,3 + 1353.369,25.12762,3 + 1349.398,37.92805,3 + 1351.149,56.04457,3 + 1358.328,68.17207,3 + 1369.312,78.50098,3 + 1382.037,80.05802,3 + 1392.443,67.88512,3 + 1400.953,71.3244,3 + 1408.376,63.24284,3 + 1413.912,61.8568,3 + 1417.932,55.47812,3 + 1421.189,58.15731,3 + 1423.85,52.57276,3 + 1425.894,55.04035,3 + 1428.72,57.47088,3 + 1430.657,50.33347,3 + 1427.302,27.01298,3 + 1417.443,12.22586,3 + 1403.036,-0.1684303,3 + 1384.237,-11.87013,3 + 1363.287,-11.63743,3 + 1342.004,-13.53146,3 + 1318.618,-16.01462,3 + 1282.605,-14.39375,3 + 1220.908,-12.12208,3 + 1141.722,-10.68284,3 + 1074.528,-10.48296,3 + 1022.054,-9.141874,3 + 960.7875,-8.731186,3 + 1216.514,-10.74907,3 + 1109.274,-9.523954,3 + 1005.743,-8.101731,3 + 906.0809,-7.618393,3 + 784.7748,-6.123598,3 + 636.8536,-6.884468,3 + 741.9532,-5.764419,3 + 836.1458,-0.8582449,3 + 600,-4.675195,3 + 952.2463,0.009875298,3 + 664.0984,-1.178708,3 + 600,-1.123972,3 + 600,-0.2031865,3 + 600,-0.6548967,3 + 600,-0.000296116,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,2.38E-07,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 644.4445,0.2542183,3 + 644.4445,3.043099,3 + 644.4944,3.76886,3 + 862.1945,7.244804,3 + 644.4445,2.008217,3 + 644.4445,1.282092,3 + 644.4445,1.102336,3 + 644.4445,1.300048,3 + 644.4445,1.259131,3 + 644.4445,1.073095,3 + 645.6724,3.006216,3 + 618.264,-0.3244839,3 + 647.7556,5.489882,3 + 701.8685,2.742796,3 + 722.4244,2.271123,3 + 743.2361,2.935951,3 + 762.5648,2.234797,3 + 772.9451,2.039693,3 + 780.2573,1.936579,3 + 786.3934,1.940598,3 + 781.9448,0.7246585,3 + 771.7178,1.247691,3 + 769.2634,1.590314,3 + 768.7009,1.456245,3 + 766.1954,1.364901,3 + 764.2012,1.504721,3 + 766.3488,1.831629,3 + 768.0362,1.460694,3 + 768.0362,1.645372,3 + 773.3542,2.075679,3 + 774.5814,1.194392,3 + 764.559,0.7873244,3 + 745.3326,0.1385179,3 + 715.4191,-0.332602,3 + 677.2729,-0.594053,3 + 635.803,-0.5641029,3 + 981.9337,-3.01793,3 + 839.9738,-0.6091862,3 + 727.9713,-1.361682,3 + 620.287,-0.3443129,3 + 600,-0.198132,3 + 600,-0.2130547,3 + 644.4445,1.156704,3 + 644.4445,2.928335,3 + 840.5137,7.855536,3 + 645.6799,4.915875,3 + 718.7428,7.940886,3 + 919.598,20.71529,3 + 1104.653,9.702165,3 + 1177.315,7.127035,3 + 1343.756,30.38393,3 + 1513.062,9.906143,3 + 1007.81,36.38819,3 + 1161.267,39.11203,3 + 1278.037,27.3871,3 + 1383.305,40.41537,3 + 1511.207,46.64371,3 + 1596.608,19.454,3 + 1075.369,38.91386,3 + 1144.645,51.12838,3 + 1236.03,71.91323,3 + 1345.194,84.24624,3 + 1462.489,97.86935,3 + 1569.923,84.68086,3 + 1640.951,52.99866,3 + 1686.982,50.89439,3 + 1708.258,14.60182,3 + 1146.06,-3.260405,3 + 1143.091,26.43259,3 + 1164.452,55.55766,3 + 1202.272,69.78938,3 + 1248.732,83.18002,3 + 1301.019,92.7276,3 + 1354.342,94.76001,3 + 1401.919,84.77892,3 + 1438.704,69.75992,3 + 1467.953,66.90834,3 + 1497.591,74.95674,3 + 1527.323,71.09368,3 + 1554.516,70.7477,3 + 1580.204,69.72466,3 + 1607.732,80.51578,3 + 1633.071,65.80466,3 + 1652.807,64.51868,3 + 1671.334,64.05013,3 + 1689.244,64.65747,3 + 1706.105,62.52456,3 + 1720.534,57.92768,3 + 1723.772,23.39667,3 + 1706.911,-12.77224,3 + 1685.898,7.341925,3 + 1671.979,9.75246,3 + 1662.279,21.29147,3 + 1658.504,29.84188,3 + 1653.587,17.03524,3 + 1638.794,-4.186825,3 + 1617.648,-4.962307,3 + 1597.884,-0.8135309,3 + 1580.257,0.750226,3 + 1562.563,-1.659951,3 + 1548.537,11.91162,3 + 1540.033,15.42424,3 + 1535.115,23.01572,3 + 1531.448,19.15309,3 + 1516.118,-12.86069,3 + 1492.284,-7.591835,3 + 1467.55,-15.70515,3 + 1435.373,-17.46522,3 + 1392.904,-16.13951,3 + 1347.977,-15.4994,3 + 1312.535,-15.2666,3 + 1292.543,4.540256,3 + 1286.511,16.9544,3 + 1287.236,22.45613,3 + 1293.9,33.18174,3 + 1303.345,30.53206,3 + 1313.502,35.92642,3 + 1331.949,54.6626,3 + 1359.692,64.28005,3 + 1396.867,85.87479,3 + 1437.925,80.98814,3 + 1474.281,77.60077,3 + 1509.642,83.28379,3 + 1543.23,76.9175,3 + 1570.127,65.98427,3 + 1588.654,52.43436,3 + 1600.84,46.78295,3 + 1606.805,32.59529,3 + 1605.65,23.18912,3 + 1600.504,19.00929,3 + 1594.781,20.86993,3 + 1590.656,23.9784,3 + 1587.486,23.77216,3 + 1582.017,16.08064,3 + 1572.358,9.474892,3 + 1555.805,-6.293793,3 + 1535.33,-3.614192,3 + 1510.986,-17.70457,3 + 1482.517,-15.38637,3 + 1448.754,-17.3886,3 + 1398.587,-15.64723,3 + 1329.799,-13.74466,3 + 1273.492,-14.25001,3 + 1241.248,-13.40315,3 + 1205.269,-12.6376,3 + 1165.85,-12.21276,3 + 1135.151,-12.03583,3 + 1120.372,9.679996,3 + 1120.828,20.11432,3 + 1124.12,16.3987,3 + 1126.471,18.06844,3 + 1130.287,20.00859,3 + 1140.336,33.27053,3 + 1156.029,34.36275,3 + 1172.272,35.92491,3 + 1186.231,29.97521,3 + 1199.088,34.3232,3 + 1218.381,47.54738,3 + 1244.808,54.75484,3 + 1274.137,58.20295,3 + 1304.004,59.67457,3 + 1330.377,51.92756,3 + 1355.218,58.4916,3 + 1371.65,30.14645,3 + 1375.962,24.95364,3 + 1378.676,25.82015,3 + 1379.214,18.80646,3 + 1374.31,10.07271,3 + 1365.201,6.415627,3 + 1355.783,8.765409,3 + 1346.029,5.078839,3 + 1331.237,-5.104489,3 + 1306.892,-15.03027,3 + 1262.704,-13.15916,3 + 1218.341,-13.36216,3 + 1187.789,-12.82549,3 + 1158.756,-12.40262,3 + 1140.404,3.783212,3 + 1146.194,39.93061,3 + 1168.859,45.34202,3 + 1196.469,54.62985,3 + 1230.943,66.16975,3 + 1267.379,64.01351,3 + 1307.698,81.99072,3 + 1350.247,75.75098,3 + 1391.923,86.11143,3 + 1438.113,95.74863,3 + 1481.187,83.65627,3 + 1522.688,98.04447,3 + 1564.162,89.97185,3 + 1600.074,86.14787,3 + 1628.449,69.52667,3 + 1645.015,49.09846,3 + 1644.383,11.60987,3 + 1636.161,22.72835,3 + 1636.631,41.04108,3 + 1644.504,48.4262,3 + 1655.387,52.34411,3 + 1667.573,54.19073,3 + 1678.724,50.02793,3 + 1685.71,40.58485,3 + 1688.384,35.37016,3 + 1693.812,50.70958,3 + 1703.243,50.27459,3 + 1708.913,38.13729,3 + 1712.647,43.88169,3 + 1719.594,50.16351,3 + 1728.071,50.19448,3 + 1728.891,23.06607,3 + 1720.413,16.42023,3 + 1711.479,20.75814,3 + 1701.872,13.39018,3 + 1689.687,10.86072,3 + 1670.811,-9.679937,3 + 1650.241,3.8373,3 + 1635.127,7.068507,3 + 1619.717,2.065735,3 + 1602.99,1.803795,3 + 1589.608,12.44946,3 + 1580.634,15.81511,3 + 1574.991,22.96172,3 + 1575.542,36.00331,3 + 1579.236,33.46876,3 + 1581.762,32.42493,3 + 1582.434,27.48787,3 + 1578.618,17.52039,3 + 1570.772,13.83211,3 + 1562.375,15.1992,3 + 1551.869,6.441697,3 + 1534.793,-5.906759,3 + 1512.289,-10.30744,3 + 1486.695,-15.03363,3 + 1458.857,-16.87653,3 + 1432.135,-12.41042,3 + 1407.629,-11.31777,3 + 1384.171,-10.03571,3 + 1369.003,10.59928,3 + 1365.08,20.52546,3 + 1370.091,36.15165,3 + 1380.638,36.95204,3 + 1393.63,44.27267,3 + 1412.734,56.37016,3 + 1440.572,72.8304,3 + 1467.684,57.35134,3 + 1491.37,65.70872,3 + 1518.066,69.83893,3 + 1541.604,58.79247,3 + 1561.153,59.73059,3 + 1579.048,55.58046,3 + 1595.762,57.87779,3 + 1611.924,55.62059,3 + 1625.601,51.2132,3 + 1629.645,23.90257,3 + 1619.246,2.099785,3 + 1602.936,3.149794,3 + 1587.781,5.188667,3 + 1575.542,12.07873,3 + 1570.329,27.7652,3 + 1573.903,40.86924,3 + 1581.722,42.21673,3 + 1589.689,42.11393,3 + 1595.95,37.23134,3 + 1600.491,36.9001,3 + 1604.898,37.1901,3 + 1610.715,42.10384,3 + 1618.87,45.72244,3 + 1628.409,47.67087,3 + 1640.151,54.35364,3 + 1653.022,52.86154,3 + 1665.678,55.06348,3 + 1679.879,59.78596,3 + 1695.907,63.27319,3 + 1713.198,66.3249,3 + 1731.269,68.31712,3 + 1748.775,66.57999,3 + 1763.997,62.08349,3 + 1779.34,69.02579,3 + 1793.984,61.35672,3 + 1805.202,57.85924,3 + 1812.82,48.92445,3 + 1819.578,55.46923,3 + 1825.906,48.01827,3 + 1821.056,13.10841,3 + 1805.565,6.840103,3 + 1788.691,6.806072,3 + 1772.488,8.286536,3 + 1756.487,6.550629,3 + 1737.798,-2.249373,3 + 1717.807,0.735312,3 + 1700.731,6.919925,3 + 1685.226,5.433849,3 + 1672.436,15.57636,3 + 1664.362,21.22834,3 + 1658.961,24.37656,3 + 1650.268,9.386177,3 + 1634.71,0.04979086,3 + 1614.544,-6.336586,3 + 1598.381,12.57801,3 + 1590.025,18.29753,3 + 1584.288,20.81376,3 + 1584.234,36.87918,3 + 1596.608,62.62403,3 + 1613.859,54.64594,3 + 1622.457,34.95087,3 + 1624.271,32.25559,3 + 1624.661,30.22398,3 + 1624.849,31.59747,3 + 1621.624,18.55824,3 + 1611.064,6.372733,3 + 1598.986,12.73059,3 + 1591.785,22.058,3 + 1592.013,37.18653,3 + 1598.704,43.85127,3 + 1607.947,46.47419,3 + 1618.319,48.64143,3 + 1621.906,24.24795,3 + 1615.068,13.35699,3 + 1603.111,6.432739,3 + 1588.722,4.500189,3 + 1572.573,-0.115675,3 + 1553.629,-4.783992,3 + 1532.751,-6.315992,3 + 1514.761,3.077488,3 + 1500.399,3.732917,3 + 1482.651,-7.154562,3 + 1463.519,-1.135713,3 + 1440.935,-16.81416,3 + 1414.158,-12.81345,3 + 1390.943,-7.845296,3 + 1368.922,-10.04424,3 + 1346.889,-8.254794,3 + 1323.471,-13.71456,3 + 1296.762,-14.93286,3 + 1265.673,-14.07961,3 + 1236.546,-11.97013,3 + 1207.23,-12.98112,3 + 1174.139,-12.54039,3 + 1146.973,-10.93499,3 + 1124.362,-10.41155,3 + 1093.918,-11.0197,3 + 1057.509,-10.56761,3 + 1037.759,6.854196,3 + 1046.344,37.0987,3 + 1073.335,48.63685,3 + 1107.407,56.2469,3 + 1148.129,68.77713,3 + 1192.304,70.15498,3 + 1231.884,63.05749,3 + 1264.786,57.78709,3 + 1296.44,63.90317,3 + 1332.419,73.914,3 + 1371.166,76.68737,3 + 1406.42,69.01247,3 + 1434.862,60.98241,3 + 1458.468,57.80101,3 + 1482.987,66.75755,3 + 1509.669,67.63638,3 + 1535.465,67.33713,3 + 1560.091,67.14167,3 + 1583.253,65.62291,3 + 1599.443,46.44219,3 + 1606.684,37.13651,3 + 1604.884,16.46138,3 + 1593.343,4.168659,3 + 1584.033,23.15694,3 + 1588.211,48.71681,3 + 1600.585,51.11957,3 + 1617.836,66.74638,3 + 1638.794,65.8931,3 + 1658.92,66.52989,3 + 1676.91,60.87619,3 + 1691.756,57.56428,3 + 1704.331,54.48838,3 + 1710.861,37.12782,3 + 1711.546,34.04327,3 + 1710.229,29.95877,3 + 1712.661,47.48108,3 + 1721.461,53.3045,3 + 1730.906,50.78699,3 + 1740.176,53.73991,3 + 1751.045,57.7492,3 + 1757.951,40.23434,3 + 1759.778,39.63506,3 + 1772.192,80.07209,3 + 1797.208,88.74728,3 + 1826.631,100.872,3 + 1858.271,102.1546,3 + 1885.397,88.15533,3 + 1904.448,74.06339,3 + 1916.432,62.34672,3 + 1919.401,39.03856,3 + 1902.46,-15.46535,3 + 1863.511,-25.07789,3 + 1823.273,-21.13098,3 + 1791.996,-14.05958,3 + 1770.969,13.06777,3 + 1286.498,48.0114,3 + 1294.058,67.24074,3 + 1306.597,75.67068,3 + 1322.628,88.41093,3 + 1342.258,98.59779,3 + 1363.062,99.24053,3 + 1378.535,73.31172,3 + 1388.825,73.33134,3 + 1401.598,89.55661,3 + 1416.387,87.50754,3 + 1432.163,98.61768,3 + 1449.387,99.54861,3 + 1465.027,93.16014,3 + 1475.385,71.32512,3 + 1479.141,55.54146,3 + 1483.825,77.69683,3 + 1492.922,83.2123,3 + 1504.218,93.1139,3 + 1517.188,96.03044,3 + 1530.509,98.30925,3 + 1543.136,94.77704,3 + 1552.281,79.19598,3 + 1557.964,74.84485,3 + 1563.461,79.22526,3 + 1569.339,78.43729,3 + 1574.591,76.46247,3 + 1577.222,62.67551,3 + 1577.242,60.19896,3 + 1575.687,52.56088,3 + 1572.498,49.43146,3 + 1569.329,52.1115,3 + 1564.947,41.14471,3 + 1554.462,12.68271,3 + 1539.967,14.31148,3 + 1525.981,14.02893,3 + 1511.818,11.48827,3 + 1497.929,13.95845,3 + 1487.532,30.92048,3 + 1481.38,38.22163,3 + 1478.329,48.67535,3 + 1478.162,55.10718,3 + 1479.678,58.7858,3 + 1483.914,71.81812,3 + 1490.819,75.78394,3 + 1498.35,77.02534,3 + 1505.099,72.51969,3 + 1511.202,74.43957,3 + 1517.911,77.50984,3 + 1525.814,83.25037,3 + 1532.593,72.12448,3 + 1537.16,70.83592,3 + 1542.236,76.25439,3 + 1544.985,57.17952,3 + 1544.32,55.29839,3 + 1544.476,62.22943,3 + 1544.496,54.4649,3 + 1542.745,51.09521,3 + 1539.38,44.02723,3 + 1535.742,48.7935,3 + 1534.999,61.51359,3 + 1537.258,67.46387,3 + 1540.965,71.03705,3 + 1547.939,88.8294,3 + 1549.738,39.71848,3 + 1538.647,8.12237,3 + 1524.67,20.05622,3 + 1512.2,15.72904,3 + 1500.873,25.39976,3 + 1490.78,21.78333,3 + 1482.358,34.10342,3 + 1478.485,47.99138,3 + 1477.977,53.7555,3 + 1477.801,49.90863,3 + 1479.15,62.92201,3 + 1481.243,54.62078,3 + 1481.116,49.8967,3 + 1480.324,50.58609,3 + 1479.63,50.35303,3 + 1477.321,40.75677,3 + 1473.565,41.27589,3 + 1470.426,43.86224,3 + 1468.401,47.451,3 + 1466.954,46.9868,3 + 1467.658,60.07456,3 + 1470.602,60.51458,3 + 1475.668,73.382,3 + 1481.801,67.88359,3 + 1484.911,56.28338,3 + 1485.674,54.24988,3 + 1486.251,55.29283,3 + 1486.691,53.52103,3 + 1486.77,53.17738,3 + 1486.721,52.76431,3 + 1487.024,55.30242,3 + 1487.669,54.89172,3 + 1489.019,59.68992,3 + 1490.731,57.32771,3 + 1492.951,63.0985,3 + 1495.279,58.38214,3 + 1494.584,45.10869,3 + 1487.405,18.9328,3 + 1470.866,-10.28922,3 + 1452.928,8.639071,3 + 1440.017,15.75091,3 + 1429.552,21.4329,3 + 1422.607,34.86482,3 + 1417.512,31.21866,3 + 1412.484,34.53926,3 + 1407.31,29.69863,3 + 1401.344,29.30284,3 + 1395.877,31.73983,3 + 1390.937,31.57141,3 + 1385.724,29.53498,3 + 1378.741,20.95574,3 + 1371.111,25.03376,3 + 1363.707,21.31329,3 + 1355.785,21.27985,3 + 1349.271,28.11312,3 + 1347.491,46.42329,3 + 1354.044,73.73386,3 + 1364.627,69.82935,3 + 1374.183,70.02986,3 + 1382.281,63.41209,3 + 1390.106,70.01546,3 + 1398.41,67.56463,3 + 1404.523,59.0325,3 + 1409.433,61.78816,3 + 1413.688,56.11639,3 + 1417.443,59.66835,3 + 1421.248,57.04577,3 + 1423.116,49.10121,3 + 1423.185,46.9263,3 + 1420.573,33.6044,3 + 1411.956,11.98207,3 + 1397.891,1.452831,3 + 1383.142,6.65378,3 + 1367.718,-3.068421,3 + 1348.968,-9.861969,3 + 1325.562,-16.11518,3 + 1284.092,-14.13637,3 + 1214.697,-11.85796,3 + 1141.781,-11.37294,3 + 1079.028,-10.51758,3 + 1008.215,-8.903414,3 + 930.7995,-8.72839,3 + 857.0523,-8.130159,3 + 789.291,-8.076338,3 + 726.7427,-8.857965,3 + 898.0064,-7.569747,3 + 769.9961,-6.515765,3 + 649.1603,-7.147186,3 + 784.9226,-4.621058,3 + 892.3317,-0.6631382,3 + 608.6652,-4.717086,3 + 600,-6.420379,3 + 606.6129,-1.587289,3 + 600,-0.7637906,3 + 600,-0.8728795,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,-2.38E-07,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,-2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,0,3 + 600,2.38E-07,3 + 600,0,3 + 600,0,3 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 644.4445,0.1401868,4 + 644.4445,4.115141,4 + 723.5632,6.148651,4 + 878.7474,0.996314,4 + 644.4445,5.992946,4 + 614.2244,0.8715067,4 + 1054.623,0.2505918,4 + 1032.132,1.002764,4 + 644.4445,1.849404,4 + 644.4445,1.160477,4 + 644.4445,1.181648,4 + 646.017,3.313942,4 + 655.8477,2.47095,4 + 673.5912,1.926634,4 + 697.6755,3.281785,4 + 729.89,2.964346,4 + 753.4118,2.586441,4 + 769.7236,2.314295,4 + 781.3311,2.144838,4 + 788.3876,1.845007,4 + 788.5922,1.371453,4 + 785.2173,1.424252,4 + 785.7797,1.820931,4 + 787.4161,1.552712,4 + 785.6775,1.431036,4 + 786.0355,1.792017,4 + 787.007,1.504555,4 + 785.3195,1.483458,4 + 784.6548,1.617746,4 + 783.939,1.474823,4 + 778.5699,1.072223,4 + 772.178,1.335513,4 + 761.5421,0.5722067,4 + 687.8577,-4.410039,4 + 1043.288,-1.19836,4 + 644.4445,2.357286,4 + 1002.265,-0.5849216,4 + 866.3327,-2.573789,4 + 732.1096,-0.3810852,4 + 661.4896,-0.2707293,4 + 600,-0.2227266,4 + 644.5211,1.784207,4 + 615.0692,-0.02452826,4 + 600,-0.1297612,4 + 644.4445,0.6420181,4 + 666.7973,4.922177,4 + 644.4445,8.587686,4 + 693.5847,6.82707,4 + 836.9651,12.78135,4 + 995.8392,12.11045,4 + 1190.252,24.46093,4 + 1341.456,7.883049,4 + 1453.439,21.57428,4 + 1009.962,38.10797,4 + 1173.415,42.39235,4 + 1323.306,42.99743,4 + 1399.727,9.089857,4 + 937.9701,32.31821,4 + 1005.795,44.4572,4 + 1088.015,53.16226,4 + 1172.164,54.589,4 + 1265.583,73.96272,4 + 1376.655,88.71164,4 + 1496.45,101.4458,4 + 1616.172,105.6161,4 + 1668.748,5.478724,4 + 1119.606,4.928539,4 + 1124.671,35.79109,4 + 1140.175,30.06963,4 + 1160.328,48.58438,4 + 1189.106,53.33678,4 + 1224.844,69.88008,4 + 1267.755,76.89536,4 + 1310.533,75.63843,4 + 1352.249,80.32765,4 + 1392.649,77.89688,4 + 1429.045,74.28435,4 + 1463.412,76.94868,4 + 1497.873,79.46665,4 + 1531.421,78.96201,4 + 1561.273,72.11664,4 + 1587.056,69.5541,4 + 1609.479,64.13884,4 + 1630.585,67.9769,4 + 1650.429,62.38124,4 + 1668.137,63.00897,4 + 1684.42,59.49305,4 + 1702.746,72.43027,4 + 1718.317,51.68219,4 + 1722.2,31.7786,4 + 1710.807,-2.869109,4 + 1690.453,-1.062667,4 + 1673.296,7.073107,4 + 1662.924,21.68794,4 + 1658.853,28.46225,4 + 1655.051,22.32484,4 + 1643,-0.4019394,4 + 1623.586,-3.330098,4 + 1604.414,-0.449111,4 + 1587.123,1.748246,4 + 1569.496,-2.081304,4 + 1552.944,4.46729,4 + 1542.894,18.06239,4 + 1538.031,20.74931,4 + 1530.547,9.303829,4 + 1514.237,-7.018807,4 + 1492.526,-7.514885,4 + 1469.149,-12.08818,4 + 1442.722,-15.80163,4 + 1404.525,-18.5696,4 + 1361.667,-17.84917,4 + 1327.529,-17.22158,4 + 1306.449,4.262201,4 + 1300.712,18.62459,4 + 1305.858,33.81105,4 + 1310.184,16.66183,4 + 1310.09,21.90794,4 + 1317.331,37.01147,4 + 1331.747,42.52515,4 + 1353.015,57.90654,4 + 1383.016,70.18417,4 + 1420.392,83.79029,4 + 1463.21,92.30715,4 + 1502.401,78.82739,4 + 1533.557,72.45618,4 + 1561.099,71.36134,4 + 1584.785,63.23337,4 + 1600.343,46.89187,4 + 1607.934,37.95928,4 + 1609.116,25.84165,4 + 1606.496,25.15568,4 + 1602.882,22.27899,4 + 1597.401,18.59029,4 + 1590.777,18.05532,4 + 1581.158,8.168066,4 + 1565.438,-2.385445,4 + 1544.224,-9.294456,4 + 1521.841,-6.390518,4 + 1499.485,-9.735824,4 + 1475.06,-12.31793,4 + 1438.369,-16.93306,4 + 1388.027,-15.79407,4 + 1334.837,-14.71431,4 + 1282.574,-13.81453,4 + 1232.73,-12.99281,4 + 1186.607,-12.35547,4 + 1153.933,-9.757157,4 + 1138.281,3.688477,4 + 1130.166,6.484842,4 + 1124.469,9.161757,4 + 1119.579,8.190273,4 + 1116.717,13.7386,4 + 1121.178,25.33872,4 + 1131.012,26.74716,4 + 1139.974,23.89797,4 + 1153.758,39.14996,4 + 1173.145,38.69012,4 + 1197.14,52.6565,4 + 1222.573,44.61408,4 + 1247.831,55.10344,4 + 1274.231,50.24755,4 + 1302.956,64.64877,4 + 1334.958,62.68685,4 + 1361.681,53.49527,4 + 1382.828,49.63818,4 + 1393.616,25.17934,4 + 1392.595,15.85793,4 + 1388.47,16.01408,4 + 1382.331,9.760792,4 + 1375.264,12.98514,4 + 1368.573,10.51227,4 + 1357.852,1.127345,4 + 1330.887,-15.09141,4 + 1287.693,-14.09798,4 + 1235.995,-12.79959,4 + 1189.24,-12.6493,4 + 1159.75,-9.993802,4 + 1143.158,2.208033,4 + 1140.753,21.87768,4 + 1152.361,35.92246,4 + 1169.356,35.89918,4 + 1193.446,55.35715,4 + 1227.665,64.36838,4 + 1263.591,64.05273,4 + 1304.172,82.13965,4 + 1350.765,86.74195,4 + 1399.89,97.1329,4 + 1448.015,91.67886,4 + 1490.363,87.14861,4 + 1527.78,82.59544,4 + 1565.411,93.79819,4 + 1601.888,84.35611,4 + 1629.712,69.70103,4 + 1643.765,40.32787,4 + 1644.598,25.34709,4 + 1642.677,30.8411,4 + 1647.957,50.22522,4 + 1657.926,47.7007,4 + 1664.052,37.76743,4 + 1668.701,43.12788,4 + 1677.555,53.11346,4 + 1688.478,51.41099,4 + 1698.5,51.11005,4 + 1706.414,44.9026,4 + 1708.993,32.6828,4 + 1711.102,43.46721,4 + 1718.371,51.58891,4 + 1728.098,53.19771,4 + 1735.42,43.84155,4 + 1735.339,26.82102,4 + 1726.916,13.36045,4 + 1716.691,19.60794,4 + 1707.085,14.90211,4 + 1695.128,10.50889,4 + 1682.271,10.91309,4 + 1663.878,-8.54956,4 + 1641.629,-3.117419,4 + 1624.07,5.537962,4 + 1609.197,4.835527,4 + 1592.752,-0.4371243,4 + 1577.893,9.274105,4 + 1570.101,22.16969,4 + 1571.847,40.37538,4 + 1576.751,32.78808,4 + 1579.035,32.08871,4 + 1581.749,34.41856,4 + 1583.133,27.87005,4 + 1576.012,6.219936,4 + 1561.421,2.702191,4 + 1547.059,6.234878,4 + 1534.363,7.427535,4 + 1520.672,2.441157,4 + 1500.385,-12.44278,4 + 1474.039,-15.19112,4 + 1448.391,-10.99723,4 + 1411.539,-16.18276,4 + 1375.237,-10.13539,4 + 1357.798,3.94146,4 + 1352.424,22.40654,4 + 1358.053,35.1076,4 + 1371.085,44.18404,4 + 1390.486,54.94989,4 + 1412.506,53.94309,4 + 1436.112,62.30517,4 + 1459.811,56.89755,4 + 1483.336,64.70206,4 + 1510.018,69.77424,4 + 1535.801,65.16431,4 + 1559.043,64.80313,4 + 1580.728,62.89471,4 + 1598.556,54.45824,4 + 1613.254,54.38581,4 + 1626.582,51.40335,4 + 1634.75,38.01902,4 + 1625.87,-5.708029,4 + 1605.435,-1.783062,4 + 1588.211,3.508634,4 + 1575.972,13.76913,4 + 1574.601,38.87314,4 + 1576.764,25.41134,4 + 1576.509,31.0111,4 + 1580.378,39.14088,4 + 1587.109,40.92192,4 + 1594.552,42.17134,4 + 1602.21,42.3647,4 + 1609.64,42.14173,4 + 1617.876,45.85305,4 + 1627.146,46.51075,4 + 1637.773,51.51218,4 + 1651.907,59.8804,4 + 1668.016,60.05737,4 + 1682.956,57.66072,4 + 1698.594,64.39252,4 + 1714.26,59.62116,4 + 1729.025,63.08392,4 + 1743.723,61.17331,4 + 1759.321,68.29936,4 + 1774.275,60.68742,4 + 1787.293,62.94482,4 + 1799.157,57.8984,4 + 1810.375,61.97612,4 + 1821.647,59.47066,4 + 1829.144,48.76117,4 + 1827.075,23.35892,4 + 1814.029,6.402053,4 + 1794.32,-2.592016,4 + 1771.735,-4.909734,4 + 1752.711,9.03825,4 + 1737.462,7.341007,4 + 1721.273,4.683862,4 + 1704.694,4.982325,4 + 1688.128,3.812349,4 + 1674.545,14.56831,4 + 1666.793,23.51281,4 + 1662.064,24.63626,4 + 1654.984,14.94999,4 + 1635.731,-15.84564,4 + 1610.997,-4.315684,4 + 1594.74,9.832749,4 + 1588.036,26.32848,4 + 1590.885,41.41418,4 + 1599,44.31393,4 + 1604.347,32.80503,4 + 1609.748,45.03335,4 + 1620.321,50.97161,4 + 1629.86,42.54122,4 + 1630.612,21.65488,4 + 1626.286,25.14294,4 + 1622.995,24.88023,4 + 1619.287,23.46855,4 + 1613.268,16.73643,4 + 1607.706,24.57117,4 + 1610.003,43.01642,4 + 1616.519,39.12624,4 + 1621.208,37.39355,4 + 1624.634,35.22969,4 + 1627.952,37.3392,4 + 1624.594,12.60667,4 + 1610.554,0.67381,4 + 1592.725,-0.8326931,4 + 1573.647,-3.764307,4 + 1556.383,4.200647,4 + 1540.61,-0.05308342,4 + 1524.676,2.95549,4 + 1506.149,-7.869933,4 + 1484.451,-6.838203,4 + 1463.063,-7.529763,4 + 1441.418,-8.017014,4 + 1419.842,-7.811407,4 + 1398.13,-8.783758,4 + 1377.628,-5.129324,4 + 1358.174,-6.480177,4 + 1330.162,-16.99247,4 + 1294.518,-16.31282,4 + 1264.088,-13.97139,4 + 1238.279,-14.27002,4 + 1205.672,-13.58043,4 + 1175.577,-8.778869,4 + 1153.073,-12.24656,4 + 1128.594,-11.99461,4 + 1095.57,-10.9451,4 + 1059.322,-10.66192,4 + 1040.862,6.466439,4 + 1046.922,32.05039,4 + 1070.836,46.81862,4 + 1105.593,59.44982,4 + 1144.421,60.56117,4 + 1185.277,69.68872,4 + 1225.22,63.52172,4 + 1258.217,56.72657,4 + 1292.812,72.29202,4 + 1331.452,72.35333,4 + 1366.88,68.45086,4 + 1393.737,51.85317,4 + 1417.343,62.23331,4 + 1449.023,79.29785,4 + 1486.588,84.81449,4 + 1520.337,72.50204,4 + 1545.353,61.22117,4 + 1565.129,58.47639,4 + 1583.576,59.16581,4 + 1597.441,45.13127,4 + 1602.506,30.88554,4 + 1600.343,21.15592,4 + 1593.612,15.33718,4 + 1586.666,19.96346,4 + 1587.996,42.56586,4 + 1600.719,58.4817,4 + 1618.574,61.39739,4 + 1637.37,63.87596,4 + 1655.736,62.19775,4 + 1672.167,59.32374,4 + 1687.886,61.68731,4 + 1702.047,55.59766,4 + 1710.914,44.22459,4 + 1715.953,42.70472,4 + 1719.231,38.34271,4 + 1721.891,40.7861,4 + 1725.048,40.4108,4 + 1728.743,43.06327,4 + 1735.541,52.16247,4 + 1744.341,51.14399,4 + 1753.557,54.70576,4 + 1763.137,53.5337,4 + 1773.912,60.3172,4 + 1790.531,76.9442,4 + 1814.647,91.22339,4 + 1844.93,104.5918,4 + 1876.086,99.57632,4 + 1900.511,82.78519,4 + 1919.052,79.66685,4 + 1921.161,18.51604,4 + 1896.575,-24.33028,4 + 1849.753,-24.22952,4 + 1809.65,-2.914296,4 + 1783.061,-16.90625,4 + 1283.055,17.62789,4 + 1281.148,47.45848,4 + 1288.122,63.8209,4 + 1299.731,73.06547,4 + 1314.197,81.21303,4 + 1332.148,94.84081,4 + 1352.77,99.70914,4 + 1374.041,103.1989,4 + 1391.799,84.65783,4 + 1404.758,79.80271,4 + 1417.834,88.10941,4 + 1433.956,100.3611,4 + 1452.571,106.4864,4 + 1469.02,91.7476,4 + 1477.869,64.48682,4 + 1482.045,65.40362,4 + 1486.32,65.86734,4 + 1494.467,89.83578,4 + 1506.898,93.77473,4 + 1519.525,93.85491,4 + 1531.702,93.87712,4 + 1542.725,89.39608,4 + 1552.242,86.8752,4 + 1559.959,80.07738,4 + 1564.449,67.961,4 + 1567.041,68.89693,4 + 1570.2,72.11388,4 + 1572.977,67.08501,4 + 1574.21,62.75511,4 + 1574.21,59.41563,4 + 1573.936,60.99732,4 + 1572.4,51.27596,4 + 1568.263,44.06831,4 + 1559.519,21.27699,4 + 1545.63,10.24199,4 + 1530.617,12.39669,4 + 1515.183,5.857883,4 + 1498.36,2.09445,4 + 1486.505,33.94199,4 + 1482.349,47.08876,4 + 1480.05,44.51606,4 + 1479.463,57.02282,4 + 1482.084,63.77707,4 + 1487.796,76.23621,4 + 1495.289,75.71186,4 + 1501.538,70.15787,4 + 1507.818,77.17599,4 + 1514.703,75.15352,4 + 1520.865,74.11327,4 + 1527.096,76.84986,4 + 1532.231,68.53654,4 + 1536.417,71.96849,4 + 1540.564,69.12055,4 + 1543.713,66.52328,4 + 1546.735,68.94624,4 + 1547.489,52.78967,4 + 1545.386,51.08469,4 + 1542.256,45.96298,4 + 1539.361,52.00807,4 + 1537.405,51.35246,4 + 1535.859,54.2338,4 + 1536.554,65.10095,4 + 1540.671,75.84949,4 + 1547.195,81.08743,4 + 1550.257,55.29021,4 + 1545.806,34.30048,4 + 1535.243,16.24277,4 + 1523.33,24.33566,4 + 1512.464,21.15258,4 + 1502.918,30.91319,4 + 1494.076,24.17211,4 + 1485.987,34.19572,4 + 1480.725,40.09128,4 + 1478.27,50.29652,4 + 1478.016,52.946,4 + 1478.182,52.7861,4 + 1478.378,53.15138,4 + 1480.079,61.90357,4 + 1482.192,55.92644,4 + 1482.075,48.81292,4 + 1479.982,43.98728,4 + 1478.104,49.7599,4 + 1476.93,47.92091,4 + 1476.646,54.91663,4 + 1477.908,57.17506,4 + 1478.681,52.18999,4 + 1479.786,59.31868,4 + 1481.165,54.03209,4 + 1482.339,58.32693,4 + 1484.236,58.61423,4 + 1487.024,64.06499,4 + 1489.743,58.70241,4 + 1491.484,58.62561,4 + 1492.824,56.57703,4 + 1493.381,54.10405,4 + 1492.256,46.44337,4 + 1490.926,52.65959,4 + 1491.445,57.45026,4 + 1492.804,57.86545,4 + 1494.702,60.97232,4 + 1495.856,53.67446,4 + 1488.354,8.644087,4 + 1473.771,9.854107,4 + 1459.911,11.31598,4 + 1449.71,29.82105,4 + 1444.35,38.53183,4 + 1441.259,42.37823,4 + 1436.486,28.24177,4 + 1429.513,28.8433,4 + 1421.864,23.41715,4 + 1414.392,28.83934,4 + 1409.071,34.798,4 + 1403.584,27.19031,4 + 1396.982,27.69853,4 + 1388.531,15.91847,4 + 1377.224,10.64097,4 + 1366.25,16.52416,4 + 1358.612,27.90209,4 + 1355.629,41.29479,4 + 1355.726,44.49744,4 + 1358.876,58.18682,4 + 1366.27,68.5884,4 + 1376.618,76.04653,4 + 1388.952,81.80117,4 + 1400.522,74.14407,4 + 1408.504,63.53102,4 + 1415.252,68.5932,4 + 1420.651,56.93834,4 + 1423.263,53.41837,4 + 1425.219,53.58304,4 + 1426.207,48.11959,4 + 1426.852,51.75898,4 + 1427.38,47.54124,4 + 1423.742,27.67442,4 + 1415.125,18.26986,4 + 1402.381,3.03742,4 + 1388.482,10.29751,4 + 1373.977,-1.384802,4 + 1355.462,-10.03899,4 + 1330.062,-15.91993,4 + 1282.331,-13.68837,4 + 1209.601,-11.78776,4 + 1130.279,-10.6761,4 + 1056.59,-9.85384,4 + 995.0887,-9.493731,4 + 932.1101,-8.854118,4 + 860.5636,-8.522646,4 + 799.4923,-8.632871,4 + 742.3431,-8.777902,4 + 916.95,-7.472395,4 + 784.6405,-6.526037,4 + 659.1023,-7.239723,4 + 802.2018,-4.796231,4 + 600,-4.862612,4 + 980.1921,3.036931,4 + 655.1318,-1.243356,4 + 600,-3.643281,4 + 600,-2.117112,4 + 600,-0.4603643,4 + 600,-2.24E-05,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,-2.38E-07,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,-2.38E-07,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,2.38E-07,4 + 600,0,4 + 600,2.38E-07,4 + 600,0,4 + 600,0,4 + 600,-2.38E-07,4 + 600,-2.38E-07,4 + 644.4445,1.714838,4 + 644.4445,1.621784,4 + 644.4445,3.298661,4 + 755.8596,3.870013,4 + 644.4445,3.134853,4 + 644.4445,1.420932,4 + 644.4445,1.825752,4 + 644.4445,1.360866,4 + 991.1098,0.8516321,4 + 644.4445,2.159252,4 + 644.4445,1.824742,4 + 644.4445,1.209069,4 + 645.8011,2.986922,4 + 651.5524,2.650311,4 + 659.7339,0.760689,4 + 685.8124,4.595871,4 + 737.2534,3.604281,4 + 762.7693,2.212489,4 + 770.3373,1.737349,4 + 772.536,1.632224,4 + 772.3826,1.47518,4 + 768.9055,1.248654,4 + 770.1327,2.003068,4 + 775.6552,1.749856,4 + 776.7802,1.519026,4 + 774.1212,1.315794,4 + 769.7236,1.307899,4 + 770.2861,1.870355,4 + 770.2861,1.245239,4 + 768.343,1.646059,4 + 768.3942,1.467183,4 + 762.5137,0.9683771,4 + 717.0042,-2.388535,4 + 628.3375,-2.716046,4 + 644.4445,1.232642,4 + 1006.313,0.3278913,4 + 950.627,-0.5628872,4 + 846.9909,-1.407126,4 + 722.4837,-1.039502,4 + 621.8163,-0.4376612,4 + 600,0.0385704,4 + 644.4445,1.879608,4 + 602.8344,0.04388237,4 + 600,-0.00674057,4 + 644.4445,1.93153,4 + 794.813,7.284958,4 + 644.8845,6.377717,4 + 738.2761,9.556376,4 + 924.2001,17.0417,4 + 1082.921,9.743132,4 + 1157.014,6.99104,4 + 775.9276,22.85481,4 + 919.729,33.17456,4 + 1086.138,42.19983,4 + 1261.492,50.43425,4 + 1375.494,19.51903,4 + 1401.449,6.091826,4 + 926.2782,23.43933,4 + 980.7605,39.51251,4 + 1054.848,47.15857,4 + 1133.927,51.68547,4 + 1226.62,71.72372,4 + 1337.942,86.13082,4 + 1457.344,97.89137,4 + 1580.828,109.5713,4 + 1657.092,36.67658,4 + 1123.368,1.461304,4 + 1122.441,25.1924,4 + 1136.454,37.02988,4 + 1161.309,52.76898,4 + 1193.459,57.73195,4 + 1230.285,68.77976,4 + 1273.533,79.75322,4 + 1318.352,79.31004,4 + 1356.562,67.54053,4 + 1392.273,77.71348,4 + 1426.908,69.05838,4 + 1460.725,80.27706,4 + 1498.424,86.01363,4 + 1534.793,81.56979,4 + 1565.21,71.81206,4 + 1590.119,67.43898,4 + 1612.582,66.8174,4 + 1634.24,67.57295,4 + 1656.032,70.10327,4 + 1677.488,69.22984,4 + 1696.042,62.52128,4 + 1711.774,61.43768,4 + 1725.102,55.68619,4 + 1731.578,37.91976,4 + 1722.254,-1.090255,4 + 1702.517,-0.3800182,4 + 1681.747,-5.168064,4 + 1664.59,11.20999,4 + 1654.514,18.04026,4 + 1645.996,15.99401,4 + 1635.436,10.42183,4 + 1621.665,4.338938,4 + 1605.22,0.5969486,4 + 1587.795,0.2512197,4 + 1570.517,0.3162355,4 + 1554.072,2.230137,4 + 1541.806,13.14601,4 + 1533.597,14.75539,4 + 1525.832,14.09572,4 + 1514.506,2.944591,4 + 1496.1,-7.84253,4 + 1471.352,-15.42717,4 + 1440.169,-20.01007,4 + 1400.468,-18.50732,4 + 1353.19,-17.0692,4 + 1315.531,-12.80798,4 + 1294.491,-3.285613,4 + 1284.173,13.58008,4 + 1289.225,37.47305,4 + 1302.015,35.04106,4 + 1311.339,28.96468,4 + 1316.942,25.44615,4 + 1328.926,47.30635,4 + 1352.921,60.59223,4 + 1385.233,74.25334,4 + 1422.945,80.9559,4 + 1461.329,81.75445,4 + 1495.643,73.77378,4 + 1525.133,71.24657,4 + 1553.333,73.6284,4 + 1578.726,65.64669,4 + 1596.568,51.4837,4 + 1607.732,45.11185,4 + 1612.851,32.04094,4 + 1610.876,21.44158,4 + 1605.126,19.07754,4 + 1598.368,17.63783,4 + 1591.677,18.84343,4 + 1582.676,9.494823,4 + 1569.455,4.294639,4 + 1552.541,-2.913902,4 + 1532.455,-5.940009,4 + 1507.855,-16.18926,4 + 1475.826,-18.23104,4 + 1433.29,-16.7917,4 + 1382.384,-15.64154,4 + 1326.494,-14.32655,4 + 1274.366,-13.89831,4 + 1227.275,-12.87859,4 + 1182.348,-12.34522,4 + 1151.286,-9.173134,4 + 1131.402,-6.310503,4 + 1119.781,8.727276,4 + 1118.289,16.43811,4 + 1118.921,13.66425,4 + 1120.828,19.48628,4 + 1124.819,18.68554,4 + 1130.757,24.36229,4 + 1141.048,29.49514,4 + 1158.46,42.48001,4 + 1180.763,43.03611,4 + 1203.146,44.87235,4 + 1225.918,46.25666,4 + 1248.597,46.92699,4 + 1272.592,52.15644,4 + 1299.516,57.51007,4 + 1329.074,62.6179,4 + 1359.343,63.1154,4 + 1380.947,40.95043,4 + 1388.403,23.98634,4 + 1388.417,19.74684,4 + 1385.165,14.44612,4 + 1379.603,12.82719,4 + 1372.187,8.792199,4 + 1363.065,7.554926,4 + 1349.723,-3.177336,4 + 1329.396,-11.0907,4 + 1300.833,-14.74182,4 + 1261.575,-13.61232,4 + 1217.468,-12.85518,4 + 1175.268,-12.22688,4 + 1141.546,-12.1833,4 + 1126.955,11.26167,4 + 1134.532,35.89684,4 + 1157.695,49.54621,4 + 1189.052,58.5972,4 + 1222.466,58.37698,4 + 1257.343,66.71474,4 + 1300.538,85.77503,4 + 1352.393,97.63816,4 + 1402.304,88.47597,4 + 1444.938,84.01994,4 + 1484.008,84.11902,4 + 1521.116,83.72038,4 + 1557.216,86.50259,4 + 1591.624,83.49979,4 + 1623.855,84.3294,4 + 1647.595,58.56056,4 + 1655.346,31.51854,4 + 1647.595,5.291959,4 + 1637.236,21.8509,4 + 1638.069,43.26761,4 + 1647.353,51.25405,4 + 1657.993,48.95843,4 + 1668.862,53.2352,4 + 1680.014,51.13348,4 + 1689.217,47.52374,4 + 1696.109,43.85042,4 + 1700.18,38.1036,4 + 1701.886,35.75303,4 + 1704.895,42.96144,4 + 1713.521,56.36014,4 + 1723.759,49.71629,4 + 1725.169,25.28842,4 + 1717.766,17.81898,4 + 1708.886,19.36817,4 + 1699.602,15.74377,4 + 1685.428,1.331335,4 + 1668.258,4.265698,4 + 1651.088,0.4824829,4 + 1632.682,-0.7735591,4 + 1616.546,7.333869,4 + 1601.297,1.405253,4 + 1587.109,10.06296,4 + 1578.108,17.9458,4 + 1571.148,16.3085,4 + 1567.669,28.97894,4 + 1571.471,40.18153,4 + 1577.49,36.66446,4 + 1581.507,34.05357,4 + 1584.664,34.14597,4 + 1581.897,14.52561,4 + 1573.567,15.4157,4 + 1560.951,-0.06234074,4 + 1539.428,-12.5987,4 + 1514.842,-9.453217,4 + 1487.81,-18.44072,4 + 1460.886,-9.728415,4 + 1437.804,-9.730576,4 + 1416.16,-6.372715,4 + 1395.067,-8.671995,4 + 1373.544,-7.898953,4 + 1360.901,15.09554,4 + 1358.859,20.97911,4 + 1363.857,35.19839,4 + 1379.617,52.60059,4 + 1405.99,68.11739,4 + 1434.069,60.73365,4 + 1456.748,55.0891,4 + 1477.304,56.83291,4 + 1499.552,62.82561,4 + 1522.835,62.77331,4 + 1543.606,57.48309,4 + 1563.611,62.81192,4 + 1585.403,65.84775,4 + 1604.911,57.73931,4 + 1619.407,51.10355,4 + 1625.279,29.70323,4 + 1619.824,12.86922,4 + 1606.134,1.337738,4 + 1587.701,-3.369208,4 + 1572.465,11.06384,4 + 1564.538,19.60567,4 + 1563.638,33.72519,4 + 1569.052,40.41961,4 + 1578.041,46.10619,4 + 1586.653,40.0111,4 + 1594.445,44.22099,4 + 1602.896,42.9819,4 + 1610.231,41.26826,4 + 1616.559,40.2604,4 + 1624.123,46.1275,4 + 1634.065,49.20351,4 + 1644.907,50.29093,4 + 1656.059,51.45343,4 + 1668.943,57.63499,4 + 1688.625,77.20282,4 + 1711.116,70.17025,4 + 1728.34,61.05583,4 + 1744.61,68.95058,4 + 1762.868,70.50829,4 + 1779.366,64.74032,4 + 1794.387,67.11285,4 + 1807.486,59.31385,4 + 1818.275,59.92589,4 + 1828.835,59.76006,4 + 1834.155,40.87052,4 + 1824.254,1.570856,4 + 1803.939,0.1671991,4 + 1785.896,8.91948,4 + 1769.089,3.76696,4 + 1750.548,1.465682,4 + 1734.198,10.69146,4 + 1720.507,10.2054,4 + 1707.327,11.65767,4 + 1695.45,14.03399,4 + 1684.931,15.71651,4 + 1675.325,16.56543,4 + 1665.933,15.82545,4 + 1654.339,8.25458,4 + 1639.587,4.160066,4 + 1622.202,-1.38369,4 + 1608.431,15.49589,4 + 1602.748,25.05814,4 + 1601.189,29.03644,4 + 1603.151,36.84112,4 + 1608.673,41.2834,4 + 1614.087,36.97735,4 + 1619.031,40.19678,4 + 1622.941,33.88109,4 + 1623.505,29.08438,4 + 1621.114,23.80924,4 + 1615.149,16.70804,4 + 1607.464,17.53648,4 + 1602.546,25.54437,4 + 1600.706,27.58181,4 + 1600.195,29.89292,4 + 1602.318,36.44426,4 + 1608.995,45.53632,4 + 1616.116,38.564,4 + 1619.327,32.86123,4 + 1617.164,20.48985,4 + 1607.571,7.451408,4 + 1591.973,-0.2941513,4 + 1573.177,-3.498985,4 + 1552.541,-6.302647,4 + 1531.81,-4.429373,4 + 1511.698,-5.13943,4 + 1493.265,-0.3575616,4 + 1477.143,0.7890692,4 + 1461.141,-0.5568328,4 + 1445.449,1.121991,4 + 1430.375,0.6806421,4 + 1410.706,-11.54041,4 + 1385.824,-13.42626,4 + 1360.619,-12.66673,4 + 1335.24,-14.07331,4 + 1309.62,-13.46232,4 + 1274.366,-13.88826,4 + 1237.862,-13.81937,4 + 1212.241,-11.44095,4 + 1184.081,-12.65552,4 + 1148.102,-11.87495,4 + 1115.508,-11.77358,4 + 1087.442,-11.19799,4 + 1054.593,-10.48865,4 + 1033.607,5.6588,4 + 1040.043,33.29015,4 + 1064.535,46.21249,4 + 1097.908,56.06443,4 + 1138.16,66.53667,4 + 1181.515,68.95843,4 + 1223.258,68.46669,4 + 1261.723,66.08852,4 + 1300.779,75.51466,4 + 1341.756,76.87059,4 + 1377.36,65.75189,4 + 1406.339,62.23019,4 + 1433.908,65.22336,4 + 1459.475,59.45428,4 + 1483.82,64.64926,4 + 1510.354,69.41556,4 + 1536.862,67.94376,4 + 1560.467,63.31855,4 + 1581.225,61.46338,4 + 1596.42,47.04777,4 + 1600.343,25.01183,4 + 1593.115,9.831497,4 + 1584.181,18.76838,4 + 1581.493,30.10958,4 + 1586.962,45.85008,4 + 1600.37,57.38508,4 + 1617.769,60.89524,4 + 1636.443,63.86408,4 + 1655.078,63.03837,4 + 1671.496,58.34701,4 + 1686.221,59.03419,4 + 1700.287,57.73484,4 + 1710.955,48.39701,4 + 1717.229,43.00974,4 + 1721.3,41.04623,4 + 1725.115,42.49238,4 + 1729.374,43.04696,4 + 1732.33,38.14999,4 + 1734.453,40.29311,4 + 1737.193,40.62325,4 + 1742.259,49.12432,4 + 1749.527,49.27705,4 + 1758.905,57.77568,4 + 1780.186,95.1664,4 + 1817.066,120.4318,4 + 1863.283,138.34,4 + 1894.667,69.34295,4 + 1907.269,68.27747,4 + 1919.079,67.84028,4 + 1917.762,16.49406,4 + 1889.951,-25.8662,4 + 1839.596,-23.89131,4 + 1797.746,-6.402427,4 + 1288.914,-15.27851,4 + 1277.128,32.77653,4 + 1281.275,63.12198,4 + 1290.283,58.78977,4 + 1302.49,81.71949,4 + 1320.926,94.45592,4 + 1342.199,101.122,4 + 1364.574,105.4511,4 + 1384.497,92.51437,4 + 1399.036,79.38459,4 + 1412.044,86.92896,4 + 1425.375,83.94568,4 + 1438.726,89.94231,4 + 1452.996,92.26556,4 + 1465.477,82.38766,4 + 1473.311,67.06986,4 + 1478.475,67.91246,4 + 1485.547,79.625,4 + 1497.763,100.7359,4 + 1512.278,96.41169,4 + 1525.707,97.44376,4 + 1538.334,94.52263,4 + 1549.249,89.58551,4 + 1557.71,81.4274,4 + 1564.057,77.99872,4 + 1569.036,74.02861,4 + 1572.312,68.13066,4 + 1575.041,71.18874,4 + 1576.86,62.82628,4 + 1576.352,56.58434,4 + 1574.357,53.18288,4 + 1571.52,50.82687,4 + 1567.755,46.73517,4 + 1562.385,39.9514,4 + 1553.406,22.98973,4 + 1541.513,20.22375,4 + 1527.653,9.152882,4 + 1512.63,11.24,4 + 1497.871,9.012047,4 + 1484.578,18.34523,4 + 1477.82,46.65918,4 + 1476.558,50.44249,4 + 1476.832,55.68708,4 + 1479.131,62.68777,4 + 1483.698,69.81506,4 + 1490.535,77.33602,4 + 1498.018,75.10793,4 + 1505.011,75.88093,4 + 1512.151,77.44696,4 + 1520.327,83.79372,4 + 1527.986,75.92196,4 + 1532.671,66.83388,4 + 1536.348,70.5734,4 + 1539.762,65.89542,4 + 1543.273,71.87601,4 + 1547.303,69.85374,4 + 1549.034,58.16096,4 + 1547.87,51.91158,4 + 1546.364,55.78762,4 + 1544.672,50.47578,4 + 1541.356,45.2815,4 + 1538.324,51.6749,4 + 1537.356,57.68959,4 + 1538.872,67.07841,4 + 1544.251,82.28827,4 + 1545.288,40.75605,4 + 1538.011,30.25864,4 + 1530.314,36.96606,4 + 1522.196,26.52944,4 + 1511.906,22.36277,4 + 1500.12,15.97792,4 + 1489.616,28.55366,4 + 1482.329,34.04303,4 + 1478.945,50.99249,4 + 1479.502,57.25879,4 + 1480.607,54.3908,4 + 1481.048,53.44007,4 + 1481.713,55.82595,4 + 1482.329,53.25982,4 + 1482.818,55.16615,4 + 1481.811,44.30854,4 + 1479.307,45.96726,4 + 1476.646,42.96669,4 + 1473.575,43.07121,4 + 1471.717,49.74657,4 + 1470.788,48.34003,4 + 1472.177,63.49163,4 + 1475.942,62.85665,4 + 1479.972,65.78904,4 + 1484.334,65.62042,4 + 1488.217,63.7094,4 + 1490.124,54.34649,4 + 1490.183,52.82955,4 + 1489.342,48.89529,4 + 1488.755,54.22676,4 + 1487.777,46.42638,4 + 1486.192,50.38337,4 + 1485.576,52.02367,4 + 1487.601,66.28146,4 + 1491.67,64.79538,4 + 1494.985,62.46672,4 + 1496.091,51.93176,4 + 1492.462,33.85468,4 + 1486.104,34.78819,4 + 1476.089,10.9714,4 + 1464.117,21.67854,4 + 1454.757,25.02648,4 + 1445.866,23.2522,4 + 1436.829,23.01534,4 + 1428.603,26.81799,4 + 1421.473,28.30663,4 + 1413.345,20.16391,4 + 1404.963,25.78935,4 + 1396.278,17.4505,4 + 1387.201,22.49283,4 + 1379.914,26.44587,4 + 1372.432,20.53219,4 + 1364.392,22.42527,4 + 1357.027,23.32439,4 + 1350.679,27.14028,4 + 1350.269,55.12245,4 + 1357.262,67.91344,4 + 1367.101,72.15673,4 + 1377.987,75.64056,4 + 1389.636,78.59641,4 + 1399.104,65.48586,4 + 1405.217,61.24613,4 + 1409.795,57.77759,4 + 1413.922,59.46923,4 + 1417.404,54.76487,4 + 1420.857,59.91445,4 + 1423.595,51.20931,4 + 1424.886,51.9877,4 + 1425.776,49.09315,4 + 1423.556,34.09339,4 + 1418.059,29.80763,4 + 1405.119,-7.826694,4 + 1385.391,-8.599997,4 + 1365.175,-11.35708,4 + 1344.4,-11.20156,4 + 1318.843,-15.60458,4 + 1278.125,-14.10385,4 + 1212.223,-11.80592,4 + 1143.825,-11.62002,4 + 1080.622,-10.19347,4 + 1005.036,-8.704713,4 + 942.2039,-9.229837,4 + 877.6898,-7.629379,4 + 796.7341,-8.281475,4 + 1005.85,-9.090136,4 + 922.6464,-8.02299,4 + 814.1037,-6.777267,4 + 680.4239,-6.171268,4 + 600,-6.54746,4 + 881.2298,-1.826855,4 + 625.3334,-5.014571,4 + 600,-5.152775,4 + 600,-4.932726,4 + 600,-1.280655,4 + 600,-0.4310925,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 + 600,0,4 \ No newline at end of file diff --git a/VectoCoreTest/TestData/Cycles/Coach Engine Only.vdri b/VectoCoreTest/TestData/Cycles/Coach Engine Only.vdri index d3eb6df5448e815c6c023dcf8d6aaf35930224be..9291db5a6c79075d9bd4fc816efd32186537b6b0 100644 --- a/VectoCoreTest/TestData/Cycles/Coach Engine Only.vdri +++ b/VectoCoreTest/TestData/Cycles/Coach Engine Only.vdri @@ -1,3952 +1,3954 @@ -<n>,<Pe> -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,2.38E-07 -600,0 -644.4445,2.329973 -644.4445,0.5693641 -644.4445,4.264177 -869.7512,7.98456 -644.4445,1.351656 -1015.31,-0.2716608 -948.6478,-0.4653716 -872.4501,-0.5719776 -644.4445,1.012361 -816.044,0.1606398 -644.4445,3.967641 -644.4445,4.3916 -645.3466,1.254886 -602.9238,0.36098 -644.4445,1.097353 -644.4445,1.476951 -645.6951,2.961375 -656.8193,3.33839 -688.8293,2.509675 -715.7259,3.104633 -743.2361,2.779576 -759.3434,2.025352 -763.0762,1.467997 -761.0308,1.383811 -757.7582,1.320618 -755.406,1.475238 -756.3265,1.681716 -753.872,1.098228 -749.1166,1.411724 -747.787,1.465289 -743.7986,1.110595 -691.6417,-3.012229 -627.2637,-0.1685431 -1049.495,-0.09707546 -644.4445,1.615664 -1026.825,0.4667768 -977.9754,-0.4151859 -906.5457,-0.4785028 -764.8557,-2.495939 -615.8789,-0.5095253 -600,-0.2679868 -644.4445,0.5701756 -644.4445,1.185031 -600,0.2967396 -646.6069,3.811063 -895.4804,7.923037 -653.8535,6.359474 -791.9158,11.55912 -900.8318,4.931076 -1007.856,14.46236 -1156.708,13.49057 -1345.086,27.20026 -1602.138,35.01208 -1888.49,46.58702 -2103.714,24.29906 -2146.359,-1.109985 -1286.033,8.800848 -1351.937,37.56419 -1494.108,56.84015 -1650.18,55.71647 -1797.949,62.99876 -1974.041,90.22348 -2191.804,115.1789 -2403.877,105.9852 -2503.301,18.33513 -1611.144,-1.709167 -1619.774,43.61679 -1655.685,42.16265 -1690.462,44.19933 -1723.907,42.2117 -1766.618,62.7349 -1823.327,70.33007 -1898.131,102.0343 -1980.033,91.64824 -2027.516,42.57878 -2040.799,27.31307 -1396.846,69.06043 -1435.803,91.8233 -1479.637,89.72998 -1511.026,58.87632 -1535.129,70.88527 -1563.544,76.08076 -1591.288,72.46291 -1615.981,69.52535 -1637.034,63.16708 -1654.957,61.31534 -1674.975,72.86595 -1695.262,64.75288 -1709.799,54.75394 -1712.769,24.54955 -1702.061,5.766651 -1685.925,4.414207 -1669.991,5.575367 -1656.502,12.07608 -1644.88,11.30247 -1634.482,15.56817 -1624.607,12.47053 -1610.151,-0.5362444 -1594.136,6.376687 -1580.163,5.485111 -1564.78,1.025784 -1550.539,8.4501 -1539.777,11.6633 -1532.066,17.71403 -1521.599,2.418658 -1504.309,-4.049212 -1481.361,-14.07779 -1453.792,-17.15281 -1423.724,-18.15207 -1385.246,-16.81612 -1337.242,-15.72801 -1293.188,-15.42869 -1281.755,38.3059 -1286.484,11.6914 -1283.596,17.9171 -1285.597,24.78118 -1291.778,29.405 -1303.359,40.06316 -1321.147,47.6144 -1343.046,53.40984 -1367.31,56.75732 -1398.372,76.35516 -1441.017,95.91759 -1491.115,106.3325 -1533.099,77.92695 -1561.824,69.6596 -1584.033,60.08042 -1597.119,41.62484 -1603.93,40.29163 -1607.558,31.45644 -1604.965,19.52167 -1600.142,23.70411 -1596.299,22.48869 -1589.192,12.48158 -1578.793,11.02395 -1566.889,6.910674 -1551.426,-1.123854 -1528.707,-15.20682 -1502.589,-11.37927 -1476.041,-16.47795 -1439.148,-17.79036 -1386.845,-16.22873 -1331.801,-15.54598 -1276.609,-14.19835 -1222.116,-13.53877 -1183.826,-13.63705 -1165.594,4.323093 -1154.524,-0.2198782 -1145.307,8.251244 -1136.212,-0.1459947 -1127.318,8.395197 -1127.425,20.90548 -1132.316,19.78157 -1134.976,15.85121 -1140.847,27.66578 -1153.503,32.64259 -1173.508,46.8272 -1195.77,39.98267 -1214.31,39.54551 -1235.31,48.15401 -1262.019,56.77373 -1290.77,56.59818 -1317.063,53.30949 -1343.879,61.21212 -1364.448,38.20493 -1372.416,26.90753 -1376.097,26.42333 -1374.269,11.18833 -1368.546,15.03598 -1362.863,11.02519 -1356.038,11.46854 -1346.136,1.988382 -1325.11,-16.2194 -1284.63,-14.65078 -1238.373,-14.2102 -1193.929,-12.98282 -1155.988,-13.10039 -1137.273,2.958799 -1132.786,15.8914 -1141.075,33.33242 -1156.7,34.19608 -1179.433,52.38899 -1213.827,66.11726 -1258.176,83.05579 -1305.898,81.63163 -1353.754,91.2124 -1396.935,75.19558 -1438.893,94.76639 -1487.004,100.8023 -1529.298,83.95088 -1563.974,82.77102 -1596.393,81.57443 -1624.446,72.54066 -1640.138,42.54347 -1643,29.84203 -1638.257,16.47232 -1629.605,16.00256 -1630.478,48.60144 -1642.785,55.60721 -1656.623,55.29026 -1669.48,53.73763 -1680.188,49.11893 -1689.163,48.75134 -1695.907,42.08216 -1700.851,42.99605 -1706.79,46.16529 -1713.763,47.34768 -1720.427,45.77478 -1727.319,48.89489 -1725.733,15.54477 -1714.932,15.2667 -1703.74,13.40421 -1690.842,8.433504 -1676.749,8.346373 -1663.421,10.28855 -1648.951,3.619027 -1633.192,5.002003 -1617.433,2.826547 -1602.775,7.905733 -1589.501,6.74611 -1576.428,7.864722 -1567.118,18.46364 -1564.686,30.00007 -1567.427,35.38074 -1572.196,36.95614 -1576.469,34.14531 -1576.307,22.5677 -1570.826,16.47429 -1563.423,15.84486 -1553.562,7.964062 -1536.916,-5.952643 -1517.233,-2.275624 -1497.389,-6.935693 -1471.863,-18.41763 -1442.372,-18.13165 -1414.871,-13.40553 -1387.812,-17.13374 -1362.057,-10.3961 -1346.257,8.515593 -1345.787,31.16553 -1358.712,46.74545 -1379.066,53.84549 -1401.382,54.66264 -1424.557,58.96523 -1447.437,56.39186 -1469.605,59.47992 -1493.117,63.22589 -1515.124,57.4621 -1535.841,61.76757 -1557.969,64.56117 -1578.323,58.54613 -1596.594,60.07353 -1611.991,50.88236 -1621.194,40.61778 -1619.421,14.21795 -1605.113,-1.868717 -1588.762,6.50421 -1576.67,11.31663 -1569.348,21.61535 -1567.91,30.3064 -1571.135,36.95245 -1576.267,36.91877 -1582.797,42.09142 -1590.294,40.76203 -1597.817,42.91198 -1605.462,41.89369 -1612.273,40.82465 -1619.582,44.26139 -1628.167,45.92483 -1637.464,47.59579 -1648.723,53.73099 -1661.419,53.84293 -1676.91,65.1045 -1695.235,65.79607 -1711.21,58.91008 -1724.968,59.73791 -1739.437,63.20061 -1753.772,61.00745 -1768,64.61153 -1781.368,59.52817 -1794.521,65.5128 -1809.072,66.50668 -1818.449,47.4547 -1817.24,26.92148 -1805.995,8.979017 -1786.662,-4.010155 -1765.233,-0.05493259 -1742.89,-7.886769 -1721.609,2.619378 -1703.539,1.704347 -1687.591,9.187813 -1675.688,15.12251 -1669.373,28.10153 -1666.148,25.54206 -1659.176,14.7161 -1647.474,8.565833 -1631.875,0.5784202 -1615.068,3.583271 -1599,2.292942 -1587.324,17.45128 -1584.315,30.57986 -1586.8,35.61685 -1593.088,43.5732 -1602.506,46.77898 -1611.978,44.69442 -1618.292,36.94254 -1621.436,34.45127 -1619.475,19.75505 -1612.367,16.75193 -1602.009,8.288825 -1592.927,20.35848 -1589.178,25.61557 -1589.299,33.05613 -1592.766,36.86369 -1600.84,48.93576 -1611.79,47.39437 -1614.947,23.44294 -1610.836,22.92943 -1603.433,12.01165 -1586.975,-7.003079 -1563.772,-9.861372 -1540.355,-8.272071 -1519.907,-2.04369 -1503.677,3.384114 -1487.904,-1.296515 -1471.513,0.8036427 -1454.625,-3.150111 -1435.789,-5.048037 -1415.583,-7.256803 -1396.787,-1.866434 -1379.012,-5.011639 -1361.345,-2.060575 -1341.192,-11.55893 -1317.613,-10.92163 -1291.294,-15.20063 -1254.361,-14.80647 -1210.226,-14.88861 -1174.65,-14.81055 -1147.215,-14.28176 -1119.552,-13.7853 -1087.993,-13.05181 -1052.511,-12.44097 -1031.579,5.715624 -1037.853,32.76339 -1064.428,51.27643 -1098.567,52.62703 -1138.801,70.14542 -1186.926,77.43063 -1233.348,72.79241 -1273.076,66.44997 -1304.85,56.3991 -1335.952,68.81242 -1369.93,68.46135 -1401.744,66.97513 -1432.914,70.78075 -1462.162,65.10287 -1490.927,73.24111 -1519.369,67.75407 -1544.292,65.61349 -1569.657,72.50694 -1591.342,56.41633 -1604.709,47.0724 -1608.203,24.27454 -1601.539,12.98722 -1592.376,15.38727 -1589.407,33.14979 -1593.76,39.76634 -1602.748,49.21623 -1614.531,50.16054 -1628.221,57.05817 -1646.023,65.98457 -1665.665,65.65594 -1683.789,63.0876 -1698.339,55.09802 -1707.865,46.70007 -1711.465,34.71091 -1712.298,37.05171 -1713.763,37.07273 -1717.041,43.76989 -1723.678,49.61529 -1733.472,56.02866 -1744.677,55.90408 -1750.736,38.25808 -1755.6,52.16808 -1767.544,65.1767 -1784.929,74.09778 -1810.361,98.34163 -1843.734,108.7761 -1876.234,100.4823 -1900.229,80.1554 -1920.624,89.84477 -1923.486,11.55359 -1384.726,-6.716908 -1365.214,-9.758064 -1335.167,-15.65223 -1305.561,-9.438278 -1293.54,25.59272 -1293.716,51.81037 -1298.87,51.8591 -1307.468,70.9785 -1321.719,83.69244 -1340.242,97.09694 -1361.364,102.0721 -1381.797,98.08289 -1396.943,76.64746 -1408.093,78.5398 -1421.649,92.87965 -1436.79,90.6324 -1452.067,97.12432 -1465.261,81.55907 -1474.817,78.22183 -1481.586,66.6988 -1486.936,71.00793 -1494.076,78.64029 -1504.805,94.48131 -1519.545,105.7961 -1533.59,93.55258 -1544.594,90.03146 -1553.279,81.37687 -1560.448,82.33672 -1566.855,78.04972 -1572.087,76.19854 -1574.895,63.56385 -1574.396,55.5367 -1573.515,61.01888 -1573.036,57.94503 -1570.845,49.96451 -1566.747,45.35576 -1559.803,31.16218 -1548.662,17.72969 -1536.094,20.5824 -1523.252,14.39674 -1509.539,13.54565 -1497.577,23.35009 -1487.474,23.31975 -1479.131,32.58831 -1472.793,34.21489 -1471.189,59.98996 -1474.25,61.94712 -1479.943,76.42569 -1487.386,73.62328 -1493.87,72.10479 -1498.252,62.06528 -1504.355,83.55563 -1514.009,85.13411 -1522.518,78.52847 -1528.054,68.42541 -1531.879,68.98322 -1535.693,69.12019 -1539.86,71.95422 -1543.156,64.46819 -1544.232,58.62698 -1542.999,50.14769 -1540.877,52.80785 -1538.393,47.5109 -1535.83,51.87814 -1534.607,55.44809 -1535.527,65.06208 -1540.046,78.20454 -1545.102,69.33004 -1542.54,31.26162 -1534.764,36.16859 -1527.125,30.95866 -1517.892,25.15287 -1508.043,25.83571 -1498.927,28.26935 -1490.525,28.91031 -1483.571,35.82453 -1480.344,50.35513 -1480.471,55.54207 -1481.576,56.2795 -1481.869,50.83329 -1480.745,47.77131 -1478.28,42.57355 -1476.333,50.48153 -1475.023,46.08316 -1474.094,52.55144 -1473.565,48.33829 -1472.754,50.75901 -1472.802,53.36675 -1472.646,49.53503 -1472.675,54.45502 -1472.744,49.77462 -1473.644,59.45992 -1476.216,59.98241 -1477.918,54.67937 -1478.984,56.45734 -1479.639,52.3883 -1481.234,62.24279 -1484.403,62.18639 -1488.227,66.80893 -1491.239,57.95909 -1493.107,60.41497 -1495.973,64.38061 -1498.477,58.73077 -1499.935,58.45076 -1498.233,39.69763 -1490.447,21.17598 -1479.659,20.41969 -1469.35,22.65018 -1458.865,18.07665 -1449.143,25.79696 -1440.174,21.3046 -1431.009,23.49089 -1422.334,22.9997 -1411.819,11.86371 -1402.048,25.93449 -1394.321,22.3779 -1386.849,26.39423 -1381.039,30.80274 -1374.056,19.11548 -1365.478,21.04128 -1357.8,23.10369 -1351.413,27.2389 -1348.342,40.50266 -1348.86,46.52771 -1354.67,69.74982 -1364.49,69.70929 -1375.415,77.81886 -1386.575,73.11307 -1395.456,67.07029 -1403.241,68.56764 -1410.313,64.41555 -1416.035,62.10302 -1420.035,55.49044 -1423.057,57.14668 -1424.515,46.92026 -1424.466,48.65111 -1424.349,46.51535 -1420.514,27.12698 -1412.171,19.98239 -1399.202,-0.2213111 -1381.088,-8.825974 -1360.959,-10.97501 -1339.52,-15.13851 -1315.038,-15.79168 -1271.67,-13.71585 -1205.943,-12.13631 -1122.19,-10.03683 -1048.169,-10.36391 -990.1788,-9.246284 -928.2859,-9.212884 -867.8992,-9.020022 -804.412,-8.525709 -729.0021,-8.260065 -887.2314,-7.793596 -782.4908,-7.821894 -665.2287,-6.784316 -772.3559,-4.63562 -600,-6.277975 -614.9388,-5.288214 -696.7551,-3.49948 -600,-1.283326 -664.3683,-1.597912 -600,-1.778763 -600,-0.7596555 -600,-0.1736608 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,-2.38E-07 -600,0 -644.4445,1.612164 -644.4445,6.538949 -785.0072,0.8882241 -841.1434,3.194654 -644.4445,4.281434 -1009.552,-0.1017489 -970.5985,0.5266633 -942.8003,0.3860083 -644.4445,2.60547 -644.4445,3.600683 -614.3267,0.6870103 -645.5776,1.867147 -654.6205,4.423994 -692.8177,1.993502 -708.7716,2.477404 -728.2538,2.476002 -755.4572,3.501919 -778.621,2.18979 -785.3195,1.743106 -784.5526,1.346341 -785.7797,1.974449 -787.5695,1.416916 -784.4503,1.4051 -782.5583,1.548533 -779.4391,1.255069 -775.604,1.452504 -776.0643,1.739155 -781.2288,2.003658 -791.558,2.376166 -794.8305,1.215703 -790.2285,1.457595 -788.5922,1.549223 -777.0869,0.305099 -717.4133,-3.12269 -620.5139,-2.686603 -644.4445,1.54447 -1016.479,0.8481472 -962.2321,-0.9291403 -847.3507,-1.475364 -747.673,-0.2668786 -676.963,-0.3898878 -602.3846,-0.3104959 -600,-0.1901872 -600,0.1421087 -644.4445,0.9691319 -658.5208,5.586625 -644.4445,10.10435 -770.7463,12.22105 -927.217,10.38821 -1058.376,12.88986 -1195.672,14.52883 -1370.653,24.36733 -1588.996,29.57337 -1850.804,44.95491 -2070.22,25.92677 -2149.734,8.226243 -1319.83,16.38028 -1416.364,49.23381 -1559.182,49.06653 -1710.518,65.96037 -1919.854,106.5468 -2084.814,43.9015 -2166.125,47.40614 -1477.623,84.04178 -1568.573,75.32056 -1632.52,51.08742 -1672.844,42.69801 -1694.081,22.06184 -1716.868,46.75986 -1754.409,48.50185 -1799.228,62.44069 -1858.482,78.40761 -1900.06,34.26859 -1927.36,55.25987 -1337.101,81.45631 -1385.247,97.38922 -1429.335,76.56412 -1463.264,73.28956 -1495.965,77.56803 -1528.196,76.33263 -1558.654,76.35077 -1587.647,75.73126 -1612.448,66.08598 -1634.75,70.53711 -1654.379,59.56525 -1669.87,58.48478 -1687.604,69.47137 -1707.072,66.88885 -1722.079,55.75189 -1724.041,21.08878 -1712.486,6.930377 -1696.472,4.276927 -1677.568,-3.706191 -1660.694,10.34586 -1651.074,20.23409 -1643.645,17.34347 -1632.816,8.011366 -1618.776,5.67132 -1603.688,3.707242 -1588.144,3.373533 -1571.404,-0.8783412 -1555.752,6.147068 -1543.593,9.695271 -1532.576,9.228716 -1522.379,11.73368 -1509.777,1.065055 -1489.946,-10.28071 -1465.427,-12.51891 -1440.021,-12.71381 -1402.846,-16.25399 -1355.514,-15.46913 -1313.435,-14.94506 -1291.697,11.92974 -1290.622,22.9257 -1291.334,16.68974 -1292.651,24.62087 -1298.683,29.66311 -1308.639,35.86757 -1329.033,59.74829 -1361.923,73.65525 -1400.414,80.50338 -1437.67,75.37047 -1474.187,83.83059 -1510.207,79.0104 -1541.698,74.4771 -1566.836,62.39557 -1586.464,59.38128 -1599.685,43.04843 -1606.496,39.10833 -1607.544,24.1147 -1602.614,18.94668 -1599.308,29.22934 -1598.395,26.77416 -1592.524,12.49185 -1582.703,13.13161 -1570.221,3.125345 -1548.953,-14.38402 -1520.766,-17.64579 -1492.177,-15.95768 -1453.188,-19.0262 -1405.211,-17.32 -1359.907,-15.5539 -1311.877,-14.40117 -1259.963,-13.38175 -1212.524,-12.87038 -1177.001,-12.74935 -1155.424,-1.723226 -1141.801,-0.260747 -1134.492,12.46988 -1133.995,15.73124 -1130.65,5.669389 -1126.767,14.28826 -1128.648,19.20252 -1133.216,20.79155 -1142.795,31.54515 -1160.919,42.30621 -1179.715,34.65625 -1197.906,42.59779 -1221.082,49.09034 -1245.937,49.3044 -1271.692,54.20898 -1300.591,60.77997 -1329.168,56.62835 -1354.789,55.80923 -1375.788,46.10873 -1385.73,25.64256 -1386.025,18.74092 -1383.688,17.9726 -1379.388,12.89893 -1372.698,10.80366 -1364.207,7.388607 -1349.334,-6.829912 -1327.031,-12.3538 -1289.95,-14.04064 -1243.626,-13.43234 -1200.889,-12.65873 -1162.021,-12.30316 -1138.523,0.8973355 -1130.394,9.3073 -1135.07,31.08614 -1156.795,50.95563 -1189.187,59.67162 -1226.563,67.66388 -1268.951,78.01559 -1312.414,76.58404 -1356.025,85.13309 -1401.126,87.58305 -1444.898,88.26737 -1487.286,90.28471 -1527.847,89.14961 -1565.344,86.64429 -1597.481,76.86526 -1626.864,82.09353 -1642.073,31.50566 -1639.99,23.92768 -1637.76,30.81757 -1638.123,32.71453 -1642.126,43.46971 -1650.376,47.85925 -1656.905,38.26996 -1663.717,49.5445 -1672.006,44.13668 -1679.073,46.09537 -1685.71,43.32407 -1691.084,42.26889 -1696.646,44.54321 -1703.364,46.98836 -1710.511,46.79175 -1716.906,45.01366 -1717.444,26.1797 -1711.129,20.26562 -1704.439,24.31491 -1696.458,15.16069 -1684.38,9.138308 -1669.212,3.496205 -1653.412,6.050759 -1636.148,-2.083723 -1620.402,10.29929 -1606.523,3.2822 -1590.468,2.226402 -1576.711,10.1251 -1568.824,20.93763 -1567.413,31.03271 -1569.711,33.10635 -1572.452,32.69432 -1574.655,31.5523 -1572.747,19.22354 -1565.035,12.21235 -1556.195,15.0088 -1543.351,-1.151437 -1523.306,-7.844097 -1498.451,-15.2105 -1471.473,-14.222 -1443.514,-17.75576 -1418.028,-8.075694 -1395.819,-9.842525 -1378.085,3.328753 -1367.149,8.02681 -1360.404,14.89146 -1361.842,31.14586 -1371.771,39.49014 -1387.436,48.75327 -1406.608,51.37 -1428.548,59.16101 -1453.08,61.76308 -1479.238,67.222 -1503.811,59.92773 -1525.214,60.14183 -1544.184,54.53143 -1562.268,59.49051 -1582.313,63.16959 -1599.873,53.45661 -1613.429,51.63828 -1621.181,35.03048 -1616.371,9.457516 -1600.061,-3.788047 -1581.856,2.248221 -1572.667,24.77247 -1572.022,30.03358 -1574.01,33.46582 -1578.242,37.671 -1584.06,39.13469 -1589.837,38.06779 -1595.385,38.90419 -1601.216,39.5349 -1606.859,38.81017 -1614.638,47.36164 -1624.701,47.38615 -1636,52.69853 -1647.057,47.73088 -1657.59,52.09483 -1669.158,52.50356 -1683.198,62.20206 -1702.491,73.03305 -1723.463,70.75262 -1743.683,73.13956 -1762.667,68.86513 -1777.58,60.39309 -1789.188,58.30213 -1797.921,50.87263 -1806.855,60.13579 -1817.388,58.0382 -1823.299,43.58347 -1816.582,10.14859 -1802.529,14.92394 -1786.299,1.025387 -1768.927,9.511108 -1751.623,0.3174438 -1732.894,3.221305 -1714.636,1.037209 -1696.606,3.044764 -1683.345,16.9832 -1676.05,23.35215 -1669.494,19.07921 -1660.667,14.90462 -1649.65,10.84701 -1637.733,11.08645 -1623.559,2.431441 -1610.325,13.43634 -1600.115,11.95773 -1593.007,23.21765 -1593.733,37.80044 -1600.921,45.08272 -1610.755,47.47602 -1621.087,47.78857 -1627.616,35.45415 -1628.436,28.78426 -1624.513,19.24914 -1617.298,17.2322 -1609.13,15.51832 -1601.445,18.32353 -1596.178,23.1551 -1595.479,33.32108 -1600.276,41.6428 -1609.909,50.18336 -1618.373,38.57851 -1622.498,36.17999 -1621.987,23.06949 -1614.45,12.16186 -1598.261,-5.880579 -1576.576,-6.21808 -1557.216,0.2066689 -1540.557,1.06763 -1523.776,-0.7704601 -1505.168,-4.783222 -1484.424,-7.280366 -1461.786,-10.48103 -1437.992,-10.87021 -1412.439,-15.4868 -1386.16,-13.11512 -1361.533,-11.51401 -1337.054,-12.97312 -1311.675,-13.94429 -1284.644,-14.70514 -1260.877,-6.438118 -1239.233,-12.14887 -1213.585,-13.36887 -1189.711,-8.318381 -1167.449,-12.13369 -1133.834,-11.54234 -1098.11,-11.47418 -1073.161,-9.736206 -1051.866,-8.969399 -1043.845,17.9187 -1059.793,42.8426 -1091.15,54.27356 -1132.423,69.97617 -1179.849,74.85709 -1224.723,70.31767 -1266.425,73.1416 -1304.474,66.09874 -1339.956,71.33346 -1376.07,72.68569 -1408.422,65.08088 -1436.595,64.42775 -1462.377,61.2652 -1487.568,65.8431 -1513.982,68.2971 -1540.825,70.66122 -1565.277,63.87906 -1586.142,61.8507 -1603.258,53.73509 -1610.003,28.49205 -1602.412,5.785827 -1591.718,17.46236 -1587.728,27.60659 -1590.347,39.33879 -1599.711,50.57925 -1614.356,58.24709 -1631.714,61.5585 -1649.959,63.41554 -1667.223,60.33664 -1682.902,59.92071 -1697.641,58.86283 -1708.402,47.30275 -1712.889,37.3675 -1714.622,37.78582 -1716.933,39.62757 -1720.386,42.15772 -1725.639,46.5316 -1733.472,52.14337 -1742.568,52.02161 -1752.026,54.51895 -1760.92,50.98923 -1773.2,68.27187 -1792.224,77.96797 -1821.486,110.3905 -1859.212,115.6734 -1886.512,75.2928 -1904.73,83.84886 -1920.543,68.10039 -1923.083,32.01192 -1906.866,-6.502386 -1369.067,-8.091158 -1347.198,-16.18642 -1322.599,-15.63903 -1300.348,-10.72464 -1291.3,42.13477 -1295.232,54.72806 -1305.844,78.21381 -1323.205,92.89117 -1342.943,94.77242 -1363.46,101.6814 -1385.072,105.6614 -1401.614,77.6887 -1414.802,90.22686 -1429.796,90.92907 -1445.416,97.26785 -1460.968,94.02265 -1474.025,85.8418 -1482.309,68.04903 -1486.554,63.08653 -1491.151,71.01434 -1497.039,71.83271 -1507.27,98.90955 -1520.142,90.28288 -1531.712,93.81809 -1542.735,89.45779 -1550.501,75.71756 -1555.763,75.2889 -1560.967,76.44486 -1565.573,72.56293 -1568.879,69.08176 -1571.598,69.47919 -1572.166,55.82536 -1571.677,62.81889 -1571.921,60.4342 -1570.689,53.40608 -1566.415,40.77371 -1555.499,10.54896 -1539.664,8.183149 -1524.034,9.895695 -1510.967,22.06216 -1500.463,23.95686 -1491.063,27.36668 -1482.349,26.82351 -1476.999,46.35995 -1477.996,64.20844 -1481.899,64.05076 -1485.909,65.5948 -1490.075,65.75693 -1495.259,72.5956 -1502.116,77.00091 -1508.6,71.68607 -1514.263,73.26437 -1521.178,80.59914 -1529.15,81.26859 -1536.368,77.57661 -1542.686,77.1497 -1547,66.23773 -1548.115,57.8325 -1546.481,49.11549 -1544.408,54.76034 -1543.166,53.98143 -1541.073,49.1928 -1539.361,55.99929 -1538.862,56.49809 -1538.393,56.0927 -1540.417,72.0712 -1545.18,73.70837 -1546.256,49.76416 -1542.735,44.97318 -1535.145,23.71458 -1523.252,17.02971 -1509.617,11.41548 -1496.003,15.4281 -1487.171,38.66481 -1482.3,38.17532 -1480.637,57.24352 -1481.762,54.72427 -1482.73,56.49815 -1483.307,52.52861 -1482.72,49.56577 -1481.508,48.64921 -1480.187,48.71376 -1478.955,48.95982 -1477.576,47.62597 -1477.849,58.67931 -1479.013,53.03189 -1479.307,53.63831 -1480.021,55.61882 -1480.793,54.11613 -1481.361,54.51465 -1483.004,60.71709 -1484.578,54.38765 -1485.42,56.56187 -1485.889,52.28399 -1486.613,58.18631 -1488.002,56.44076 -1489.87,61.34771 -1490.917,51.78019 -1491.102,56.30661 -1492.227,57.52043 -1493.675,58.47193 -1495.113,57.72102 -1495.445,51.99366 -1494.271,48.60529 -1489.625,30.71955 -1480.001,17.82528 -1467.472,12.0361 -1457.623,32.14432 -1450.424,26.50847 -1441.191,19.21676 -1431.459,22.39477 -1422.754,23.97624 -1414.069,21.42962 -1406.89,31.4945 -1401.579,31.19041 -1395.554,26.72908 -1387.563,19.29863 -1377.782,15.70328 -1368.803,22.63366 -1361.243,22.56006 -1353.398,20.18481 -1347.96,34.80918 -1349.799,59.43176 -1356.929,64.2579 -1365.889,70.86021 -1376.755,76.60091 -1387.504,72.27655 -1395.348,62.18171 -1402.557,70.15619 -1408.826,58.08114 -1414.47,67.74133 -1420.152,59.29419 -1424.652,61.93027 -1429.249,60.66118 -1431.322,48.02657 -1430.774,45.73412 -1426.217,24.6445 -1410.704,-15.22193 -1391.456,1.596369 -1375.386,-1.242421 -1360.089,4.432325 -1342.327,-12.48885 -1315.958,-15.63675 -1278.253,-14.49595 -1226.61,-12.92336 -1157.421,-11.01548 -1084.691,-10.37803 -1016.333,-9.222387 -953.2953,-8.877071 -891.1482,-8.744204 -1132.584,-10.29824 -1027.589,-7.797905 -906.3764,-7.333625 -778.9708,-6.812672 -640.4005,-6.574084 -725.2108,-4.330684 -600,-6.607558 -974.2606,0.2646341 -678.2445,-2.214189 -600,-2.06674 -600,-2.121689 -600,-1.457825 -600,-0.0909586 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,2.38E-07 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,2.38E-07 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,-2.38E-07 -600,2.38E-07 -600,-2.38E-07 -600,2.38E-07 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,2.38E-07 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,-2.38E-07 -600,2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,4.77E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,2.38E-07 -644.4445,0.07269168 -644.4445,0.5636628 -644.4445,6.32637 -909.8743,8.952326 -612.8438,0.4596145 -1049.945,0.5363288 -644.4445,1.307286 -644.4445,1.506667 -644.4445,1.191484 -644.4445,1.223324 -644.5549,1.372464 -645.5549,2.282104 -647.3238,2.434664 -660.2452,2.209997 -681.7216,2.61131 -706.7773,2.741129 -730.1458,2.619758 -748.145,2.314906 -760.0593,2.050172 -764.6102,1.540037 -765.2238,1.621832 -763.9455,1.326239 -764.4057,1.815315 -767.3715,1.615054 -764.6102,1.172328 -763.6898,1.813547 -765.7863,1.513745 -764.7125,1.459806 -763.4852,1.49177 -760.6218,1.268719 -717.6179,-2.408862 -665.5632,0.2176919 -624.9115,-1.213306 -1023.406,-0.02850914 -644.4445,2.188613 -998.4866,-0.7567296 -913.1129,-0.6905825 -792.6539,-1.726186 -682.2707,-0.2418582 -619.2075,-0.1684604 -644.4445,0.6611562 -646.427,1.844816 -674.444,1.06398 -698.6438,1.278553 -843.8422,6.181966 -645.6003,6.826957 -727.7936,6.854918 -867.4923,13.15338 -1035.213,14.05835 -1166.934,11.57775 -1302.747,18.54018 -1484.631,24.88181 -1734.831,42.28856 -2034.273,49.13046 -2212.783,14.95125 -1365.991,14.98481 -1435.985,36.59709 -1555.953,48.97858 -1705.628,64.5892 -1887.01,84.50237 -2010.176,29.41932 -1359.912,69.16082 -1460.599,91.42927 -1564.59,85.87419 -1639.38,57.33976 -1678.83,35.33801 -1693.723,19.23966 -1709.133,37.07459 -1753.812,70.30568 -1809.11,58.7817 -1828.497,10.1565 -1245.703,51.546 -1279.657,74.22597 -1325.282,88.26819 -1368.083,72.68974 -1405.977,80.60335 -1446.416,85.91576 -1481.576,70.02934 -1508.876,66.10561 -1538.958,82.82529 -1572.196,80.56322 -1601.915,75.8309 -1627.751,71.48734 -1648.79,62.65011 -1666.484,62.48646 -1683.574,62.6969 -1701.953,69.27721 -1717.592,55.01025 -1723.154,34.47604 -1716.396,10.84506 -1701.523,4.702551 -1681.102,-8.599273 -1661.836,7.633382 -1652.243,23.09983 -1646.547,20.57926 -1637.236,10.19999 -1622.242,0.4904656 -1602.922,-4.652774 -1584.731,3.380548 -1570.49,7.09161 -1557.458,6.66973 -1543.848,4.555008 -1531.689,10.66433 -1519.437,3.691454 -1503.61,-1.150481 -1485.728,-3.026744 -1464.379,-11.14701 -1436.985,-17.6633 -1401.435,-16.52778 -1357.637,-15.3913 -1312.307,-14.65012 -1287.908,11.86469 -1286,20.54327 -1286.619,18.54342 -1288.244,23.31835 -1295.069,32.82963 -1308.289,41.42417 -1326.36,47.51019 -1350.341,60.05747 -1386.146,84.80302 -1424.275,71.51812 -1459.61,82.11712 -1496.731,82.10949 -1531.165,78.98655 -1560.709,71.02921 -1584.879,65.1485 -1601.875,49.84313 -1609.842,36.42356 -1612.555,32.75125 -1610.258,19.61487 -1605.542,24.35468 -1602.197,23.91504 -1596.433,15.96346 -1585.846,7.36155 -1572.707,6.84079 -1554.569,-8.548178 -1529.58,-14.25133 -1502.374,-15.33138 -1473.287,-18.2294 -1433.115,-16.61605 -1379.361,-15.28753 -1322.517,-14.32261 -1269.65,-13.59477 -1223.823,-13.03917 -1191.054,-10.34762 -1167.623,-10.96569 -1146.087,-7.865382 -1138.617,20.75992 -1139.92,11.95193 -1135.07,6.090739 -1128.836,8.454925 -1127.815,18.23122 -1133.229,23.74462 -1145.025,33.94183 -1162.007,37.24741 -1180.266,38.54793 -1199.371,41.02165 -1220.437,45.36328 -1244.338,50.5095 -1270.631,54.25564 -1298.159,56.81184 -1326.924,60.92234 -1355.084,58.48366 -1378.461,50.37475 -1393.267,35.86261 -1398.198,22.63688 -1395.484,13.71113 -1386.67,4.619095 -1373.732,1.322395 -1360.028,1.926163 -1347.05,2.909883 -1327.864,-13.99705 -1303.439,-10.30259 -1270.98,-13.94411 -1227.45,-13.10693 -1189.361,-12.86395 -1163.257,-9.064267 -1149.096,6.519079 -1145.415,14.67137 -1153.382,34.60891 -1178.546,57.754 -1216.998,71.03598 -1263.134,83.27469 -1314.765,93.22186 -1365.711,89.68562 -1406.138,70.3726 -1441.432,80.56233 -1480.152,86.0248 -1517.623,82.35265 -1553.777,87.54527 -1590.871,91.02081 -1619.381,63.71481 -1634.092,47.46525 -1638.526,29.794 -1635.489,22.06191 -1635.758,40.95305 -1643.712,48.7066 -1653.788,49.15121 -1663.139,47.23022 -1672.597,50.53967 -1682.109,48.42113 -1690.426,47.30361 -1696.001,39.47346 -1699.468,40.3076 -1704.479,45.37587 -1710.861,45.75566 -1718.881,52.00259 -1722.791,31.61168 -1716.893,16.77742 -1706.844,16.1372 -1696.579,15.30738 -1686.61,16.48245 -1676.655,14.68511 -1666.323,14.48469 -1653.439,5.125021 -1638.015,4.899573 -1622.054,2.485665 -1605.65,2.586072 -1589.635,3.008597 -1576.482,11.31122 -1568.972,20.98672 -1568.045,32.59629 -1571.82,36.49885 -1575.689,33.22871 -1577.006,28.33649 -1576.509,27.30095 -1573.043,18.44022 -1566.083,15.48969 -1553.253,-1.0913 -1533.543,-6.647263 -1512.571,-5.314623 -1489.597,-12.72277 -1465.037,-10.23271 -1440.626,-12.70623 -1416.577,-9.706091 -1395.107,-6.353202 -1377.024,-1.41299 -1362.729,3.233414 -1354.829,16.14577 -1363.078,49.1428 -1386.616,61.25877 -1414.32,64.14809 -1440.303,59.41497 -1460.953,50.86452 -1479.574,55.51258 -1498.37,53.43364 -1516.938,56.92963 -1538.501,65.29128 -1562.402,67.20255 -1585.376,65.22421 -1607.168,66.15616 -1622.363,45.26455 -1626.448,29.70588 -1619.663,8.417274 -1605.892,5.471342 -1590.294,1.554001 -1574.104,2.731438 -1564.27,21.70022 -1562.819,29.79327 -1568.34,44.64818 -1577.866,43.57754 -1587.66,46.50829 -1597.844,45.86784 -1605.354,38.47025 -1610.205,37.56776 -1614.96,38.60074 -1622.027,45.92914 -1631.029,45.93453 -1640.622,48.91043 -1652.001,53.17495 -1664.657,54.63203 -1677.662,55.84564 -1692.656,63.26057 -1711.21,70.51211 -1732.478,75.57997 -1753.544,72.63683 -1769.828,60.5629 -1783.451,64.80178 -1796.429,59.79764 -1807.943,60.86138 -1820.33,64.59172 -1828.176,44.81462 -1821.163,8.214087 -1804.249,6.292377 -1787.871,9.134424 -1770.714,2.376011 -1754.109,10.06567 -1738.806,6.212786 -1721.286,1.067402 -1704.721,8.612881 -1690.95,10.14219 -1679.624,16.43083 -1669.144,12.42631 -1658.987,16.84797 -1647.85,8.391995 -1632.507,1.645216 -1616.008,3.606684 -1600.128,2.947272 -1589.487,20.32802 -1587.647,31.78459 -1590.159,34.78584 -1594.271,37.37839 -1600.692,42.96344 -1610.513,49.539 -1619.219,40.11499 -1623.559,35.45469 -1622.551,22.18125 -1616.573,18.38556 -1609.412,17.73681 -1601.727,16.13419 -1594.458,18.62502 -1590.616,27.14091 -1592.551,37.74634 -1599.214,43.24936 -1607.383,43.47301 -1616.519,47.3689 -1620.966,28.29967 -1614.678,11.12828 -1600.491,1.117563 -1577.759,-15.98362 -1550.498,-12.94688 -1526.638,-6.817096 -1505.168,-6.72456 -1484.263,-5.809709 -1462.727,-8.948511 -1443.058,-1.342418 -1426.667,-0.6651244 -1410.316,-1.713572 -1393.038,-3.54139 -1376.876,0.7599344 -1361.493,-1.957383 -1339.513,-15.69704 -1313.126,-13.22394 -1287.062,-14.71945 -1250.061,-13.29444 -1211.717,-13.18758 -1184.632,-12.68648 -1156.754,-13.87198 -1125.974,-13.35509 -1094.321,-12.72246 -1054.539,-11.65611 -1026.366,1.78571 -1031.707,34.37691 -1059.625,52.05185 -1095.194,54.60882 -1132.853,61.3746 -1177.447,76.69508 -1222.979,69.77629 -1261.898,65.92332 -1296.198,62.50776 -1331.935,74.62606 -1370.172,74.38905 -1403.021,64.03122 -1430.133,61.57874 -1454.451,58.83109 -1481.079,71.86363 -1508.285,63.87067 -1533.275,68.35617 -1556.074,59.77805 -1575.649,60.55231 -1590.562,46.38965 -1598.476,38.60023 -1600.316,26.62489 -1595.412,16.02007 -1589.635,23.31708 -1594.485,51.32585 -1609.062,56.67459 -1626.676,63.39441 -1644.746,60.32769 -1660.559,57.70242 -1675.096,57.71563 -1688.518,55.43426 -1701.389,57.32327 -1710.565,43.53574 -1713.427,35.47276 -1715.402,40.61037 -1719.432,43.12147 -1724.444,44.58424 -1731.376,50.66751 -1740.593,53.71496 -1749.258,49.65441 -1754.552,42.17929 -1757.723,42.34054 -1768.121,69.52338 -1794.468,103.9193 -1825.61,91.68179 -1855.813,105.6374 -1881.836,79.81264 -1897.179,67.01525 -1905.496,53.63717 -1906.692,39.33886 -1889.011,-19.16266 -1849.122,-24.79765 -1807.889,-24.43617 -1779.689,-0.7561536 -1284.092,17.17696 -1284.102,58.07148 -1292.093,58.99236 -1304.082,80.69597 -1321.862,92.27543 -1340.809,90.74892 -1359.844,96.99959 -1378.966,95.45564 -1393.216,73.59466 -1402.928,72.61659 -1413.785,82.11748 -1426.51,85.63467 -1440.927,94.76996 -1455.95,92.36811 -1470.416,94.86768 -1480.725,70.45586 -1486.985,72.58999 -1494.017,76.40392 -1505.187,99.43295 -1520.278,103.0791 -1537.327,115.3624 -1552.584,95.87924 -1562.453,84.82603 -1568.948,76.54655 -1573.946,76.64169 -1578.063,71.93213 -1579.726,61.67735 -1579.57,60.54532 -1578.23,54.0312 -1574.601,45.59658 -1570.894,52.8693 -1567.725,48.39549 -1563.177,43.51645 -1555.069,25.0616 -1541.767,9.581061 -1527.692,18.39748 -1515.007,16.44184 -1501.92,14.32027 -1490.76,26.46716 -1483.728,37.81801 -1478.436,35.96482 -1475.345,50.22443 -1478.28,71.72651 -1485.41,76.1095 -1492.481,72.78746 -1498.937,73.78825 -1505.128,72.46352 -1511.525,76.31317 -1517.471,70.96622 -1522.88,74.19914 -1528.641,74.2482 -1535.39,81.57578 -1541.278,70.22089 -1544.848,68.2123 -1547.264,63.6499 -1547.371,54.11656 -1545.171,49.12331 -1542.52,50.89368 -1539.84,48.48135 -1537.816,54.52997 -1536.886,54.98994 -1537.346,63.06376 -1541.503,78.29755 -1548.662,82.82697 -1550.482,45.99143 -1544.809,35.92283 -1533.756,11.44688 -1518.009,5.243145 -1503.915,19.64205 -1492.609,20.55502 -1483.464,31.21258 -1479.277,49.16108 -1478.886,53.42761 -1479.62,55.8742 -1479.786,50.1337 -1479.678,54.25177 -1479.933,52.29718 -1480.578,56.65665 -1480.842,50.10637 -1480.598,53.63382 -1479.004,41.93355 -1476.324,46.8269 -1474.172,44.68207 -1472.274,48.00023 -1472.079,54.57672 -1472.597,52.24992 -1474.455,62.71901 -1477.018,56.80586 -1479.698,63.90294 -1482.955,60.77087 -1485.019,57.28467 -1487.298,62.45473 -1490.075,60.72274 -1492.403,60.23314 -1493.763,55.25238 -1493.205,48.80926 -1492.892,56.64178 -1493.557,54.70619 -1494.144,56.28391 -1494.682,54.51154 -1494.007,48.99399 -1492.853,51.47742 -1488.951,32.13356 -1476.187,-2.118674 -1457.887,-2.126604 -1443.636,19.47982 -1434.912,28.30535 -1428.173,29.93163 -1421.649,28.65341 -1414.167,23.54668 -1406.841,28.56202 -1399.642,23.36224 -1392.786,29.56185 -1386.477,25.6082 -1378.163,17.51092 -1369.077,20.2835 -1360.695,20.3895 -1353.369,25.12762 -1349.398,37.92805 -1351.149,56.04457 -1358.328,68.17207 -1369.312,78.50098 -1382.037,80.05802 -1392.443,67.88512 -1400.953,71.3244 -1408.376,63.24284 -1413.912,61.8568 -1417.932,55.47812 -1421.189,58.15731 -1423.85,52.57276 -1425.894,55.04035 -1428.72,57.47088 -1430.657,50.33347 -1427.302,27.01298 -1417.443,12.22586 -1403.036,-0.1684303 -1384.237,-11.87013 -1363.287,-11.63743 -1342.004,-13.53146 -1318.618,-16.01462 -1282.605,-14.39375 -1220.908,-12.12208 -1141.722,-10.68284 -1074.528,-10.48296 -1022.054,-9.141874 -960.7875,-8.731186 -1216.514,-10.74907 -1109.274,-9.523954 -1005.743,-8.101731 -906.0809,-7.618393 -784.7748,-6.123598 -636.8536,-6.884468 -741.9532,-5.764419 -836.1458,-0.8582449 -600,-4.675195 -952.2463,0.009875298 -664.0984,-1.178708 -600,-1.123972 -600,-0.2031865 -600,-0.6548967 -600,-0.000296116 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,2.38E-07 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,2.38E-07 -644.4445,0.2542183 -644.4445,3.043099 -644.4944,3.76886 -862.1945,7.244804 -644.4445,2.008217 -644.4445,1.282092 -644.4445,1.102336 -644.4445,1.300048 -644.4445,1.259131 -644.4445,1.073095 -645.6724,3.006216 -618.264,-0.3244839 -647.7556,5.489882 -701.8685,2.742796 -722.4244,2.271123 -743.2361,2.935951 -762.5648,2.234797 -772.9451,2.039693 -780.2573,1.936579 -786.3934,1.940598 -781.9448,0.7246585 -771.7178,1.247691 -769.2634,1.590314 -768.7009,1.456245 -766.1954,1.364901 -764.2012,1.504721 -766.3488,1.831629 -768.0362,1.460694 -768.0362,1.645372 -773.3542,2.075679 -774.5814,1.194392 -764.559,0.7873244 -745.3326,0.1385179 -715.4191,-0.332602 -677.2729,-0.594053 -635.803,-0.5641029 -981.9337,-3.01793 -839.9738,-0.6091862 -727.9713,-1.361682 -620.287,-0.3443129 -600,-0.198132 -600,-0.2130547 -644.4445,1.156704 -644.4445,2.928335 -840.5137,7.855536 -645.6799,4.915875 -718.7428,7.940886 -919.598,20.71529 -1104.653,9.702165 -1177.315,7.127035 -1343.756,30.38393 -1513.062,9.906143 -1007.81,36.38819 -1161.267,39.11203 -1278.037,27.3871 -1383.305,40.41537 -1511.207,46.64371 -1596.608,19.454 -1075.369,38.91386 -1144.645,51.12838 -1236.03,71.91323 -1345.194,84.24624 -1462.489,97.86935 -1569.923,84.68086 -1640.951,52.99866 -1686.982,50.89439 -1708.258,14.60182 -1146.06,-3.260405 -1143.091,26.43259 -1164.452,55.55766 -1202.272,69.78938 -1248.732,83.18002 -1301.019,92.7276 -1354.342,94.76001 -1401.919,84.77892 -1438.704,69.75992 -1467.953,66.90834 -1497.591,74.95674 -1527.323,71.09368 -1554.516,70.7477 -1580.204,69.72466 -1607.732,80.51578 -1633.071,65.80466 -1652.807,64.51868 -1671.334,64.05013 -1689.244,64.65747 -1706.105,62.52456 -1720.534,57.92768 -1723.772,23.39667 -1706.911,-12.77224 -1685.898,7.341925 -1671.979,9.75246 -1662.279,21.29147 -1658.504,29.84188 -1653.587,17.03524 -1638.794,-4.186825 -1617.648,-4.962307 -1597.884,-0.8135309 -1580.257,0.750226 -1562.563,-1.659951 -1548.537,11.91162 -1540.033,15.42424 -1535.115,23.01572 -1531.448,19.15309 -1516.118,-12.86069 -1492.284,-7.591835 -1467.55,-15.70515 -1435.373,-17.46522 -1392.904,-16.13951 -1347.977,-15.4994 -1312.535,-15.2666 -1292.543,4.540256 -1286.511,16.9544 -1287.236,22.45613 -1293.9,33.18174 -1303.345,30.53206 -1313.502,35.92642 -1331.949,54.6626 -1359.692,64.28005 -1396.867,85.87479 -1437.925,80.98814 -1474.281,77.60077 -1509.642,83.28379 -1543.23,76.9175 -1570.127,65.98427 -1588.654,52.43436 -1600.84,46.78295 -1606.805,32.59529 -1605.65,23.18912 -1600.504,19.00929 -1594.781,20.86993 -1590.656,23.9784 -1587.486,23.77216 -1582.017,16.08064 -1572.358,9.474892 -1555.805,-6.293793 -1535.33,-3.614192 -1510.986,-17.70457 -1482.517,-15.38637 -1448.754,-17.3886 -1398.587,-15.64723 -1329.799,-13.74466 -1273.492,-14.25001 -1241.248,-13.40315 -1205.269,-12.6376 -1165.85,-12.21276 -1135.151,-12.03583 -1120.372,9.679996 -1120.828,20.11432 -1124.12,16.3987 -1126.471,18.06844 -1130.287,20.00859 -1140.336,33.27053 -1156.029,34.36275 -1172.272,35.92491 -1186.231,29.97521 -1199.088,34.3232 -1218.381,47.54738 -1244.808,54.75484 -1274.137,58.20295 -1304.004,59.67457 -1330.377,51.92756 -1355.218,58.4916 -1371.65,30.14645 -1375.962,24.95364 -1378.676,25.82015 -1379.214,18.80646 -1374.31,10.07271 -1365.201,6.415627 -1355.783,8.765409 -1346.029,5.078839 -1331.237,-5.104489 -1306.892,-15.03027 -1262.704,-13.15916 -1218.341,-13.36216 -1187.789,-12.82549 -1158.756,-12.40262 -1140.404,3.783212 -1146.194,39.93061 -1168.859,45.34202 -1196.469,54.62985 -1230.943,66.16975 -1267.379,64.01351 -1307.698,81.99072 -1350.247,75.75098 -1391.923,86.11143 -1438.113,95.74863 -1481.187,83.65627 -1522.688,98.04447 -1564.162,89.97185 -1600.074,86.14787 -1628.449,69.52667 -1645.015,49.09846 -1644.383,11.60987 -1636.161,22.72835 -1636.631,41.04108 -1644.504,48.4262 -1655.387,52.34411 -1667.573,54.19073 -1678.724,50.02793 -1685.71,40.58485 -1688.384,35.37016 -1693.812,50.70958 -1703.243,50.27459 -1708.913,38.13729 -1712.647,43.88169 -1719.594,50.16351 -1728.071,50.19448 -1728.891,23.06607 -1720.413,16.42023 -1711.479,20.75814 -1701.872,13.39018 -1689.687,10.86072 -1670.811,-9.679937 -1650.241,3.8373 -1635.127,7.068507 -1619.717,2.065735 -1602.99,1.803795 -1589.608,12.44946 -1580.634,15.81511 -1574.991,22.96172 -1575.542,36.00331 -1579.236,33.46876 -1581.762,32.42493 -1582.434,27.48787 -1578.618,17.52039 -1570.772,13.83211 -1562.375,15.1992 -1551.869,6.441697 -1534.793,-5.906759 -1512.289,-10.30744 -1486.695,-15.03363 -1458.857,-16.87653 -1432.135,-12.41042 -1407.629,-11.31777 -1384.171,-10.03571 -1369.003,10.59928 -1365.08,20.52546 -1370.091,36.15165 -1380.638,36.95204 -1393.63,44.27267 -1412.734,56.37016 -1440.572,72.8304 -1467.684,57.35134 -1491.37,65.70872 -1518.066,69.83893 -1541.604,58.79247 -1561.153,59.73059 -1579.048,55.58046 -1595.762,57.87779 -1611.924,55.62059 -1625.601,51.2132 -1629.645,23.90257 -1619.246,2.099785 -1602.936,3.149794 -1587.781,5.188667 -1575.542,12.07873 -1570.329,27.7652 -1573.903,40.86924 -1581.722,42.21673 -1589.689,42.11393 -1595.95,37.23134 -1600.491,36.9001 -1604.898,37.1901 -1610.715,42.10384 -1618.87,45.72244 -1628.409,47.67087 -1640.151,54.35364 -1653.022,52.86154 -1665.678,55.06348 -1679.879,59.78596 -1695.907,63.27319 -1713.198,66.3249 -1731.269,68.31712 -1748.775,66.57999 -1763.997,62.08349 -1779.34,69.02579 -1793.984,61.35672 -1805.202,57.85924 -1812.82,48.92445 -1819.578,55.46923 -1825.906,48.01827 -1821.056,13.10841 -1805.565,6.840103 -1788.691,6.806072 -1772.488,8.286536 -1756.487,6.550629 -1737.798,-2.249373 -1717.807,0.735312 -1700.731,6.919925 -1685.226,5.433849 -1672.436,15.57636 -1664.362,21.22834 -1658.961,24.37656 -1650.268,9.386177 -1634.71,0.04979086 -1614.544,-6.336586 -1598.381,12.57801 -1590.025,18.29753 -1584.288,20.81376 -1584.234,36.87918 -1596.608,62.62403 -1613.859,54.64594 -1622.457,34.95087 -1624.271,32.25559 -1624.661,30.22398 -1624.849,31.59747 -1621.624,18.55824 -1611.064,6.372733 -1598.986,12.73059 -1591.785,22.058 -1592.013,37.18653 -1598.704,43.85127 -1607.947,46.47419 -1618.319,48.64143 -1621.906,24.24795 -1615.068,13.35699 -1603.111,6.432739 -1588.722,4.500189 -1572.573,-0.115675 -1553.629,-4.783992 -1532.751,-6.315992 -1514.761,3.077488 -1500.399,3.732917 -1482.651,-7.154562 -1463.519,-1.135713 -1440.935,-16.81416 -1414.158,-12.81345 -1390.943,-7.845296 -1368.922,-10.04424 -1346.889,-8.254794 -1323.471,-13.71456 -1296.762,-14.93286 -1265.673,-14.07961 -1236.546,-11.97013 -1207.23,-12.98112 -1174.139,-12.54039 -1146.973,-10.93499 -1124.362,-10.41155 -1093.918,-11.0197 -1057.509,-10.56761 -1037.759,6.854196 -1046.344,37.0987 -1073.335,48.63685 -1107.407,56.2469 -1148.129,68.77713 -1192.304,70.15498 -1231.884,63.05749 -1264.786,57.78709 -1296.44,63.90317 -1332.419,73.914 -1371.166,76.68737 -1406.42,69.01247 -1434.862,60.98241 -1458.468,57.80101 -1482.987,66.75755 -1509.669,67.63638 -1535.465,67.33713 -1560.091,67.14167 -1583.253,65.62291 -1599.443,46.44219 -1606.684,37.13651 -1604.884,16.46138 -1593.343,4.168659 -1584.033,23.15694 -1588.211,48.71681 -1600.585,51.11957 -1617.836,66.74638 -1638.794,65.8931 -1658.92,66.52989 -1676.91,60.87619 -1691.756,57.56428 -1704.331,54.48838 -1710.861,37.12782 -1711.546,34.04327 -1710.229,29.95877 -1712.661,47.48108 -1721.461,53.3045 -1730.906,50.78699 -1740.176,53.73991 -1751.045,57.7492 -1757.951,40.23434 -1759.778,39.63506 -1772.192,80.07209 -1797.208,88.74728 -1826.631,100.872 -1858.271,102.1546 -1885.397,88.15533 -1904.448,74.06339 -1916.432,62.34672 -1919.401,39.03856 -1902.46,-15.46535 -1863.511,-25.07789 -1823.273,-21.13098 -1791.996,-14.05958 -1770.969,13.06777 -1286.498,48.0114 -1294.058,67.24074 -1306.597,75.67068 -1322.628,88.41093 -1342.258,98.59779 -1363.062,99.24053 -1378.535,73.31172 -1388.825,73.33134 -1401.598,89.55661 -1416.387,87.50754 -1432.163,98.61768 -1449.387,99.54861 -1465.027,93.16014 -1475.385,71.32512 -1479.141,55.54146 -1483.825,77.69683 -1492.922,83.2123 -1504.218,93.1139 -1517.188,96.03044 -1530.509,98.30925 -1543.136,94.77704 -1552.281,79.19598 -1557.964,74.84485 -1563.461,79.22526 -1569.339,78.43729 -1574.591,76.46247 -1577.222,62.67551 -1577.242,60.19896 -1575.687,52.56088 -1572.498,49.43146 -1569.329,52.1115 -1564.947,41.14471 -1554.462,12.68271 -1539.967,14.31148 -1525.981,14.02893 -1511.818,11.48827 -1497.929,13.95845 -1487.532,30.92048 -1481.38,38.22163 -1478.329,48.67535 -1478.162,55.10718 -1479.678,58.7858 -1483.914,71.81812 -1490.819,75.78394 -1498.35,77.02534 -1505.099,72.51969 -1511.202,74.43957 -1517.911,77.50984 -1525.814,83.25037 -1532.593,72.12448 -1537.16,70.83592 -1542.236,76.25439 -1544.985,57.17952 -1544.32,55.29839 -1544.476,62.22943 -1544.496,54.4649 -1542.745,51.09521 -1539.38,44.02723 -1535.742,48.7935 -1534.999,61.51359 -1537.258,67.46387 -1540.965,71.03705 -1547.939,88.8294 -1549.738,39.71848 -1538.647,8.12237 -1524.67,20.05622 -1512.2,15.72904 -1500.873,25.39976 -1490.78,21.78333 -1482.358,34.10342 -1478.485,47.99138 -1477.977,53.7555 -1477.801,49.90863 -1479.15,62.92201 -1481.243,54.62078 -1481.116,49.8967 -1480.324,50.58609 -1479.63,50.35303 -1477.321,40.75677 -1473.565,41.27589 -1470.426,43.86224 -1468.401,47.451 -1466.954,46.9868 -1467.658,60.07456 -1470.602,60.51458 -1475.668,73.382 -1481.801,67.88359 -1484.911,56.28338 -1485.674,54.24988 -1486.251,55.29283 -1486.691,53.52103 -1486.77,53.17738 -1486.721,52.76431 -1487.024,55.30242 -1487.669,54.89172 -1489.019,59.68992 -1490.731,57.32771 -1492.951,63.0985 -1495.279,58.38214 -1494.584,45.10869 -1487.405,18.9328 -1470.866,-10.28922 -1452.928,8.639071 -1440.017,15.75091 -1429.552,21.4329 -1422.607,34.86482 -1417.512,31.21866 -1412.484,34.53926 -1407.31,29.69863 -1401.344,29.30284 -1395.877,31.73983 -1390.937,31.57141 -1385.724,29.53498 -1378.741,20.95574 -1371.111,25.03376 -1363.707,21.31329 -1355.785,21.27985 -1349.271,28.11312 -1347.491,46.42329 -1354.044,73.73386 -1364.627,69.82935 -1374.183,70.02986 -1382.281,63.41209 -1390.106,70.01546 -1398.41,67.56463 -1404.523,59.0325 -1409.433,61.78816 -1413.688,56.11639 -1417.443,59.66835 -1421.248,57.04577 -1423.116,49.10121 -1423.185,46.9263 -1420.573,33.6044 -1411.956,11.98207 -1397.891,1.452831 -1383.142,6.65378 -1367.718,-3.068421 -1348.968,-9.861969 -1325.562,-16.11518 -1284.092,-14.13637 -1214.697,-11.85796 -1141.781,-11.37294 -1079.028,-10.51758 -1008.215,-8.903414 -930.7995,-8.72839 -857.0523,-8.130159 -789.291,-8.076338 -726.7427,-8.857965 -898.0064,-7.569747 -769.9961,-6.515765 -649.1603,-7.147186 -784.9226,-4.621058 -892.3317,-0.6631382 -608.6652,-4.717086 -600,-6.420379 -606.6129,-1.587289 -600,-0.7637906 -600,-0.8728795 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,-2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,-2.38E-07 -600,0 -600,-2.38E-07 -600,-2.38E-07 -600,0 -600,-2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -644.4445,0.1401868 -644.4445,4.115141 -723.5632,6.148651 -878.7474,0.996314 -644.4445,5.992946 -614.2244,0.8715067 -1054.623,0.2505918 -1032.132,1.002764 -644.4445,1.849404 -644.4445,1.160477 -644.4445,1.181648 -646.017,3.313942 -655.8477,2.47095 -673.5912,1.926634 -697.6755,3.281785 -729.89,2.964346 -753.4118,2.586441 -769.7236,2.314295 -781.3311,2.144838 -788.3876,1.845007 -788.5922,1.371453 -785.2173,1.424252 -785.7797,1.820931 -787.4161,1.552712 -785.6775,1.431036 -786.0355,1.792017 -787.007,1.504555 -785.3195,1.483458 -784.6548,1.617746 -783.939,1.474823 -778.5699,1.072223 -772.178,1.335513 -761.5421,0.5722067 -687.8577,-4.410039 -1043.288,-1.19836 -644.4445,2.357286 -1002.265,-0.5849216 -866.3327,-2.573789 -732.1096,-0.3810852 -661.4896,-0.2707293 -600,-0.2227266 -644.5211,1.784207 -615.0692,-0.02452826 -600,-0.1297612 -644.4445,0.6420181 -666.7973,4.922177 -644.4445,8.587686 -693.5847,6.82707 -836.9651,12.78135 -995.8392,12.11045 -1190.252,24.46093 -1341.456,7.883049 -1453.439,21.57428 -1009.962,38.10797 -1173.415,42.39235 -1323.306,42.99743 -1399.727,9.089857 -937.9701,32.31821 -1005.795,44.4572 -1088.015,53.16226 -1172.164,54.589 -1265.583,73.96272 -1376.655,88.71164 -1496.45,101.4458 -1616.172,105.6161 -1668.748,5.478724 -1119.606,4.928539 -1124.671,35.79109 -1140.175,30.06963 -1160.328,48.58438 -1189.106,53.33678 -1224.844,69.88008 -1267.755,76.89536 -1310.533,75.63843 -1352.249,80.32765 -1392.649,77.89688 -1429.045,74.28435 -1463.412,76.94868 -1497.873,79.46665 -1531.421,78.96201 -1561.273,72.11664 -1587.056,69.5541 -1609.479,64.13884 -1630.585,67.9769 -1650.429,62.38124 -1668.137,63.00897 -1684.42,59.49305 -1702.746,72.43027 -1718.317,51.68219 -1722.2,31.7786 -1710.807,-2.869109 -1690.453,-1.062667 -1673.296,7.073107 -1662.924,21.68794 -1658.853,28.46225 -1655.051,22.32484 -1643,-0.4019394 -1623.586,-3.330098 -1604.414,-0.449111 -1587.123,1.748246 -1569.496,-2.081304 -1552.944,4.46729 -1542.894,18.06239 -1538.031,20.74931 -1530.547,9.303829 -1514.237,-7.018807 -1492.526,-7.514885 -1469.149,-12.08818 -1442.722,-15.80163 -1404.525,-18.5696 -1361.667,-17.84917 -1327.529,-17.22158 -1306.449,4.262201 -1300.712,18.62459 -1305.858,33.81105 -1310.184,16.66183 -1310.09,21.90794 -1317.331,37.01147 -1331.747,42.52515 -1353.015,57.90654 -1383.016,70.18417 -1420.392,83.79029 -1463.21,92.30715 -1502.401,78.82739 -1533.557,72.45618 -1561.099,71.36134 -1584.785,63.23337 -1600.343,46.89187 -1607.934,37.95928 -1609.116,25.84165 -1606.496,25.15568 -1602.882,22.27899 -1597.401,18.59029 -1590.777,18.05532 -1581.158,8.168066 -1565.438,-2.385445 -1544.224,-9.294456 -1521.841,-6.390518 -1499.485,-9.735824 -1475.06,-12.31793 -1438.369,-16.93306 -1388.027,-15.79407 -1334.837,-14.71431 -1282.574,-13.81453 -1232.73,-12.99281 -1186.607,-12.35547 -1153.933,-9.757157 -1138.281,3.688477 -1130.166,6.484842 -1124.469,9.161757 -1119.579,8.190273 -1116.717,13.7386 -1121.178,25.33872 -1131.012,26.74716 -1139.974,23.89797 -1153.758,39.14996 -1173.145,38.69012 -1197.14,52.6565 -1222.573,44.61408 -1247.831,55.10344 -1274.231,50.24755 -1302.956,64.64877 -1334.958,62.68685 -1361.681,53.49527 -1382.828,49.63818 -1393.616,25.17934 -1392.595,15.85793 -1388.47,16.01408 -1382.331,9.760792 -1375.264,12.98514 -1368.573,10.51227 -1357.852,1.127345 -1330.887,-15.09141 -1287.693,-14.09798 -1235.995,-12.79959 -1189.24,-12.6493 -1159.75,-9.993802 -1143.158,2.208033 -1140.753,21.87768 -1152.361,35.92246 -1169.356,35.89918 -1193.446,55.35715 -1227.665,64.36838 -1263.591,64.05273 -1304.172,82.13965 -1350.765,86.74195 -1399.89,97.1329 -1448.015,91.67886 -1490.363,87.14861 -1527.78,82.59544 -1565.411,93.79819 -1601.888,84.35611 -1629.712,69.70103 -1643.765,40.32787 -1644.598,25.34709 -1642.677,30.8411 -1647.957,50.22522 -1657.926,47.7007 -1664.052,37.76743 -1668.701,43.12788 -1677.555,53.11346 -1688.478,51.41099 -1698.5,51.11005 -1706.414,44.9026 -1708.993,32.6828 -1711.102,43.46721 -1718.371,51.58891 -1728.098,53.19771 -1735.42,43.84155 -1735.339,26.82102 -1726.916,13.36045 -1716.691,19.60794 -1707.085,14.90211 -1695.128,10.50889 -1682.271,10.91309 -1663.878,-8.54956 -1641.629,-3.117419 -1624.07,5.537962 -1609.197,4.835527 -1592.752,-0.4371243 -1577.893,9.274105 -1570.101,22.16969 -1571.847,40.37538 -1576.751,32.78808 -1579.035,32.08871 -1581.749,34.41856 -1583.133,27.87005 -1576.012,6.219936 -1561.421,2.702191 -1547.059,6.234878 -1534.363,7.427535 -1520.672,2.441157 -1500.385,-12.44278 -1474.039,-15.19112 -1448.391,-10.99723 -1411.539,-16.18276 -1375.237,-10.13539 -1357.798,3.94146 -1352.424,22.40654 -1358.053,35.1076 -1371.085,44.18404 -1390.486,54.94989 -1412.506,53.94309 -1436.112,62.30517 -1459.811,56.89755 -1483.336,64.70206 -1510.018,69.77424 -1535.801,65.16431 -1559.043,64.80313 -1580.728,62.89471 -1598.556,54.45824 -1613.254,54.38581 -1626.582,51.40335 -1634.75,38.01902 -1625.87,-5.708029 -1605.435,-1.783062 -1588.211,3.508634 -1575.972,13.76913 -1574.601,38.87314 -1576.764,25.41134 -1576.509,31.0111 -1580.378,39.14088 -1587.109,40.92192 -1594.552,42.17134 -1602.21,42.3647 -1609.64,42.14173 -1617.876,45.85305 -1627.146,46.51075 -1637.773,51.51218 -1651.907,59.8804 -1668.016,60.05737 -1682.956,57.66072 -1698.594,64.39252 -1714.26,59.62116 -1729.025,63.08392 -1743.723,61.17331 -1759.321,68.29936 -1774.275,60.68742 -1787.293,62.94482 -1799.157,57.8984 -1810.375,61.97612 -1821.647,59.47066 -1829.144,48.76117 -1827.075,23.35892 -1814.029,6.402053 -1794.32,-2.592016 -1771.735,-4.909734 -1752.711,9.03825 -1737.462,7.341007 -1721.273,4.683862 -1704.694,4.982325 -1688.128,3.812349 -1674.545,14.56831 -1666.793,23.51281 -1662.064,24.63626 -1654.984,14.94999 -1635.731,-15.84564 -1610.997,-4.315684 -1594.74,9.832749 -1588.036,26.32848 -1590.885,41.41418 -1599,44.31393 -1604.347,32.80503 -1609.748,45.03335 -1620.321,50.97161 -1629.86,42.54122 -1630.612,21.65488 -1626.286,25.14294 -1622.995,24.88023 -1619.287,23.46855 -1613.268,16.73643 -1607.706,24.57117 -1610.003,43.01642 -1616.519,39.12624 -1621.208,37.39355 -1624.634,35.22969 -1627.952,37.3392 -1624.594,12.60667 -1610.554,0.67381 -1592.725,-0.8326931 -1573.647,-3.764307 -1556.383,4.200647 -1540.61,-0.05308342 -1524.676,2.95549 -1506.149,-7.869933 -1484.451,-6.838203 -1463.063,-7.529763 -1441.418,-8.017014 -1419.842,-7.811407 -1398.13,-8.783758 -1377.628,-5.129324 -1358.174,-6.480177 -1330.162,-16.99247 -1294.518,-16.31282 -1264.088,-13.97139 -1238.279,-14.27002 -1205.672,-13.58043 -1175.577,-8.778869 -1153.073,-12.24656 -1128.594,-11.99461 -1095.57,-10.9451 -1059.322,-10.66192 -1040.862,6.466439 -1046.922,32.05039 -1070.836,46.81862 -1105.593,59.44982 -1144.421,60.56117 -1185.277,69.68872 -1225.22,63.52172 -1258.217,56.72657 -1292.812,72.29202 -1331.452,72.35333 -1366.88,68.45086 -1393.737,51.85317 -1417.343,62.23331 -1449.023,79.29785 -1486.588,84.81449 -1520.337,72.50204 -1545.353,61.22117 -1565.129,58.47639 -1583.576,59.16581 -1597.441,45.13127 -1602.506,30.88554 -1600.343,21.15592 -1593.612,15.33718 -1586.666,19.96346 -1587.996,42.56586 -1600.719,58.4817 -1618.574,61.39739 -1637.37,63.87596 -1655.736,62.19775 -1672.167,59.32374 -1687.886,61.68731 -1702.047,55.59766 -1710.914,44.22459 -1715.953,42.70472 -1719.231,38.34271 -1721.891,40.7861 -1725.048,40.4108 -1728.743,43.06327 -1735.541,52.16247 -1744.341,51.14399 -1753.557,54.70576 -1763.137,53.5337 -1773.912,60.3172 -1790.531,76.9442 -1814.647,91.22339 -1844.93,104.5918 -1876.086,99.57632 -1900.511,82.78519 -1919.052,79.66685 -1921.161,18.51604 -1896.575,-24.33028 -1849.753,-24.22952 -1809.65,-2.914296 -1783.061,-16.90625 -1283.055,17.62789 -1281.148,47.45848 -1288.122,63.8209 -1299.731,73.06547 -1314.197,81.21303 -1332.148,94.84081 -1352.77,99.70914 -1374.041,103.1989 -1391.799,84.65783 -1404.758,79.80271 -1417.834,88.10941 -1433.956,100.3611 -1452.571,106.4864 -1469.02,91.7476 -1477.869,64.48682 -1482.045,65.40362 -1486.32,65.86734 -1494.467,89.83578 -1506.898,93.77473 -1519.525,93.85491 -1531.702,93.87712 -1542.725,89.39608 -1552.242,86.8752 -1559.959,80.07738 -1564.449,67.961 -1567.041,68.89693 -1570.2,72.11388 -1572.977,67.08501 -1574.21,62.75511 -1574.21,59.41563 -1573.936,60.99732 -1572.4,51.27596 -1568.263,44.06831 -1559.519,21.27699 -1545.63,10.24199 -1530.617,12.39669 -1515.183,5.857883 -1498.36,2.09445 -1486.505,33.94199 -1482.349,47.08876 -1480.05,44.51606 -1479.463,57.02282 -1482.084,63.77707 -1487.796,76.23621 -1495.289,75.71186 -1501.538,70.15787 -1507.818,77.17599 -1514.703,75.15352 -1520.865,74.11327 -1527.096,76.84986 -1532.231,68.53654 -1536.417,71.96849 -1540.564,69.12055 -1543.713,66.52328 -1546.735,68.94624 -1547.489,52.78967 -1545.386,51.08469 -1542.256,45.96298 -1539.361,52.00807 -1537.405,51.35246 -1535.859,54.2338 -1536.554,65.10095 -1540.671,75.84949 -1547.195,81.08743 -1550.257,55.29021 -1545.806,34.30048 -1535.243,16.24277 -1523.33,24.33566 -1512.464,21.15258 -1502.918,30.91319 -1494.076,24.17211 -1485.987,34.19572 -1480.725,40.09128 -1478.27,50.29652 -1478.016,52.946 -1478.182,52.7861 -1478.378,53.15138 -1480.079,61.90357 -1482.192,55.92644 -1482.075,48.81292 -1479.982,43.98728 -1478.104,49.7599 -1476.93,47.92091 -1476.646,54.91663 -1477.908,57.17506 -1478.681,52.18999 -1479.786,59.31868 -1481.165,54.03209 -1482.339,58.32693 -1484.236,58.61423 -1487.024,64.06499 -1489.743,58.70241 -1491.484,58.62561 -1492.824,56.57703 -1493.381,54.10405 -1492.256,46.44337 -1490.926,52.65959 -1491.445,57.45026 -1492.804,57.86545 -1494.702,60.97232 -1495.856,53.67446 -1488.354,8.644087 -1473.771,9.854107 -1459.911,11.31598 -1449.71,29.82105 -1444.35,38.53183 -1441.259,42.37823 -1436.486,28.24177 -1429.513,28.8433 -1421.864,23.41715 -1414.392,28.83934 -1409.071,34.798 -1403.584,27.19031 -1396.982,27.69853 -1388.531,15.91847 -1377.224,10.64097 -1366.25,16.52416 -1358.612,27.90209 -1355.629,41.29479 -1355.726,44.49744 -1358.876,58.18682 -1366.27,68.5884 -1376.618,76.04653 -1388.952,81.80117 -1400.522,74.14407 -1408.504,63.53102 -1415.252,68.5932 -1420.651,56.93834 -1423.263,53.41837 -1425.219,53.58304 -1426.207,48.11959 -1426.852,51.75898 -1427.38,47.54124 -1423.742,27.67442 -1415.125,18.26986 -1402.381,3.03742 -1388.482,10.29751 -1373.977,-1.384802 -1355.462,-10.03899 -1330.062,-15.91993 -1282.331,-13.68837 -1209.601,-11.78776 -1130.279,-10.6761 -1056.59,-9.85384 -995.0887,-9.493731 -932.1101,-8.854118 -860.5636,-8.522646 -799.4923,-8.632871 -742.3431,-8.777902 -916.95,-7.472395 -784.6405,-6.526037 -659.1023,-7.239723 -802.2018,-4.796231 -600,-4.862612 -980.1921,3.036931 -655.1318,-1.243356 -600,-3.643281 -600,-2.117112 -600,-0.4603643 -600,-2.24E-05 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,-2.38E-07 -600,0 -600,0 -600,0 -600,0 -600,0 -600,2.38E-07 -600,0 -600,2.38E-07 -600,0 -600,0 -600,-2.38E-07 -600,-2.38E-07 -644.4445,1.714838 -644.4445,1.621784 -644.4445,3.298661 -755.8596,3.870013 -644.4445,3.134853 -644.4445,1.420932 -644.4445,1.825752 -644.4445,1.360866 -991.1098,0.8516321 -644.4445,2.159252 -644.4445,1.824742 -644.4445,1.209069 -645.8011,2.986922 -651.5524,2.650311 -659.7339,0.760689 -685.8124,4.595871 -737.2534,3.604281 -762.7693,2.212489 -770.3373,1.737349 -772.536,1.632224 -772.3826,1.47518 -768.9055,1.248654 -770.1327,2.003068 -775.6552,1.749856 -776.7802,1.519026 -774.1212,1.315794 -769.7236,1.307899 -770.2861,1.870355 -770.2861,1.245239 -768.343,1.646059 -768.3942,1.467183 -762.5137,0.9683771 -717.0042,-2.388535 -628.3375,-2.716046 -644.4445,1.232642 -1006.313,0.3278913 -950.627,-0.5628872 -846.9909,-1.407126 -722.4837,-1.039502 -621.8163,-0.4376612 -600,0.0385704 -644.4445,1.879608 -602.8344,0.04388237 -600,-0.00674057 -644.4445,1.93153 -794.813,7.284958 -644.8845,6.377717 -738.2761,9.556376 -924.2001,17.0417 -1082.921,9.743132 -1157.014,6.99104 -775.9276,22.85481 -919.729,33.17456 -1086.138,42.19983 -1261.492,50.43425 -1375.494,19.51903 -1401.449,6.091826 -926.2782,23.43933 -980.7605,39.51251 -1054.848,47.15857 -1133.927,51.68547 -1226.62,71.72372 -1337.942,86.13082 -1457.344,97.89137 -1580.828,109.5713 -1657.092,36.67658 -1123.368,1.461304 -1122.441,25.1924 -1136.454,37.02988 -1161.309,52.76898 -1193.459,57.73195 -1230.285,68.77976 -1273.533,79.75322 -1318.352,79.31004 -1356.562,67.54053 -1392.273,77.71348 -1426.908,69.05838 -1460.725,80.27706 -1498.424,86.01363 -1534.793,81.56979 -1565.21,71.81206 -1590.119,67.43898 -1612.582,66.8174 -1634.24,67.57295 -1656.032,70.10327 -1677.488,69.22984 -1696.042,62.52128 -1711.774,61.43768 -1725.102,55.68619 -1731.578,37.91976 -1722.254,-1.090255 -1702.517,-0.3800182 -1681.747,-5.168064 -1664.59,11.20999 -1654.514,18.04026 -1645.996,15.99401 -1635.436,10.42183 -1621.665,4.338938 -1605.22,0.5969486 -1587.795,0.2512197 -1570.517,0.3162355 -1554.072,2.230137 -1541.806,13.14601 -1533.597,14.75539 -1525.832,14.09572 -1514.506,2.944591 -1496.1,-7.84253 -1471.352,-15.42717 -1440.169,-20.01007 -1400.468,-18.50732 -1353.19,-17.0692 -1315.531,-12.80798 -1294.491,-3.285613 -1284.173,13.58008 -1289.225,37.47305 -1302.015,35.04106 -1311.339,28.96468 -1316.942,25.44615 -1328.926,47.30635 -1352.921,60.59223 -1385.233,74.25334 -1422.945,80.9559 -1461.329,81.75445 -1495.643,73.77378 -1525.133,71.24657 -1553.333,73.6284 -1578.726,65.64669 -1596.568,51.4837 -1607.732,45.11185 -1612.851,32.04094 -1610.876,21.44158 -1605.126,19.07754 -1598.368,17.63783 -1591.677,18.84343 -1582.676,9.494823 -1569.455,4.294639 -1552.541,-2.913902 -1532.455,-5.940009 -1507.855,-16.18926 -1475.826,-18.23104 -1433.29,-16.7917 -1382.384,-15.64154 -1326.494,-14.32655 -1274.366,-13.89831 -1227.275,-12.87859 -1182.348,-12.34522 -1151.286,-9.173134 -1131.402,-6.310503 -1119.781,8.727276 -1118.289,16.43811 -1118.921,13.66425 -1120.828,19.48628 -1124.819,18.68554 -1130.757,24.36229 -1141.048,29.49514 -1158.46,42.48001 -1180.763,43.03611 -1203.146,44.87235 -1225.918,46.25666 -1248.597,46.92699 -1272.592,52.15644 -1299.516,57.51007 -1329.074,62.6179 -1359.343,63.1154 -1380.947,40.95043 -1388.403,23.98634 -1388.417,19.74684 -1385.165,14.44612 -1379.603,12.82719 -1372.187,8.792199 -1363.065,7.554926 -1349.723,-3.177336 -1329.396,-11.0907 -1300.833,-14.74182 -1261.575,-13.61232 -1217.468,-12.85518 -1175.268,-12.22688 -1141.546,-12.1833 -1126.955,11.26167 -1134.532,35.89684 -1157.695,49.54621 -1189.052,58.5972 -1222.466,58.37698 -1257.343,66.71474 -1300.538,85.77503 -1352.393,97.63816 -1402.304,88.47597 -1444.938,84.01994 -1484.008,84.11902 -1521.116,83.72038 -1557.216,86.50259 -1591.624,83.49979 -1623.855,84.3294 -1647.595,58.56056 -1655.346,31.51854 -1647.595,5.291959 -1637.236,21.8509 -1638.069,43.26761 -1647.353,51.25405 -1657.993,48.95843 -1668.862,53.2352 -1680.014,51.13348 -1689.217,47.52374 -1696.109,43.85042 -1700.18,38.1036 -1701.886,35.75303 -1704.895,42.96144 -1713.521,56.36014 -1723.759,49.71629 -1725.169,25.28842 -1717.766,17.81898 -1708.886,19.36817 -1699.602,15.74377 -1685.428,1.331335 -1668.258,4.265698 -1651.088,0.4824829 -1632.682,-0.7735591 -1616.546,7.333869 -1601.297,1.405253 -1587.109,10.06296 -1578.108,17.9458 -1571.148,16.3085 -1567.669,28.97894 -1571.471,40.18153 -1577.49,36.66446 -1581.507,34.05357 -1584.664,34.14597 -1581.897,14.52561 -1573.567,15.4157 -1560.951,-0.06234074 -1539.428,-12.5987 -1514.842,-9.453217 -1487.81,-18.44072 -1460.886,-9.728415 -1437.804,-9.730576 -1416.16,-6.372715 -1395.067,-8.671995 -1373.544,-7.898953 -1360.901,15.09554 -1358.859,20.97911 -1363.857,35.19839 -1379.617,52.60059 -1405.99,68.11739 -1434.069,60.73365 -1456.748,55.0891 -1477.304,56.83291 -1499.552,62.82561 -1522.835,62.77331 -1543.606,57.48309 -1563.611,62.81192 -1585.403,65.84775 -1604.911,57.73931 -1619.407,51.10355 -1625.279,29.70323 -1619.824,12.86922 -1606.134,1.337738 -1587.701,-3.369208 -1572.465,11.06384 -1564.538,19.60567 -1563.638,33.72519 -1569.052,40.41961 -1578.041,46.10619 -1586.653,40.0111 -1594.445,44.22099 -1602.896,42.9819 -1610.231,41.26826 -1616.559,40.2604 -1624.123,46.1275 -1634.065,49.20351 -1644.907,50.29093 -1656.059,51.45343 -1668.943,57.63499 -1688.625,77.20282 -1711.116,70.17025 -1728.34,61.05583 -1744.61,68.95058 -1762.868,70.50829 -1779.366,64.74032 -1794.387,67.11285 -1807.486,59.31385 -1818.275,59.92589 -1828.835,59.76006 -1834.155,40.87052 -1824.254,1.570856 -1803.939,0.1671991 -1785.896,8.91948 -1769.089,3.76696 -1750.548,1.465682 -1734.198,10.69146 -1720.507,10.2054 -1707.327,11.65767 -1695.45,14.03399 -1684.931,15.71651 -1675.325,16.56543 -1665.933,15.82545 -1654.339,8.25458 -1639.587,4.160066 -1622.202,-1.38369 -1608.431,15.49589 -1602.748,25.05814 -1601.189,29.03644 -1603.151,36.84112 -1608.673,41.2834 -1614.087,36.97735 -1619.031,40.19678 -1622.941,33.88109 -1623.505,29.08438 -1621.114,23.80924 -1615.149,16.70804 -1607.464,17.53648 -1602.546,25.54437 -1600.706,27.58181 -1600.195,29.89292 -1602.318,36.44426 -1608.995,45.53632 -1616.116,38.564 -1619.327,32.86123 -1617.164,20.48985 -1607.571,7.451408 -1591.973,-0.2941513 -1573.177,-3.498985 -1552.541,-6.302647 -1531.81,-4.429373 -1511.698,-5.13943 -1493.265,-0.3575616 -1477.143,0.7890692 -1461.141,-0.5568328 -1445.449,1.121991 -1430.375,0.6806421 -1410.706,-11.54041 -1385.824,-13.42626 -1360.619,-12.66673 -1335.24,-14.07331 -1309.62,-13.46232 -1274.366,-13.88826 -1237.862,-13.81937 -1212.241,-11.44095 -1184.081,-12.65552 -1148.102,-11.87495 -1115.508,-11.77358 -1087.442,-11.19799 -1054.593,-10.48865 -1033.607,5.6588 -1040.043,33.29015 -1064.535,46.21249 -1097.908,56.06443 -1138.16,66.53667 -1181.515,68.95843 -1223.258,68.46669 -1261.723,66.08852 -1300.779,75.51466 -1341.756,76.87059 -1377.36,65.75189 -1406.339,62.23019 -1433.908,65.22336 -1459.475,59.45428 -1483.82,64.64926 -1510.354,69.41556 -1536.862,67.94376 -1560.467,63.31855 -1581.225,61.46338 -1596.42,47.04777 -1600.343,25.01183 -1593.115,9.831497 -1584.181,18.76838 -1581.493,30.10958 -1586.962,45.85008 -1600.37,57.38508 -1617.769,60.89524 -1636.443,63.86408 -1655.078,63.03837 -1671.496,58.34701 -1686.221,59.03419 -1700.287,57.73484 -1710.955,48.39701 -1717.229,43.00974 -1721.3,41.04623 -1725.115,42.49238 -1729.374,43.04696 -1732.33,38.14999 -1734.453,40.29311 -1737.193,40.62325 -1742.259,49.12432 -1749.527,49.27705 -1758.905,57.77568 -1780.186,95.1664 -1817.066,120.4318 -1863.283,138.34 -1894.667,69.34295 -1907.269,68.27747 -1919.079,67.84028 -1917.762,16.49406 -1889.951,-25.8662 -1839.596,-23.89131 -1797.746,-6.402427 -1288.914,-15.27851 -1277.128,32.77653 -1281.275,63.12198 -1290.283,58.78977 -1302.49,81.71949 -1320.926,94.45592 -1342.199,101.122 -1364.574,105.4511 -1384.497,92.51437 -1399.036,79.38459 -1412.044,86.92896 -1425.375,83.94568 -1438.726,89.94231 -1452.996,92.26556 -1465.477,82.38766 -1473.311,67.06986 -1478.475,67.91246 -1485.547,79.625 -1497.763,100.7359 -1512.278,96.41169 -1525.707,97.44376 -1538.334,94.52263 -1549.249,89.58551 -1557.71,81.4274 -1564.057,77.99872 -1569.036,74.02861 -1572.312,68.13066 -1575.041,71.18874 -1576.86,62.82628 -1576.352,56.58434 -1574.357,53.18288 -1571.52,50.82687 -1567.755,46.73517 -1562.385,39.9514 -1553.406,22.98973 -1541.513,20.22375 -1527.653,9.152882 -1512.63,11.24 -1497.871,9.012047 -1484.578,18.34523 -1477.82,46.65918 -1476.558,50.44249 -1476.832,55.68708 -1479.131,62.68777 -1483.698,69.81506 -1490.535,77.33602 -1498.018,75.10793 -1505.011,75.88093 -1512.151,77.44696 -1520.327,83.79372 -1527.986,75.92196 -1532.671,66.83388 -1536.348,70.5734 -1539.762,65.89542 -1543.273,71.87601 -1547.303,69.85374 -1549.034,58.16096 -1547.87,51.91158 -1546.364,55.78762 -1544.672,50.47578 -1541.356,45.2815 -1538.324,51.6749 -1537.356,57.68959 -1538.872,67.07841 -1544.251,82.28827 -1545.288,40.75605 -1538.011,30.25864 -1530.314,36.96606 -1522.196,26.52944 -1511.906,22.36277 -1500.12,15.97792 -1489.616,28.55366 -1482.329,34.04303 -1478.945,50.99249 -1479.502,57.25879 -1480.607,54.3908 -1481.048,53.44007 -1481.713,55.82595 -1482.329,53.25982 -1482.818,55.16615 -1481.811,44.30854 -1479.307,45.96726 -1476.646,42.96669 -1473.575,43.07121 -1471.717,49.74657 -1470.788,48.34003 -1472.177,63.49163 -1475.942,62.85665 -1479.972,65.78904 -1484.334,65.62042 -1488.217,63.7094 -1490.124,54.34649 -1490.183,52.82955 -1489.342,48.89529 -1488.755,54.22676 -1487.777,46.42638 -1486.192,50.38337 -1485.576,52.02367 -1487.601,66.28146 -1491.67,64.79538 -1494.985,62.46672 -1496.091,51.93176 -1492.462,33.85468 -1486.104,34.78819 -1476.089,10.9714 -1464.117,21.67854 -1454.757,25.02648 -1445.866,23.2522 -1436.829,23.01534 -1428.603,26.81799 -1421.473,28.30663 -1413.345,20.16391 -1404.963,25.78935 -1396.278,17.4505 -1387.201,22.49283 -1379.914,26.44587 -1372.432,20.53219 -1364.392,22.42527 -1357.027,23.32439 -1350.679,27.14028 -1350.269,55.12245 -1357.262,67.91344 -1367.101,72.15673 -1377.987,75.64056 -1389.636,78.59641 -1399.104,65.48586 -1405.217,61.24613 -1409.795,57.77759 -1413.922,59.46923 -1417.404,54.76487 -1420.857,59.91445 -1423.595,51.20931 -1424.886,51.9877 -1425.776,49.09315 -1423.556,34.09339 -1418.059,29.80763 -1405.119,-7.826694 -1385.391,-8.599997 -1365.175,-11.35708 -1344.4,-11.20156 -1318.843,-15.60458 -1278.125,-14.10385 -1212.223,-11.80592 -1143.825,-11.62002 -1080.622,-10.19347 -1005.036,-8.704713 -942.2039,-9.229837 -877.6898,-7.629379 -796.7341,-8.281475 -1005.85,-9.090136 -922.6464,-8.02299 -814.1037,-6.777267 -680.4239,-6.171268 -600,-6.54746 -881.2298,-1.826855 -625.3334,-5.014571 -600,-5.152775 -600,-4.932726 -600,-1.280655 -600,-0.4310925 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 -600,0 +<n> + , + <Pe> + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,2.38E-07 + 600,0 + 644.4445,2.329973 + 644.4445,0.5693641 + 644.4445,4.264177 + 869.7512,7.98456 + 644.4445,1.351656 + 1015.31,-0.2716608 + 948.6478,-0.4653716 + 872.4501,-0.5719776 + 644.4445,1.012361 + 816.044,0.1606398 + 644.4445,3.967641 + 644.4445,4.3916 + 645.3466,1.254886 + 602.9238,0.36098 + 644.4445,1.097353 + 644.4445,1.476951 + 645.6951,2.961375 + 656.8193,3.33839 + 688.8293,2.509675 + 715.7259,3.104633 + 743.2361,2.779576 + 759.3434,2.025352 + 763.0762,1.467997 + 761.0308,1.383811 + 757.7582,1.320618 + 755.406,1.475238 + 756.3265,1.681716 + 753.872,1.098228 + 749.1166,1.411724 + 747.787,1.465289 + 743.7986,1.110595 + 691.6417,-3.012229 + 627.2637,-0.1685431 + 1049.495,-0.09707546 + 644.4445,1.615664 + 1026.825,0.4667768 + 977.9754,-0.4151859 + 906.5457,-0.4785028 + 764.8557,-2.495939 + 615.8789,-0.5095253 + 600,-0.2679868 + 644.4445,0.5701756 + 644.4445,1.185031 + 600,0.2967396 + 646.6069,3.811063 + 895.4804,7.923037 + 653.8535,6.359474 + 791.9158,11.55912 + 900.8318,4.931076 + 1007.856,14.46236 + 1156.708,13.49057 + 1345.086,27.20026 + 1602.138,35.01208 + 1888.49,46.58702 + 2103.714,24.29906 + 2146.359,-1.109985 + 1286.033,8.800848 + 1351.937,37.56419 + 1494.108,56.84015 + 1650.18,55.71647 + 1797.949,62.99876 + 1974.041,90.22348 + 2191.804,115.1789 + 2403.877,105.9852 + 2503.301,18.33513 + 1611.144,-1.709167 + 1619.774,43.61679 + 1655.685,42.16265 + 1690.462,44.19933 + 1723.907,42.2117 + 1766.618,62.7349 + 1823.327,70.33007 + 1898.131,102.0343 + 1980.033,91.64824 + 2027.516,42.57878 + 2040.799,27.31307 + 1396.846,69.06043 + 1435.803,91.8233 + 1479.637,89.72998 + 1511.026,58.87632 + 1535.129,70.88527 + 1563.544,76.08076 + 1591.288,72.46291 + 1615.981,69.52535 + 1637.034,63.16708 + 1654.957,61.31534 + 1674.975,72.86595 + 1695.262,64.75288 + 1709.799,54.75394 + 1712.769,24.54955 + 1702.061,5.766651 + 1685.925,4.414207 + 1669.991,5.575367 + 1656.502,12.07608 + 1644.88,11.30247 + 1634.482,15.56817 + 1624.607,12.47053 + 1610.151,-0.5362444 + 1594.136,6.376687 + 1580.163,5.485111 + 1564.78,1.025784 + 1550.539,8.4501 + 1539.777,11.6633 + 1532.066,17.71403 + 1521.599,2.418658 + 1504.309,-4.049212 + 1481.361,-14.07779 + 1453.792,-17.15281 + 1423.724,-18.15207 + 1385.246,-16.81612 + 1337.242,-15.72801 + 1293.188,-15.42869 + 1281.755,38.3059 + 1286.484,11.6914 + 1283.596,17.9171 + 1285.597,24.78118 + 1291.778,29.405 + 1303.359,40.06316 + 1321.147,47.6144 + 1343.046,53.40984 + 1367.31,56.75732 + 1398.372,76.35516 + 1441.017,95.91759 + 1491.115,106.3325 + 1533.099,77.92695 + 1561.824,69.6596 + 1584.033,60.08042 + 1597.119,41.62484 + 1603.93,40.29163 + 1607.558,31.45644 + 1604.965,19.52167 + 1600.142,23.70411 + 1596.299,22.48869 + 1589.192,12.48158 + 1578.793,11.02395 + 1566.889,6.910674 + 1551.426,-1.123854 + 1528.707,-15.20682 + 1502.589,-11.37927 + 1476.041,-16.47795 + 1439.148,-17.79036 + 1386.845,-16.22873 + 1331.801,-15.54598 + 1276.609,-14.19835 + 1222.116,-13.53877 + 1183.826,-13.63705 + 1165.594,4.323093 + 1154.524,-0.2198782 + 1145.307,8.251244 + 1136.212,-0.1459947 + 1127.318,8.395197 + 1127.425,20.90548 + 1132.316,19.78157 + 1134.976,15.85121 + 1140.847,27.66578 + 1153.503,32.64259 + 1173.508,46.8272 + 1195.77,39.98267 + 1214.31,39.54551 + 1235.31,48.15401 + 1262.019,56.77373 + 1290.77,56.59818 + 1317.063,53.30949 + 1343.879,61.21212 + 1364.448,38.20493 + 1372.416,26.90753 + 1376.097,26.42333 + 1374.269,11.18833 + 1368.546,15.03598 + 1362.863,11.02519 + 1356.038,11.46854 + 1346.136,1.988382 + 1325.11,-16.2194 + 1284.63,-14.65078 + 1238.373,-14.2102 + 1193.929,-12.98282 + 1155.988,-13.10039 + 1137.273,2.958799 + 1132.786,15.8914 + 1141.075,33.33242 + 1156.7,34.19608 + 1179.433,52.38899 + 1213.827,66.11726 + 1258.176,83.05579 + 1305.898,81.63163 + 1353.754,91.2124 + 1396.935,75.19558 + 1438.893,94.76639 + 1487.004,100.8023 + 1529.298,83.95088 + 1563.974,82.77102 + 1596.393,81.57443 + 1624.446,72.54066 + 1640.138,42.54347 + 1643,29.84203 + 1638.257,16.47232 + 1629.605,16.00256 + 1630.478,48.60144 + 1642.785,55.60721 + 1656.623,55.29026 + 1669.48,53.73763 + 1680.188,49.11893 + 1689.163,48.75134 + 1695.907,42.08216 + 1700.851,42.99605 + 1706.79,46.16529 + 1713.763,47.34768 + 1720.427,45.77478 + 1727.319,48.89489 + 1725.733,15.54477 + 1714.932,15.2667 + 1703.74,13.40421 + 1690.842,8.433504 + 1676.749,8.346373 + 1663.421,10.28855 + 1648.951,3.619027 + 1633.192,5.002003 + 1617.433,2.826547 + 1602.775,7.905733 + 1589.501,6.74611 + 1576.428,7.864722 + 1567.118,18.46364 + 1564.686,30.00007 + 1567.427,35.38074 + 1572.196,36.95614 + 1576.469,34.14531 + 1576.307,22.5677 + 1570.826,16.47429 + 1563.423,15.84486 + 1553.562,7.964062 + 1536.916,-5.952643 + 1517.233,-2.275624 + 1497.389,-6.935693 + 1471.863,-18.41763 + 1442.372,-18.13165 + 1414.871,-13.40553 + 1387.812,-17.13374 + 1362.057,-10.3961 + 1346.257,8.515593 + 1345.787,31.16553 + 1358.712,46.74545 + 1379.066,53.84549 + 1401.382,54.66264 + 1424.557,58.96523 + 1447.437,56.39186 + 1469.605,59.47992 + 1493.117,63.22589 + 1515.124,57.4621 + 1535.841,61.76757 + 1557.969,64.56117 + 1578.323,58.54613 + 1596.594,60.07353 + 1611.991,50.88236 + 1621.194,40.61778 + 1619.421,14.21795 + 1605.113,-1.868717 + 1588.762,6.50421 + 1576.67,11.31663 + 1569.348,21.61535 + 1567.91,30.3064 + 1571.135,36.95245 + 1576.267,36.91877 + 1582.797,42.09142 + 1590.294,40.76203 + 1597.817,42.91198 + 1605.462,41.89369 + 1612.273,40.82465 + 1619.582,44.26139 + 1628.167,45.92483 + 1637.464,47.59579 + 1648.723,53.73099 + 1661.419,53.84293 + 1676.91,65.1045 + 1695.235,65.79607 + 1711.21,58.91008 + 1724.968,59.73791 + 1739.437,63.20061 + 1753.772,61.00745 + 1768,64.61153 + 1781.368,59.52817 + 1794.521,65.5128 + 1809.072,66.50668 + 1818.449,47.4547 + 1817.24,26.92148 + 1805.995,8.979017 + 1786.662,-4.010155 + 1765.233,-0.05493259 + 1742.89,-7.886769 + 1721.609,2.619378 + 1703.539,1.704347 + 1687.591,9.187813 + 1675.688,15.12251 + 1669.373,28.10153 + 1666.148,25.54206 + 1659.176,14.7161 + 1647.474,8.565833 + 1631.875,0.5784202 + 1615.068,3.583271 + 1599,2.292942 + 1587.324,17.45128 + 1584.315,30.57986 + 1586.8,35.61685 + 1593.088,43.5732 + 1602.506,46.77898 + 1611.978,44.69442 + 1618.292,36.94254 + 1621.436,34.45127 + 1619.475,19.75505 + 1612.367,16.75193 + 1602.009,8.288825 + 1592.927,20.35848 + 1589.178,25.61557 + 1589.299,33.05613 + 1592.766,36.86369 + 1600.84,48.93576 + 1611.79,47.39437 + 1614.947,23.44294 + 1610.836,22.92943 + 1603.433,12.01165 + 1586.975,-7.003079 + 1563.772,-9.861372 + 1540.355,-8.272071 + 1519.907,-2.04369 + 1503.677,3.384114 + 1487.904,-1.296515 + 1471.513,0.8036427 + 1454.625,-3.150111 + 1435.789,-5.048037 + 1415.583,-7.256803 + 1396.787,-1.866434 + 1379.012,-5.011639 + 1361.345,-2.060575 + 1341.192,-11.55893 + 1317.613,-10.92163 + 1291.294,-15.20063 + 1254.361,-14.80647 + 1210.226,-14.88861 + 1174.65,-14.81055 + 1147.215,-14.28176 + 1119.552,-13.7853 + 1087.993,-13.05181 + 1052.511,-12.44097 + 1031.579,5.715624 + 1037.853,32.76339 + 1064.428,51.27643 + 1098.567,52.62703 + 1138.801,70.14542 + 1186.926,77.43063 + 1233.348,72.79241 + 1273.076,66.44997 + 1304.85,56.3991 + 1335.952,68.81242 + 1369.93,68.46135 + 1401.744,66.97513 + 1432.914,70.78075 + 1462.162,65.10287 + 1490.927,73.24111 + 1519.369,67.75407 + 1544.292,65.61349 + 1569.657,72.50694 + 1591.342,56.41633 + 1604.709,47.0724 + 1608.203,24.27454 + 1601.539,12.98722 + 1592.376,15.38727 + 1589.407,33.14979 + 1593.76,39.76634 + 1602.748,49.21623 + 1614.531,50.16054 + 1628.221,57.05817 + 1646.023,65.98457 + 1665.665,65.65594 + 1683.789,63.0876 + 1698.339,55.09802 + 1707.865,46.70007 + 1711.465,34.71091 + 1712.298,37.05171 + 1713.763,37.07273 + 1717.041,43.76989 + 1723.678,49.61529 + 1733.472,56.02866 + 1744.677,55.90408 + 1750.736,38.25808 + 1755.6,52.16808 + 1767.544,65.1767 + 1784.929,74.09778 + 1810.361,98.34163 + 1843.734,108.7761 + 1876.234,100.4823 + 1900.229,80.1554 + 1920.624,89.84477 + 1923.486,11.55359 + 1384.726,-6.716908 + 1365.214,-9.758064 + 1335.167,-15.65223 + 1305.561,-9.438278 + 1293.54,25.59272 + 1293.716,51.81037 + 1298.87,51.8591 + 1307.468,70.9785 + 1321.719,83.69244 + 1340.242,97.09694 + 1361.364,102.0721 + 1381.797,98.08289 + 1396.943,76.64746 + 1408.093,78.5398 + 1421.649,92.87965 + 1436.79,90.6324 + 1452.067,97.12432 + 1465.261,81.55907 + 1474.817,78.22183 + 1481.586,66.6988 + 1486.936,71.00793 + 1494.076,78.64029 + 1504.805,94.48131 + 1519.545,105.7961 + 1533.59,93.55258 + 1544.594,90.03146 + 1553.279,81.37687 + 1560.448,82.33672 + 1566.855,78.04972 + 1572.087,76.19854 + 1574.895,63.56385 + 1574.396,55.5367 + 1573.515,61.01888 + 1573.036,57.94503 + 1570.845,49.96451 + 1566.747,45.35576 + 1559.803,31.16218 + 1548.662,17.72969 + 1536.094,20.5824 + 1523.252,14.39674 + 1509.539,13.54565 + 1497.577,23.35009 + 1487.474,23.31975 + 1479.131,32.58831 + 1472.793,34.21489 + 1471.189,59.98996 + 1474.25,61.94712 + 1479.943,76.42569 + 1487.386,73.62328 + 1493.87,72.10479 + 1498.252,62.06528 + 1504.355,83.55563 + 1514.009,85.13411 + 1522.518,78.52847 + 1528.054,68.42541 + 1531.879,68.98322 + 1535.693,69.12019 + 1539.86,71.95422 + 1543.156,64.46819 + 1544.232,58.62698 + 1542.999,50.14769 + 1540.877,52.80785 + 1538.393,47.5109 + 1535.83,51.87814 + 1534.607,55.44809 + 1535.527,65.06208 + 1540.046,78.20454 + 1545.102,69.33004 + 1542.54,31.26162 + 1534.764,36.16859 + 1527.125,30.95866 + 1517.892,25.15287 + 1508.043,25.83571 + 1498.927,28.26935 + 1490.525,28.91031 + 1483.571,35.82453 + 1480.344,50.35513 + 1480.471,55.54207 + 1481.576,56.2795 + 1481.869,50.83329 + 1480.745,47.77131 + 1478.28,42.57355 + 1476.333,50.48153 + 1475.023,46.08316 + 1474.094,52.55144 + 1473.565,48.33829 + 1472.754,50.75901 + 1472.802,53.36675 + 1472.646,49.53503 + 1472.675,54.45502 + 1472.744,49.77462 + 1473.644,59.45992 + 1476.216,59.98241 + 1477.918,54.67937 + 1478.984,56.45734 + 1479.639,52.3883 + 1481.234,62.24279 + 1484.403,62.18639 + 1488.227,66.80893 + 1491.239,57.95909 + 1493.107,60.41497 + 1495.973,64.38061 + 1498.477,58.73077 + 1499.935,58.45076 + 1498.233,39.69763 + 1490.447,21.17598 + 1479.659,20.41969 + 1469.35,22.65018 + 1458.865,18.07665 + 1449.143,25.79696 + 1440.174,21.3046 + 1431.009,23.49089 + 1422.334,22.9997 + 1411.819,11.86371 + 1402.048,25.93449 + 1394.321,22.3779 + 1386.849,26.39423 + 1381.039,30.80274 + 1374.056,19.11548 + 1365.478,21.04128 + 1357.8,23.10369 + 1351.413,27.2389 + 1348.342,40.50266 + 1348.86,46.52771 + 1354.67,69.74982 + 1364.49,69.70929 + 1375.415,77.81886 + 1386.575,73.11307 + 1395.456,67.07029 + 1403.241,68.56764 + 1410.313,64.41555 + 1416.035,62.10302 + 1420.035,55.49044 + 1423.057,57.14668 + 1424.515,46.92026 + 1424.466,48.65111 + 1424.349,46.51535 + 1420.514,27.12698 + 1412.171,19.98239 + 1399.202,-0.2213111 + 1381.088,-8.825974 + 1360.959,-10.97501 + 1339.52,-15.13851 + 1315.038,-15.79168 + 1271.67,-13.71585 + 1205.943,-12.13631 + 1122.19,-10.03683 + 1048.169,-10.36391 + 990.1788,-9.246284 + 928.2859,-9.212884 + 867.8992,-9.020022 + 804.412,-8.525709 + 729.0021,-8.260065 + 887.2314,-7.793596 + 782.4908,-7.821894 + 665.2287,-6.784316 + 772.3559,-4.63562 + 600,-6.277975 + 614.9388,-5.288214 + 696.7551,-3.49948 + 600,-1.283326 + 664.3683,-1.597912 + 600,-1.778763 + 600,-0.7596555 + 600,-0.1736608 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 644.4445,1.612164 + 644.4445,6.538949 + 785.0072,0.8882241 + 841.1434,3.194654 + 644.4445,4.281434 + 1009.552,-0.1017489 + 970.5985,0.5266633 + 942.8003,0.3860083 + 644.4445,2.60547 + 644.4445,3.600683 + 614.3267,0.6870103 + 645.5776,1.867147 + 654.6205,4.423994 + 692.8177,1.993502 + 708.7716,2.477404 + 728.2538,2.476002 + 755.4572,3.501919 + 778.621,2.18979 + 785.3195,1.743106 + 784.5526,1.346341 + 785.7797,1.974449 + 787.5695,1.416916 + 784.4503,1.4051 + 782.5583,1.548533 + 779.4391,1.255069 + 775.604,1.452504 + 776.0643,1.739155 + 781.2288,2.003658 + 791.558,2.376166 + 794.8305,1.215703 + 790.2285,1.457595 + 788.5922,1.549223 + 777.0869,0.305099 + 717.4133,-3.12269 + 620.5139,-2.686603 + 644.4445,1.54447 + 1016.479,0.8481472 + 962.2321,-0.9291403 + 847.3507,-1.475364 + 747.673,-0.2668786 + 676.963,-0.3898878 + 602.3846,-0.3104959 + 600,-0.1901872 + 600,0.1421087 + 644.4445,0.9691319 + 658.5208,5.586625 + 644.4445,10.10435 + 770.7463,12.22105 + 927.217,10.38821 + 1058.376,12.88986 + 1195.672,14.52883 + 1370.653,24.36733 + 1588.996,29.57337 + 1850.804,44.95491 + 2070.22,25.92677 + 2149.734,8.226243 + 1319.83,16.38028 + 1416.364,49.23381 + 1559.182,49.06653 + 1710.518,65.96037 + 1919.854,106.5468 + 2084.814,43.9015 + 2166.125,47.40614 + 1477.623,84.04178 + 1568.573,75.32056 + 1632.52,51.08742 + 1672.844,42.69801 + 1694.081,22.06184 + 1716.868,46.75986 + 1754.409,48.50185 + 1799.228,62.44069 + 1858.482,78.40761 + 1900.06,34.26859 + 1927.36,55.25987 + 1337.101,81.45631 + 1385.247,97.38922 + 1429.335,76.56412 + 1463.264,73.28956 + 1495.965,77.56803 + 1528.196,76.33263 + 1558.654,76.35077 + 1587.647,75.73126 + 1612.448,66.08598 + 1634.75,70.53711 + 1654.379,59.56525 + 1669.87,58.48478 + 1687.604,69.47137 + 1707.072,66.88885 + 1722.079,55.75189 + 1724.041,21.08878 + 1712.486,6.930377 + 1696.472,4.276927 + 1677.568,-3.706191 + 1660.694,10.34586 + 1651.074,20.23409 + 1643.645,17.34347 + 1632.816,8.011366 + 1618.776,5.67132 + 1603.688,3.707242 + 1588.144,3.373533 + 1571.404,-0.8783412 + 1555.752,6.147068 + 1543.593,9.695271 + 1532.576,9.228716 + 1522.379,11.73368 + 1509.777,1.065055 + 1489.946,-10.28071 + 1465.427,-12.51891 + 1440.021,-12.71381 + 1402.846,-16.25399 + 1355.514,-15.46913 + 1313.435,-14.94506 + 1291.697,11.92974 + 1290.622,22.9257 + 1291.334,16.68974 + 1292.651,24.62087 + 1298.683,29.66311 + 1308.639,35.86757 + 1329.033,59.74829 + 1361.923,73.65525 + 1400.414,80.50338 + 1437.67,75.37047 + 1474.187,83.83059 + 1510.207,79.0104 + 1541.698,74.4771 + 1566.836,62.39557 + 1586.464,59.38128 + 1599.685,43.04843 + 1606.496,39.10833 + 1607.544,24.1147 + 1602.614,18.94668 + 1599.308,29.22934 + 1598.395,26.77416 + 1592.524,12.49185 + 1582.703,13.13161 + 1570.221,3.125345 + 1548.953,-14.38402 + 1520.766,-17.64579 + 1492.177,-15.95768 + 1453.188,-19.0262 + 1405.211,-17.32 + 1359.907,-15.5539 + 1311.877,-14.40117 + 1259.963,-13.38175 + 1212.524,-12.87038 + 1177.001,-12.74935 + 1155.424,-1.723226 + 1141.801,-0.260747 + 1134.492,12.46988 + 1133.995,15.73124 + 1130.65,5.669389 + 1126.767,14.28826 + 1128.648,19.20252 + 1133.216,20.79155 + 1142.795,31.54515 + 1160.919,42.30621 + 1179.715,34.65625 + 1197.906,42.59779 + 1221.082,49.09034 + 1245.937,49.3044 + 1271.692,54.20898 + 1300.591,60.77997 + 1329.168,56.62835 + 1354.789,55.80923 + 1375.788,46.10873 + 1385.73,25.64256 + 1386.025,18.74092 + 1383.688,17.9726 + 1379.388,12.89893 + 1372.698,10.80366 + 1364.207,7.388607 + 1349.334,-6.829912 + 1327.031,-12.3538 + 1289.95,-14.04064 + 1243.626,-13.43234 + 1200.889,-12.65873 + 1162.021,-12.30316 + 1138.523,0.8973355 + 1130.394,9.3073 + 1135.07,31.08614 + 1156.795,50.95563 + 1189.187,59.67162 + 1226.563,67.66388 + 1268.951,78.01559 + 1312.414,76.58404 + 1356.025,85.13309 + 1401.126,87.58305 + 1444.898,88.26737 + 1487.286,90.28471 + 1527.847,89.14961 + 1565.344,86.64429 + 1597.481,76.86526 + 1626.864,82.09353 + 1642.073,31.50566 + 1639.99,23.92768 + 1637.76,30.81757 + 1638.123,32.71453 + 1642.126,43.46971 + 1650.376,47.85925 + 1656.905,38.26996 + 1663.717,49.5445 + 1672.006,44.13668 + 1679.073,46.09537 + 1685.71,43.32407 + 1691.084,42.26889 + 1696.646,44.54321 + 1703.364,46.98836 + 1710.511,46.79175 + 1716.906,45.01366 + 1717.444,26.1797 + 1711.129,20.26562 + 1704.439,24.31491 + 1696.458,15.16069 + 1684.38,9.138308 + 1669.212,3.496205 + 1653.412,6.050759 + 1636.148,-2.083723 + 1620.402,10.29929 + 1606.523,3.2822 + 1590.468,2.226402 + 1576.711,10.1251 + 1568.824,20.93763 + 1567.413,31.03271 + 1569.711,33.10635 + 1572.452,32.69432 + 1574.655,31.5523 + 1572.747,19.22354 + 1565.035,12.21235 + 1556.195,15.0088 + 1543.351,-1.151437 + 1523.306,-7.844097 + 1498.451,-15.2105 + 1471.473,-14.222 + 1443.514,-17.75576 + 1418.028,-8.075694 + 1395.819,-9.842525 + 1378.085,3.328753 + 1367.149,8.02681 + 1360.404,14.89146 + 1361.842,31.14586 + 1371.771,39.49014 + 1387.436,48.75327 + 1406.608,51.37 + 1428.548,59.16101 + 1453.08,61.76308 + 1479.238,67.222 + 1503.811,59.92773 + 1525.214,60.14183 + 1544.184,54.53143 + 1562.268,59.49051 + 1582.313,63.16959 + 1599.873,53.45661 + 1613.429,51.63828 + 1621.181,35.03048 + 1616.371,9.457516 + 1600.061,-3.788047 + 1581.856,2.248221 + 1572.667,24.77247 + 1572.022,30.03358 + 1574.01,33.46582 + 1578.242,37.671 + 1584.06,39.13469 + 1589.837,38.06779 + 1595.385,38.90419 + 1601.216,39.5349 + 1606.859,38.81017 + 1614.638,47.36164 + 1624.701,47.38615 + 1636,52.69853 + 1647.057,47.73088 + 1657.59,52.09483 + 1669.158,52.50356 + 1683.198,62.20206 + 1702.491,73.03305 + 1723.463,70.75262 + 1743.683,73.13956 + 1762.667,68.86513 + 1777.58,60.39309 + 1789.188,58.30213 + 1797.921,50.87263 + 1806.855,60.13579 + 1817.388,58.0382 + 1823.299,43.58347 + 1816.582,10.14859 + 1802.529,14.92394 + 1786.299,1.025387 + 1768.927,9.511108 + 1751.623,0.3174438 + 1732.894,3.221305 + 1714.636,1.037209 + 1696.606,3.044764 + 1683.345,16.9832 + 1676.05,23.35215 + 1669.494,19.07921 + 1660.667,14.90462 + 1649.65,10.84701 + 1637.733,11.08645 + 1623.559,2.431441 + 1610.325,13.43634 + 1600.115,11.95773 + 1593.007,23.21765 + 1593.733,37.80044 + 1600.921,45.08272 + 1610.755,47.47602 + 1621.087,47.78857 + 1627.616,35.45415 + 1628.436,28.78426 + 1624.513,19.24914 + 1617.298,17.2322 + 1609.13,15.51832 + 1601.445,18.32353 + 1596.178,23.1551 + 1595.479,33.32108 + 1600.276,41.6428 + 1609.909,50.18336 + 1618.373,38.57851 + 1622.498,36.17999 + 1621.987,23.06949 + 1614.45,12.16186 + 1598.261,-5.880579 + 1576.576,-6.21808 + 1557.216,0.2066689 + 1540.557,1.06763 + 1523.776,-0.7704601 + 1505.168,-4.783222 + 1484.424,-7.280366 + 1461.786,-10.48103 + 1437.992,-10.87021 + 1412.439,-15.4868 + 1386.16,-13.11512 + 1361.533,-11.51401 + 1337.054,-12.97312 + 1311.675,-13.94429 + 1284.644,-14.70514 + 1260.877,-6.438118 + 1239.233,-12.14887 + 1213.585,-13.36887 + 1189.711,-8.318381 + 1167.449,-12.13369 + 1133.834,-11.54234 + 1098.11,-11.47418 + 1073.161,-9.736206 + 1051.866,-8.969399 + 1043.845,17.9187 + 1059.793,42.8426 + 1091.15,54.27356 + 1132.423,69.97617 + 1179.849,74.85709 + 1224.723,70.31767 + 1266.425,73.1416 + 1304.474,66.09874 + 1339.956,71.33346 + 1376.07,72.68569 + 1408.422,65.08088 + 1436.595,64.42775 + 1462.377,61.2652 + 1487.568,65.8431 + 1513.982,68.2971 + 1540.825,70.66122 + 1565.277,63.87906 + 1586.142,61.8507 + 1603.258,53.73509 + 1610.003,28.49205 + 1602.412,5.785827 + 1591.718,17.46236 + 1587.728,27.60659 + 1590.347,39.33879 + 1599.711,50.57925 + 1614.356,58.24709 + 1631.714,61.5585 + 1649.959,63.41554 + 1667.223,60.33664 + 1682.902,59.92071 + 1697.641,58.86283 + 1708.402,47.30275 + 1712.889,37.3675 + 1714.622,37.78582 + 1716.933,39.62757 + 1720.386,42.15772 + 1725.639,46.5316 + 1733.472,52.14337 + 1742.568,52.02161 + 1752.026,54.51895 + 1760.92,50.98923 + 1773.2,68.27187 + 1792.224,77.96797 + 1821.486,110.3905 + 1859.212,115.6734 + 1886.512,75.2928 + 1904.73,83.84886 + 1920.543,68.10039 + 1923.083,32.01192 + 1906.866,-6.502386 + 1369.067,-8.091158 + 1347.198,-16.18642 + 1322.599,-15.63903 + 1300.348,-10.72464 + 1291.3,42.13477 + 1295.232,54.72806 + 1305.844,78.21381 + 1323.205,92.89117 + 1342.943,94.77242 + 1363.46,101.6814 + 1385.072,105.6614 + 1401.614,77.6887 + 1414.802,90.22686 + 1429.796,90.92907 + 1445.416,97.26785 + 1460.968,94.02265 + 1474.025,85.8418 + 1482.309,68.04903 + 1486.554,63.08653 + 1491.151,71.01434 + 1497.039,71.83271 + 1507.27,98.90955 + 1520.142,90.28288 + 1531.712,93.81809 + 1542.735,89.45779 + 1550.501,75.71756 + 1555.763,75.2889 + 1560.967,76.44486 + 1565.573,72.56293 + 1568.879,69.08176 + 1571.598,69.47919 + 1572.166,55.82536 + 1571.677,62.81889 + 1571.921,60.4342 + 1570.689,53.40608 + 1566.415,40.77371 + 1555.499,10.54896 + 1539.664,8.183149 + 1524.034,9.895695 + 1510.967,22.06216 + 1500.463,23.95686 + 1491.063,27.36668 + 1482.349,26.82351 + 1476.999,46.35995 + 1477.996,64.20844 + 1481.899,64.05076 + 1485.909,65.5948 + 1490.075,65.75693 + 1495.259,72.5956 + 1502.116,77.00091 + 1508.6,71.68607 + 1514.263,73.26437 + 1521.178,80.59914 + 1529.15,81.26859 + 1536.368,77.57661 + 1542.686,77.1497 + 1547,66.23773 + 1548.115,57.8325 + 1546.481,49.11549 + 1544.408,54.76034 + 1543.166,53.98143 + 1541.073,49.1928 + 1539.361,55.99929 + 1538.862,56.49809 + 1538.393,56.0927 + 1540.417,72.0712 + 1545.18,73.70837 + 1546.256,49.76416 + 1542.735,44.97318 + 1535.145,23.71458 + 1523.252,17.02971 + 1509.617,11.41548 + 1496.003,15.4281 + 1487.171,38.66481 + 1482.3,38.17532 + 1480.637,57.24352 + 1481.762,54.72427 + 1482.73,56.49815 + 1483.307,52.52861 + 1482.72,49.56577 + 1481.508,48.64921 + 1480.187,48.71376 + 1478.955,48.95982 + 1477.576,47.62597 + 1477.849,58.67931 + 1479.013,53.03189 + 1479.307,53.63831 + 1480.021,55.61882 + 1480.793,54.11613 + 1481.361,54.51465 + 1483.004,60.71709 + 1484.578,54.38765 + 1485.42,56.56187 + 1485.889,52.28399 + 1486.613,58.18631 + 1488.002,56.44076 + 1489.87,61.34771 + 1490.917,51.78019 + 1491.102,56.30661 + 1492.227,57.52043 + 1493.675,58.47193 + 1495.113,57.72102 + 1495.445,51.99366 + 1494.271,48.60529 + 1489.625,30.71955 + 1480.001,17.82528 + 1467.472,12.0361 + 1457.623,32.14432 + 1450.424,26.50847 + 1441.191,19.21676 + 1431.459,22.39477 + 1422.754,23.97624 + 1414.069,21.42962 + 1406.89,31.4945 + 1401.579,31.19041 + 1395.554,26.72908 + 1387.563,19.29863 + 1377.782,15.70328 + 1368.803,22.63366 + 1361.243,22.56006 + 1353.398,20.18481 + 1347.96,34.80918 + 1349.799,59.43176 + 1356.929,64.2579 + 1365.889,70.86021 + 1376.755,76.60091 + 1387.504,72.27655 + 1395.348,62.18171 + 1402.557,70.15619 + 1408.826,58.08114 + 1414.47,67.74133 + 1420.152,59.29419 + 1424.652,61.93027 + 1429.249,60.66118 + 1431.322,48.02657 + 1430.774,45.73412 + 1426.217,24.6445 + 1410.704,-15.22193 + 1391.456,1.596369 + 1375.386,-1.242421 + 1360.089,4.432325 + 1342.327,-12.48885 + 1315.958,-15.63675 + 1278.253,-14.49595 + 1226.61,-12.92336 + 1157.421,-11.01548 + 1084.691,-10.37803 + 1016.333,-9.222387 + 953.2953,-8.877071 + 891.1482,-8.744204 + 1132.584,-10.29824 + 1027.589,-7.797905 + 906.3764,-7.333625 + 778.9708,-6.812672 + 640.4005,-6.574084 + 725.2108,-4.330684 + 600,-6.607558 + 974.2606,0.2646341 + 678.2445,-2.214189 + 600,-2.06674 + 600,-2.121689 + 600,-1.457825 + 600,-0.0909586 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,2.38E-07 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,-2.38E-07 + 600,2.38E-07 + 600,-2.38E-07 + 600,2.38E-07 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,-2.38E-07 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,4.77E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,2.38E-07 + 644.4445,0.07269168 + 644.4445,0.5636628 + 644.4445,6.32637 + 909.8743,8.952326 + 612.8438,0.4596145 + 1049.945,0.5363288 + 644.4445,1.307286 + 644.4445,1.506667 + 644.4445,1.191484 + 644.4445,1.223324 + 644.5549,1.372464 + 645.5549,2.282104 + 647.3238,2.434664 + 660.2452,2.209997 + 681.7216,2.61131 + 706.7773,2.741129 + 730.1458,2.619758 + 748.145,2.314906 + 760.0593,2.050172 + 764.6102,1.540037 + 765.2238,1.621832 + 763.9455,1.326239 + 764.4057,1.815315 + 767.3715,1.615054 + 764.6102,1.172328 + 763.6898,1.813547 + 765.7863,1.513745 + 764.7125,1.459806 + 763.4852,1.49177 + 760.6218,1.268719 + 717.6179,-2.408862 + 665.5632,0.2176919 + 624.9115,-1.213306 + 1023.406,-0.02850914 + 644.4445,2.188613 + 998.4866,-0.7567296 + 913.1129,-0.6905825 + 792.6539,-1.726186 + 682.2707,-0.2418582 + 619.2075,-0.1684604 + 644.4445,0.6611562 + 646.427,1.844816 + 674.444,1.06398 + 698.6438,1.278553 + 843.8422,6.181966 + 645.6003,6.826957 + 727.7936,6.854918 + 867.4923,13.15338 + 1035.213,14.05835 + 1166.934,11.57775 + 1302.747,18.54018 + 1484.631,24.88181 + 1734.831,42.28856 + 2034.273,49.13046 + 2212.783,14.95125 + 1365.991,14.98481 + 1435.985,36.59709 + 1555.953,48.97858 + 1705.628,64.5892 + 1887.01,84.50237 + 2010.176,29.41932 + 1359.912,69.16082 + 1460.599,91.42927 + 1564.59,85.87419 + 1639.38,57.33976 + 1678.83,35.33801 + 1693.723,19.23966 + 1709.133,37.07459 + 1753.812,70.30568 + 1809.11,58.7817 + 1828.497,10.1565 + 1245.703,51.546 + 1279.657,74.22597 + 1325.282,88.26819 + 1368.083,72.68974 + 1405.977,80.60335 + 1446.416,85.91576 + 1481.576,70.02934 + 1508.876,66.10561 + 1538.958,82.82529 + 1572.196,80.56322 + 1601.915,75.8309 + 1627.751,71.48734 + 1648.79,62.65011 + 1666.484,62.48646 + 1683.574,62.6969 + 1701.953,69.27721 + 1717.592,55.01025 + 1723.154,34.47604 + 1716.396,10.84506 + 1701.523,4.702551 + 1681.102,-8.599273 + 1661.836,7.633382 + 1652.243,23.09983 + 1646.547,20.57926 + 1637.236,10.19999 + 1622.242,0.4904656 + 1602.922,-4.652774 + 1584.731,3.380548 + 1570.49,7.09161 + 1557.458,6.66973 + 1543.848,4.555008 + 1531.689,10.66433 + 1519.437,3.691454 + 1503.61,-1.150481 + 1485.728,-3.026744 + 1464.379,-11.14701 + 1436.985,-17.6633 + 1401.435,-16.52778 + 1357.637,-15.3913 + 1312.307,-14.65012 + 1287.908,11.86469 + 1286,20.54327 + 1286.619,18.54342 + 1288.244,23.31835 + 1295.069,32.82963 + 1308.289,41.42417 + 1326.36,47.51019 + 1350.341,60.05747 + 1386.146,84.80302 + 1424.275,71.51812 + 1459.61,82.11712 + 1496.731,82.10949 + 1531.165,78.98655 + 1560.709,71.02921 + 1584.879,65.1485 + 1601.875,49.84313 + 1609.842,36.42356 + 1612.555,32.75125 + 1610.258,19.61487 + 1605.542,24.35468 + 1602.197,23.91504 + 1596.433,15.96346 + 1585.846,7.36155 + 1572.707,6.84079 + 1554.569,-8.548178 + 1529.58,-14.25133 + 1502.374,-15.33138 + 1473.287,-18.2294 + 1433.115,-16.61605 + 1379.361,-15.28753 + 1322.517,-14.32261 + 1269.65,-13.59477 + 1223.823,-13.03917 + 1191.054,-10.34762 + 1167.623,-10.96569 + 1146.087,-7.865382 + 1138.617,20.75992 + 1139.92,11.95193 + 1135.07,6.090739 + 1128.836,8.454925 + 1127.815,18.23122 + 1133.229,23.74462 + 1145.025,33.94183 + 1162.007,37.24741 + 1180.266,38.54793 + 1199.371,41.02165 + 1220.437,45.36328 + 1244.338,50.5095 + 1270.631,54.25564 + 1298.159,56.81184 + 1326.924,60.92234 + 1355.084,58.48366 + 1378.461,50.37475 + 1393.267,35.86261 + 1398.198,22.63688 + 1395.484,13.71113 + 1386.67,4.619095 + 1373.732,1.322395 + 1360.028,1.926163 + 1347.05,2.909883 + 1327.864,-13.99705 + 1303.439,-10.30259 + 1270.98,-13.94411 + 1227.45,-13.10693 + 1189.361,-12.86395 + 1163.257,-9.064267 + 1149.096,6.519079 + 1145.415,14.67137 + 1153.382,34.60891 + 1178.546,57.754 + 1216.998,71.03598 + 1263.134,83.27469 + 1314.765,93.22186 + 1365.711,89.68562 + 1406.138,70.3726 + 1441.432,80.56233 + 1480.152,86.0248 + 1517.623,82.35265 + 1553.777,87.54527 + 1590.871,91.02081 + 1619.381,63.71481 + 1634.092,47.46525 + 1638.526,29.794 + 1635.489,22.06191 + 1635.758,40.95305 + 1643.712,48.7066 + 1653.788,49.15121 + 1663.139,47.23022 + 1672.597,50.53967 + 1682.109,48.42113 + 1690.426,47.30361 + 1696.001,39.47346 + 1699.468,40.3076 + 1704.479,45.37587 + 1710.861,45.75566 + 1718.881,52.00259 + 1722.791,31.61168 + 1716.893,16.77742 + 1706.844,16.1372 + 1696.579,15.30738 + 1686.61,16.48245 + 1676.655,14.68511 + 1666.323,14.48469 + 1653.439,5.125021 + 1638.015,4.899573 + 1622.054,2.485665 + 1605.65,2.586072 + 1589.635,3.008597 + 1576.482,11.31122 + 1568.972,20.98672 + 1568.045,32.59629 + 1571.82,36.49885 + 1575.689,33.22871 + 1577.006,28.33649 + 1576.509,27.30095 + 1573.043,18.44022 + 1566.083,15.48969 + 1553.253,-1.0913 + 1533.543,-6.647263 + 1512.571,-5.314623 + 1489.597,-12.72277 + 1465.037,-10.23271 + 1440.626,-12.70623 + 1416.577,-9.706091 + 1395.107,-6.353202 + 1377.024,-1.41299 + 1362.729,3.233414 + 1354.829,16.14577 + 1363.078,49.1428 + 1386.616,61.25877 + 1414.32,64.14809 + 1440.303,59.41497 + 1460.953,50.86452 + 1479.574,55.51258 + 1498.37,53.43364 + 1516.938,56.92963 + 1538.501,65.29128 + 1562.402,67.20255 + 1585.376,65.22421 + 1607.168,66.15616 + 1622.363,45.26455 + 1626.448,29.70588 + 1619.663,8.417274 + 1605.892,5.471342 + 1590.294,1.554001 + 1574.104,2.731438 + 1564.27,21.70022 + 1562.819,29.79327 + 1568.34,44.64818 + 1577.866,43.57754 + 1587.66,46.50829 + 1597.844,45.86784 + 1605.354,38.47025 + 1610.205,37.56776 + 1614.96,38.60074 + 1622.027,45.92914 + 1631.029,45.93453 + 1640.622,48.91043 + 1652.001,53.17495 + 1664.657,54.63203 + 1677.662,55.84564 + 1692.656,63.26057 + 1711.21,70.51211 + 1732.478,75.57997 + 1753.544,72.63683 + 1769.828,60.5629 + 1783.451,64.80178 + 1796.429,59.79764 + 1807.943,60.86138 + 1820.33,64.59172 + 1828.176,44.81462 + 1821.163,8.214087 + 1804.249,6.292377 + 1787.871,9.134424 + 1770.714,2.376011 + 1754.109,10.06567 + 1738.806,6.212786 + 1721.286,1.067402 + 1704.721,8.612881 + 1690.95,10.14219 + 1679.624,16.43083 + 1669.144,12.42631 + 1658.987,16.84797 + 1647.85,8.391995 + 1632.507,1.645216 + 1616.008,3.606684 + 1600.128,2.947272 + 1589.487,20.32802 + 1587.647,31.78459 + 1590.159,34.78584 + 1594.271,37.37839 + 1600.692,42.96344 + 1610.513,49.539 + 1619.219,40.11499 + 1623.559,35.45469 + 1622.551,22.18125 + 1616.573,18.38556 + 1609.412,17.73681 + 1601.727,16.13419 + 1594.458,18.62502 + 1590.616,27.14091 + 1592.551,37.74634 + 1599.214,43.24936 + 1607.383,43.47301 + 1616.519,47.3689 + 1620.966,28.29967 + 1614.678,11.12828 + 1600.491,1.117563 + 1577.759,-15.98362 + 1550.498,-12.94688 + 1526.638,-6.817096 + 1505.168,-6.72456 + 1484.263,-5.809709 + 1462.727,-8.948511 + 1443.058,-1.342418 + 1426.667,-0.6651244 + 1410.316,-1.713572 + 1393.038,-3.54139 + 1376.876,0.7599344 + 1361.493,-1.957383 + 1339.513,-15.69704 + 1313.126,-13.22394 + 1287.062,-14.71945 + 1250.061,-13.29444 + 1211.717,-13.18758 + 1184.632,-12.68648 + 1156.754,-13.87198 + 1125.974,-13.35509 + 1094.321,-12.72246 + 1054.539,-11.65611 + 1026.366,1.78571 + 1031.707,34.37691 + 1059.625,52.05185 + 1095.194,54.60882 + 1132.853,61.3746 + 1177.447,76.69508 + 1222.979,69.77629 + 1261.898,65.92332 + 1296.198,62.50776 + 1331.935,74.62606 + 1370.172,74.38905 + 1403.021,64.03122 + 1430.133,61.57874 + 1454.451,58.83109 + 1481.079,71.86363 + 1508.285,63.87067 + 1533.275,68.35617 + 1556.074,59.77805 + 1575.649,60.55231 + 1590.562,46.38965 + 1598.476,38.60023 + 1600.316,26.62489 + 1595.412,16.02007 + 1589.635,23.31708 + 1594.485,51.32585 + 1609.062,56.67459 + 1626.676,63.39441 + 1644.746,60.32769 + 1660.559,57.70242 + 1675.096,57.71563 + 1688.518,55.43426 + 1701.389,57.32327 + 1710.565,43.53574 + 1713.427,35.47276 + 1715.402,40.61037 + 1719.432,43.12147 + 1724.444,44.58424 + 1731.376,50.66751 + 1740.593,53.71496 + 1749.258,49.65441 + 1754.552,42.17929 + 1757.723,42.34054 + 1768.121,69.52338 + 1794.468,103.9193 + 1825.61,91.68179 + 1855.813,105.6374 + 1881.836,79.81264 + 1897.179,67.01525 + 1905.496,53.63717 + 1906.692,39.33886 + 1889.011,-19.16266 + 1849.122,-24.79765 + 1807.889,-24.43617 + 1779.689,-0.7561536 + 1284.092,17.17696 + 1284.102,58.07148 + 1292.093,58.99236 + 1304.082,80.69597 + 1321.862,92.27543 + 1340.809,90.74892 + 1359.844,96.99959 + 1378.966,95.45564 + 1393.216,73.59466 + 1402.928,72.61659 + 1413.785,82.11748 + 1426.51,85.63467 + 1440.927,94.76996 + 1455.95,92.36811 + 1470.416,94.86768 + 1480.725,70.45586 + 1486.985,72.58999 + 1494.017,76.40392 + 1505.187,99.43295 + 1520.278,103.0791 + 1537.327,115.3624 + 1552.584,95.87924 + 1562.453,84.82603 + 1568.948,76.54655 + 1573.946,76.64169 + 1578.063,71.93213 + 1579.726,61.67735 + 1579.57,60.54532 + 1578.23,54.0312 + 1574.601,45.59658 + 1570.894,52.8693 + 1567.725,48.39549 + 1563.177,43.51645 + 1555.069,25.0616 + 1541.767,9.581061 + 1527.692,18.39748 + 1515.007,16.44184 + 1501.92,14.32027 + 1490.76,26.46716 + 1483.728,37.81801 + 1478.436,35.96482 + 1475.345,50.22443 + 1478.28,71.72651 + 1485.41,76.1095 + 1492.481,72.78746 + 1498.937,73.78825 + 1505.128,72.46352 + 1511.525,76.31317 + 1517.471,70.96622 + 1522.88,74.19914 + 1528.641,74.2482 + 1535.39,81.57578 + 1541.278,70.22089 + 1544.848,68.2123 + 1547.264,63.6499 + 1547.371,54.11656 + 1545.171,49.12331 + 1542.52,50.89368 + 1539.84,48.48135 + 1537.816,54.52997 + 1536.886,54.98994 + 1537.346,63.06376 + 1541.503,78.29755 + 1548.662,82.82697 + 1550.482,45.99143 + 1544.809,35.92283 + 1533.756,11.44688 + 1518.009,5.243145 + 1503.915,19.64205 + 1492.609,20.55502 + 1483.464,31.21258 + 1479.277,49.16108 + 1478.886,53.42761 + 1479.62,55.8742 + 1479.786,50.1337 + 1479.678,54.25177 + 1479.933,52.29718 + 1480.578,56.65665 + 1480.842,50.10637 + 1480.598,53.63382 + 1479.004,41.93355 + 1476.324,46.8269 + 1474.172,44.68207 + 1472.274,48.00023 + 1472.079,54.57672 + 1472.597,52.24992 + 1474.455,62.71901 + 1477.018,56.80586 + 1479.698,63.90294 + 1482.955,60.77087 + 1485.019,57.28467 + 1487.298,62.45473 + 1490.075,60.72274 + 1492.403,60.23314 + 1493.763,55.25238 + 1493.205,48.80926 + 1492.892,56.64178 + 1493.557,54.70619 + 1494.144,56.28391 + 1494.682,54.51154 + 1494.007,48.99399 + 1492.853,51.47742 + 1488.951,32.13356 + 1476.187,-2.118674 + 1457.887,-2.126604 + 1443.636,19.47982 + 1434.912,28.30535 + 1428.173,29.93163 + 1421.649,28.65341 + 1414.167,23.54668 + 1406.841,28.56202 + 1399.642,23.36224 + 1392.786,29.56185 + 1386.477,25.6082 + 1378.163,17.51092 + 1369.077,20.2835 + 1360.695,20.3895 + 1353.369,25.12762 + 1349.398,37.92805 + 1351.149,56.04457 + 1358.328,68.17207 + 1369.312,78.50098 + 1382.037,80.05802 + 1392.443,67.88512 + 1400.953,71.3244 + 1408.376,63.24284 + 1413.912,61.8568 + 1417.932,55.47812 + 1421.189,58.15731 + 1423.85,52.57276 + 1425.894,55.04035 + 1428.72,57.47088 + 1430.657,50.33347 + 1427.302,27.01298 + 1417.443,12.22586 + 1403.036,-0.1684303 + 1384.237,-11.87013 + 1363.287,-11.63743 + 1342.004,-13.53146 + 1318.618,-16.01462 + 1282.605,-14.39375 + 1220.908,-12.12208 + 1141.722,-10.68284 + 1074.528,-10.48296 + 1022.054,-9.141874 + 960.7875,-8.731186 + 1216.514,-10.74907 + 1109.274,-9.523954 + 1005.743,-8.101731 + 906.0809,-7.618393 + 784.7748,-6.123598 + 636.8536,-6.884468 + 741.9532,-5.764419 + 836.1458,-0.8582449 + 600,-4.675195 + 952.2463,0.009875298 + 664.0984,-1.178708 + 600,-1.123972 + 600,-0.2031865 + 600,-0.6548967 + 600,-0.000296116 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,2.38E-07 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 644.4445,0.2542183 + 644.4445,3.043099 + 644.4944,3.76886 + 862.1945,7.244804 + 644.4445,2.008217 + 644.4445,1.282092 + 644.4445,1.102336 + 644.4445,1.300048 + 644.4445,1.259131 + 644.4445,1.073095 + 645.6724,3.006216 + 618.264,-0.3244839 + 647.7556,5.489882 + 701.8685,2.742796 + 722.4244,2.271123 + 743.2361,2.935951 + 762.5648,2.234797 + 772.9451,2.039693 + 780.2573,1.936579 + 786.3934,1.940598 + 781.9448,0.7246585 + 771.7178,1.247691 + 769.2634,1.590314 + 768.7009,1.456245 + 766.1954,1.364901 + 764.2012,1.504721 + 766.3488,1.831629 + 768.0362,1.460694 + 768.0362,1.645372 + 773.3542,2.075679 + 774.5814,1.194392 + 764.559,0.7873244 + 745.3326,0.1385179 + 715.4191,-0.332602 + 677.2729,-0.594053 + 635.803,-0.5641029 + 981.9337,-3.01793 + 839.9738,-0.6091862 + 727.9713,-1.361682 + 620.287,-0.3443129 + 600,-0.198132 + 600,-0.2130547 + 644.4445,1.156704 + 644.4445,2.928335 + 840.5137,7.855536 + 645.6799,4.915875 + 718.7428,7.940886 + 919.598,20.71529 + 1104.653,9.702165 + 1177.315,7.127035 + 1343.756,30.38393 + 1513.062,9.906143 + 1007.81,36.38819 + 1161.267,39.11203 + 1278.037,27.3871 + 1383.305,40.41537 + 1511.207,46.64371 + 1596.608,19.454 + 1075.369,38.91386 + 1144.645,51.12838 + 1236.03,71.91323 + 1345.194,84.24624 + 1462.489,97.86935 + 1569.923,84.68086 + 1640.951,52.99866 + 1686.982,50.89439 + 1708.258,14.60182 + 1146.06,-3.260405 + 1143.091,26.43259 + 1164.452,55.55766 + 1202.272,69.78938 + 1248.732,83.18002 + 1301.019,92.7276 + 1354.342,94.76001 + 1401.919,84.77892 + 1438.704,69.75992 + 1467.953,66.90834 + 1497.591,74.95674 + 1527.323,71.09368 + 1554.516,70.7477 + 1580.204,69.72466 + 1607.732,80.51578 + 1633.071,65.80466 + 1652.807,64.51868 + 1671.334,64.05013 + 1689.244,64.65747 + 1706.105,62.52456 + 1720.534,57.92768 + 1723.772,23.39667 + 1706.911,-12.77224 + 1685.898,7.341925 + 1671.979,9.75246 + 1662.279,21.29147 + 1658.504,29.84188 + 1653.587,17.03524 + 1638.794,-4.186825 + 1617.648,-4.962307 + 1597.884,-0.8135309 + 1580.257,0.750226 + 1562.563,-1.659951 + 1548.537,11.91162 + 1540.033,15.42424 + 1535.115,23.01572 + 1531.448,19.15309 + 1516.118,-12.86069 + 1492.284,-7.591835 + 1467.55,-15.70515 + 1435.373,-17.46522 + 1392.904,-16.13951 + 1347.977,-15.4994 + 1312.535,-15.2666 + 1292.543,4.540256 + 1286.511,16.9544 + 1287.236,22.45613 + 1293.9,33.18174 + 1303.345,30.53206 + 1313.502,35.92642 + 1331.949,54.6626 + 1359.692,64.28005 + 1396.867,85.87479 + 1437.925,80.98814 + 1474.281,77.60077 + 1509.642,83.28379 + 1543.23,76.9175 + 1570.127,65.98427 + 1588.654,52.43436 + 1600.84,46.78295 + 1606.805,32.59529 + 1605.65,23.18912 + 1600.504,19.00929 + 1594.781,20.86993 + 1590.656,23.9784 + 1587.486,23.77216 + 1582.017,16.08064 + 1572.358,9.474892 + 1555.805,-6.293793 + 1535.33,-3.614192 + 1510.986,-17.70457 + 1482.517,-15.38637 + 1448.754,-17.3886 + 1398.587,-15.64723 + 1329.799,-13.74466 + 1273.492,-14.25001 + 1241.248,-13.40315 + 1205.269,-12.6376 + 1165.85,-12.21276 + 1135.151,-12.03583 + 1120.372,9.679996 + 1120.828,20.11432 + 1124.12,16.3987 + 1126.471,18.06844 + 1130.287,20.00859 + 1140.336,33.27053 + 1156.029,34.36275 + 1172.272,35.92491 + 1186.231,29.97521 + 1199.088,34.3232 + 1218.381,47.54738 + 1244.808,54.75484 + 1274.137,58.20295 + 1304.004,59.67457 + 1330.377,51.92756 + 1355.218,58.4916 + 1371.65,30.14645 + 1375.962,24.95364 + 1378.676,25.82015 + 1379.214,18.80646 + 1374.31,10.07271 + 1365.201,6.415627 + 1355.783,8.765409 + 1346.029,5.078839 + 1331.237,-5.104489 + 1306.892,-15.03027 + 1262.704,-13.15916 + 1218.341,-13.36216 + 1187.789,-12.82549 + 1158.756,-12.40262 + 1140.404,3.783212 + 1146.194,39.93061 + 1168.859,45.34202 + 1196.469,54.62985 + 1230.943,66.16975 + 1267.379,64.01351 + 1307.698,81.99072 + 1350.247,75.75098 + 1391.923,86.11143 + 1438.113,95.74863 + 1481.187,83.65627 + 1522.688,98.04447 + 1564.162,89.97185 + 1600.074,86.14787 + 1628.449,69.52667 + 1645.015,49.09846 + 1644.383,11.60987 + 1636.161,22.72835 + 1636.631,41.04108 + 1644.504,48.4262 + 1655.387,52.34411 + 1667.573,54.19073 + 1678.724,50.02793 + 1685.71,40.58485 + 1688.384,35.37016 + 1693.812,50.70958 + 1703.243,50.27459 + 1708.913,38.13729 + 1712.647,43.88169 + 1719.594,50.16351 + 1728.071,50.19448 + 1728.891,23.06607 + 1720.413,16.42023 + 1711.479,20.75814 + 1701.872,13.39018 + 1689.687,10.86072 + 1670.811,-9.679937 + 1650.241,3.8373 + 1635.127,7.068507 + 1619.717,2.065735 + 1602.99,1.803795 + 1589.608,12.44946 + 1580.634,15.81511 + 1574.991,22.96172 + 1575.542,36.00331 + 1579.236,33.46876 + 1581.762,32.42493 + 1582.434,27.48787 + 1578.618,17.52039 + 1570.772,13.83211 + 1562.375,15.1992 + 1551.869,6.441697 + 1534.793,-5.906759 + 1512.289,-10.30744 + 1486.695,-15.03363 + 1458.857,-16.87653 + 1432.135,-12.41042 + 1407.629,-11.31777 + 1384.171,-10.03571 + 1369.003,10.59928 + 1365.08,20.52546 + 1370.091,36.15165 + 1380.638,36.95204 + 1393.63,44.27267 + 1412.734,56.37016 + 1440.572,72.8304 + 1467.684,57.35134 + 1491.37,65.70872 + 1518.066,69.83893 + 1541.604,58.79247 + 1561.153,59.73059 + 1579.048,55.58046 + 1595.762,57.87779 + 1611.924,55.62059 + 1625.601,51.2132 + 1629.645,23.90257 + 1619.246,2.099785 + 1602.936,3.149794 + 1587.781,5.188667 + 1575.542,12.07873 + 1570.329,27.7652 + 1573.903,40.86924 + 1581.722,42.21673 + 1589.689,42.11393 + 1595.95,37.23134 + 1600.491,36.9001 + 1604.898,37.1901 + 1610.715,42.10384 + 1618.87,45.72244 + 1628.409,47.67087 + 1640.151,54.35364 + 1653.022,52.86154 + 1665.678,55.06348 + 1679.879,59.78596 + 1695.907,63.27319 + 1713.198,66.3249 + 1731.269,68.31712 + 1748.775,66.57999 + 1763.997,62.08349 + 1779.34,69.02579 + 1793.984,61.35672 + 1805.202,57.85924 + 1812.82,48.92445 + 1819.578,55.46923 + 1825.906,48.01827 + 1821.056,13.10841 + 1805.565,6.840103 + 1788.691,6.806072 + 1772.488,8.286536 + 1756.487,6.550629 + 1737.798,-2.249373 + 1717.807,0.735312 + 1700.731,6.919925 + 1685.226,5.433849 + 1672.436,15.57636 + 1664.362,21.22834 + 1658.961,24.37656 + 1650.268,9.386177 + 1634.71,0.04979086 + 1614.544,-6.336586 + 1598.381,12.57801 + 1590.025,18.29753 + 1584.288,20.81376 + 1584.234,36.87918 + 1596.608,62.62403 + 1613.859,54.64594 + 1622.457,34.95087 + 1624.271,32.25559 + 1624.661,30.22398 + 1624.849,31.59747 + 1621.624,18.55824 + 1611.064,6.372733 + 1598.986,12.73059 + 1591.785,22.058 + 1592.013,37.18653 + 1598.704,43.85127 + 1607.947,46.47419 + 1618.319,48.64143 + 1621.906,24.24795 + 1615.068,13.35699 + 1603.111,6.432739 + 1588.722,4.500189 + 1572.573,-0.115675 + 1553.629,-4.783992 + 1532.751,-6.315992 + 1514.761,3.077488 + 1500.399,3.732917 + 1482.651,-7.154562 + 1463.519,-1.135713 + 1440.935,-16.81416 + 1414.158,-12.81345 + 1390.943,-7.845296 + 1368.922,-10.04424 + 1346.889,-8.254794 + 1323.471,-13.71456 + 1296.762,-14.93286 + 1265.673,-14.07961 + 1236.546,-11.97013 + 1207.23,-12.98112 + 1174.139,-12.54039 + 1146.973,-10.93499 + 1124.362,-10.41155 + 1093.918,-11.0197 + 1057.509,-10.56761 + 1037.759,6.854196 + 1046.344,37.0987 + 1073.335,48.63685 + 1107.407,56.2469 + 1148.129,68.77713 + 1192.304,70.15498 + 1231.884,63.05749 + 1264.786,57.78709 + 1296.44,63.90317 + 1332.419,73.914 + 1371.166,76.68737 + 1406.42,69.01247 + 1434.862,60.98241 + 1458.468,57.80101 + 1482.987,66.75755 + 1509.669,67.63638 + 1535.465,67.33713 + 1560.091,67.14167 + 1583.253,65.62291 + 1599.443,46.44219 + 1606.684,37.13651 + 1604.884,16.46138 + 1593.343,4.168659 + 1584.033,23.15694 + 1588.211,48.71681 + 1600.585,51.11957 + 1617.836,66.74638 + 1638.794,65.8931 + 1658.92,66.52989 + 1676.91,60.87619 + 1691.756,57.56428 + 1704.331,54.48838 + 1710.861,37.12782 + 1711.546,34.04327 + 1710.229,29.95877 + 1712.661,47.48108 + 1721.461,53.3045 + 1730.906,50.78699 + 1740.176,53.73991 + 1751.045,57.7492 + 1757.951,40.23434 + 1759.778,39.63506 + 1772.192,80.07209 + 1797.208,88.74728 + 1826.631,100.872 + 1858.271,102.1546 + 1885.397,88.15533 + 1904.448,74.06339 + 1916.432,62.34672 + 1919.401,39.03856 + 1902.46,-15.46535 + 1863.511,-25.07789 + 1823.273,-21.13098 + 1791.996,-14.05958 + 1770.969,13.06777 + 1286.498,48.0114 + 1294.058,67.24074 + 1306.597,75.67068 + 1322.628,88.41093 + 1342.258,98.59779 + 1363.062,99.24053 + 1378.535,73.31172 + 1388.825,73.33134 + 1401.598,89.55661 + 1416.387,87.50754 + 1432.163,98.61768 + 1449.387,99.54861 + 1465.027,93.16014 + 1475.385,71.32512 + 1479.141,55.54146 + 1483.825,77.69683 + 1492.922,83.2123 + 1504.218,93.1139 + 1517.188,96.03044 + 1530.509,98.30925 + 1543.136,94.77704 + 1552.281,79.19598 + 1557.964,74.84485 + 1563.461,79.22526 + 1569.339,78.43729 + 1574.591,76.46247 + 1577.222,62.67551 + 1577.242,60.19896 + 1575.687,52.56088 + 1572.498,49.43146 + 1569.329,52.1115 + 1564.947,41.14471 + 1554.462,12.68271 + 1539.967,14.31148 + 1525.981,14.02893 + 1511.818,11.48827 + 1497.929,13.95845 + 1487.532,30.92048 + 1481.38,38.22163 + 1478.329,48.67535 + 1478.162,55.10718 + 1479.678,58.7858 + 1483.914,71.81812 + 1490.819,75.78394 + 1498.35,77.02534 + 1505.099,72.51969 + 1511.202,74.43957 + 1517.911,77.50984 + 1525.814,83.25037 + 1532.593,72.12448 + 1537.16,70.83592 + 1542.236,76.25439 + 1544.985,57.17952 + 1544.32,55.29839 + 1544.476,62.22943 + 1544.496,54.4649 + 1542.745,51.09521 + 1539.38,44.02723 + 1535.742,48.7935 + 1534.999,61.51359 + 1537.258,67.46387 + 1540.965,71.03705 + 1547.939,88.8294 + 1549.738,39.71848 + 1538.647,8.12237 + 1524.67,20.05622 + 1512.2,15.72904 + 1500.873,25.39976 + 1490.78,21.78333 + 1482.358,34.10342 + 1478.485,47.99138 + 1477.977,53.7555 + 1477.801,49.90863 + 1479.15,62.92201 + 1481.243,54.62078 + 1481.116,49.8967 + 1480.324,50.58609 + 1479.63,50.35303 + 1477.321,40.75677 + 1473.565,41.27589 + 1470.426,43.86224 + 1468.401,47.451 + 1466.954,46.9868 + 1467.658,60.07456 + 1470.602,60.51458 + 1475.668,73.382 + 1481.801,67.88359 + 1484.911,56.28338 + 1485.674,54.24988 + 1486.251,55.29283 + 1486.691,53.52103 + 1486.77,53.17738 + 1486.721,52.76431 + 1487.024,55.30242 + 1487.669,54.89172 + 1489.019,59.68992 + 1490.731,57.32771 + 1492.951,63.0985 + 1495.279,58.38214 + 1494.584,45.10869 + 1487.405,18.9328 + 1470.866,-10.28922 + 1452.928,8.639071 + 1440.017,15.75091 + 1429.552,21.4329 + 1422.607,34.86482 + 1417.512,31.21866 + 1412.484,34.53926 + 1407.31,29.69863 + 1401.344,29.30284 + 1395.877,31.73983 + 1390.937,31.57141 + 1385.724,29.53498 + 1378.741,20.95574 + 1371.111,25.03376 + 1363.707,21.31329 + 1355.785,21.27985 + 1349.271,28.11312 + 1347.491,46.42329 + 1354.044,73.73386 + 1364.627,69.82935 + 1374.183,70.02986 + 1382.281,63.41209 + 1390.106,70.01546 + 1398.41,67.56463 + 1404.523,59.0325 + 1409.433,61.78816 + 1413.688,56.11639 + 1417.443,59.66835 + 1421.248,57.04577 + 1423.116,49.10121 + 1423.185,46.9263 + 1420.573,33.6044 + 1411.956,11.98207 + 1397.891,1.452831 + 1383.142,6.65378 + 1367.718,-3.068421 + 1348.968,-9.861969 + 1325.562,-16.11518 + 1284.092,-14.13637 + 1214.697,-11.85796 + 1141.781,-11.37294 + 1079.028,-10.51758 + 1008.215,-8.903414 + 930.7995,-8.72839 + 857.0523,-8.130159 + 789.291,-8.076338 + 726.7427,-8.857965 + 898.0064,-7.569747 + 769.9961,-6.515765 + 649.1603,-7.147186 + 784.9226,-4.621058 + 892.3317,-0.6631382 + 608.6652,-4.717086 + 600,-6.420379 + 606.6129,-1.587289 + 600,-0.7637906 + 600,-0.8728795 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,-2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,-2.38E-07 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 600,0 + 600,-2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 644.4445,0.1401868 + 644.4445,4.115141 + 723.5632,6.148651 + 878.7474,0.996314 + 644.4445,5.992946 + 614.2244,0.8715067 + 1054.623,0.2505918 + 1032.132,1.002764 + 644.4445,1.849404 + 644.4445,1.160477 + 644.4445,1.181648 + 646.017,3.313942 + 655.8477,2.47095 + 673.5912,1.926634 + 697.6755,3.281785 + 729.89,2.964346 + 753.4118,2.586441 + 769.7236,2.314295 + 781.3311,2.144838 + 788.3876,1.845007 + 788.5922,1.371453 + 785.2173,1.424252 + 785.7797,1.820931 + 787.4161,1.552712 + 785.6775,1.431036 + 786.0355,1.792017 + 787.007,1.504555 + 785.3195,1.483458 + 784.6548,1.617746 + 783.939,1.474823 + 778.5699,1.072223 + 772.178,1.335513 + 761.5421,0.5722067 + 687.8577,-4.410039 + 1043.288,-1.19836 + 644.4445,2.357286 + 1002.265,-0.5849216 + 866.3327,-2.573789 + 732.1096,-0.3810852 + 661.4896,-0.2707293 + 600,-0.2227266 + 644.5211,1.784207 + 615.0692,-0.02452826 + 600,-0.1297612 + 644.4445,0.6420181 + 666.7973,4.922177 + 644.4445,8.587686 + 693.5847,6.82707 + 836.9651,12.78135 + 995.8392,12.11045 + 1190.252,24.46093 + 1341.456,7.883049 + 1453.439,21.57428 + 1009.962,38.10797 + 1173.415,42.39235 + 1323.306,42.99743 + 1399.727,9.089857 + 937.9701,32.31821 + 1005.795,44.4572 + 1088.015,53.16226 + 1172.164,54.589 + 1265.583,73.96272 + 1376.655,88.71164 + 1496.45,101.4458 + 1616.172,105.6161 + 1668.748,5.478724 + 1119.606,4.928539 + 1124.671,35.79109 + 1140.175,30.06963 + 1160.328,48.58438 + 1189.106,53.33678 + 1224.844,69.88008 + 1267.755,76.89536 + 1310.533,75.63843 + 1352.249,80.32765 + 1392.649,77.89688 + 1429.045,74.28435 + 1463.412,76.94868 + 1497.873,79.46665 + 1531.421,78.96201 + 1561.273,72.11664 + 1587.056,69.5541 + 1609.479,64.13884 + 1630.585,67.9769 + 1650.429,62.38124 + 1668.137,63.00897 + 1684.42,59.49305 + 1702.746,72.43027 + 1718.317,51.68219 + 1722.2,31.7786 + 1710.807,-2.869109 + 1690.453,-1.062667 + 1673.296,7.073107 + 1662.924,21.68794 + 1658.853,28.46225 + 1655.051,22.32484 + 1643,-0.4019394 + 1623.586,-3.330098 + 1604.414,-0.449111 + 1587.123,1.748246 + 1569.496,-2.081304 + 1552.944,4.46729 + 1542.894,18.06239 + 1538.031,20.74931 + 1530.547,9.303829 + 1514.237,-7.018807 + 1492.526,-7.514885 + 1469.149,-12.08818 + 1442.722,-15.80163 + 1404.525,-18.5696 + 1361.667,-17.84917 + 1327.529,-17.22158 + 1306.449,4.262201 + 1300.712,18.62459 + 1305.858,33.81105 + 1310.184,16.66183 + 1310.09,21.90794 + 1317.331,37.01147 + 1331.747,42.52515 + 1353.015,57.90654 + 1383.016,70.18417 + 1420.392,83.79029 + 1463.21,92.30715 + 1502.401,78.82739 + 1533.557,72.45618 + 1561.099,71.36134 + 1584.785,63.23337 + 1600.343,46.89187 + 1607.934,37.95928 + 1609.116,25.84165 + 1606.496,25.15568 + 1602.882,22.27899 + 1597.401,18.59029 + 1590.777,18.05532 + 1581.158,8.168066 + 1565.438,-2.385445 + 1544.224,-9.294456 + 1521.841,-6.390518 + 1499.485,-9.735824 + 1475.06,-12.31793 + 1438.369,-16.93306 + 1388.027,-15.79407 + 1334.837,-14.71431 + 1282.574,-13.81453 + 1232.73,-12.99281 + 1186.607,-12.35547 + 1153.933,-9.757157 + 1138.281,3.688477 + 1130.166,6.484842 + 1124.469,9.161757 + 1119.579,8.190273 + 1116.717,13.7386 + 1121.178,25.33872 + 1131.012,26.74716 + 1139.974,23.89797 + 1153.758,39.14996 + 1173.145,38.69012 + 1197.14,52.6565 + 1222.573,44.61408 + 1247.831,55.10344 + 1274.231,50.24755 + 1302.956,64.64877 + 1334.958,62.68685 + 1361.681,53.49527 + 1382.828,49.63818 + 1393.616,25.17934 + 1392.595,15.85793 + 1388.47,16.01408 + 1382.331,9.760792 + 1375.264,12.98514 + 1368.573,10.51227 + 1357.852,1.127345 + 1330.887,-15.09141 + 1287.693,-14.09798 + 1235.995,-12.79959 + 1189.24,-12.6493 + 1159.75,-9.993802 + 1143.158,2.208033 + 1140.753,21.87768 + 1152.361,35.92246 + 1169.356,35.89918 + 1193.446,55.35715 + 1227.665,64.36838 + 1263.591,64.05273 + 1304.172,82.13965 + 1350.765,86.74195 + 1399.89,97.1329 + 1448.015,91.67886 + 1490.363,87.14861 + 1527.78,82.59544 + 1565.411,93.79819 + 1601.888,84.35611 + 1629.712,69.70103 + 1643.765,40.32787 + 1644.598,25.34709 + 1642.677,30.8411 + 1647.957,50.22522 + 1657.926,47.7007 + 1664.052,37.76743 + 1668.701,43.12788 + 1677.555,53.11346 + 1688.478,51.41099 + 1698.5,51.11005 + 1706.414,44.9026 + 1708.993,32.6828 + 1711.102,43.46721 + 1718.371,51.58891 + 1728.098,53.19771 + 1735.42,43.84155 + 1735.339,26.82102 + 1726.916,13.36045 + 1716.691,19.60794 + 1707.085,14.90211 + 1695.128,10.50889 + 1682.271,10.91309 + 1663.878,-8.54956 + 1641.629,-3.117419 + 1624.07,5.537962 + 1609.197,4.835527 + 1592.752,-0.4371243 + 1577.893,9.274105 + 1570.101,22.16969 + 1571.847,40.37538 + 1576.751,32.78808 + 1579.035,32.08871 + 1581.749,34.41856 + 1583.133,27.87005 + 1576.012,6.219936 + 1561.421,2.702191 + 1547.059,6.234878 + 1534.363,7.427535 + 1520.672,2.441157 + 1500.385,-12.44278 + 1474.039,-15.19112 + 1448.391,-10.99723 + 1411.539,-16.18276 + 1375.237,-10.13539 + 1357.798,3.94146 + 1352.424,22.40654 + 1358.053,35.1076 + 1371.085,44.18404 + 1390.486,54.94989 + 1412.506,53.94309 + 1436.112,62.30517 + 1459.811,56.89755 + 1483.336,64.70206 + 1510.018,69.77424 + 1535.801,65.16431 + 1559.043,64.80313 + 1580.728,62.89471 + 1598.556,54.45824 + 1613.254,54.38581 + 1626.582,51.40335 + 1634.75,38.01902 + 1625.87,-5.708029 + 1605.435,-1.783062 + 1588.211,3.508634 + 1575.972,13.76913 + 1574.601,38.87314 + 1576.764,25.41134 + 1576.509,31.0111 + 1580.378,39.14088 + 1587.109,40.92192 + 1594.552,42.17134 + 1602.21,42.3647 + 1609.64,42.14173 + 1617.876,45.85305 + 1627.146,46.51075 + 1637.773,51.51218 + 1651.907,59.8804 + 1668.016,60.05737 + 1682.956,57.66072 + 1698.594,64.39252 + 1714.26,59.62116 + 1729.025,63.08392 + 1743.723,61.17331 + 1759.321,68.29936 + 1774.275,60.68742 + 1787.293,62.94482 + 1799.157,57.8984 + 1810.375,61.97612 + 1821.647,59.47066 + 1829.144,48.76117 + 1827.075,23.35892 + 1814.029,6.402053 + 1794.32,-2.592016 + 1771.735,-4.909734 + 1752.711,9.03825 + 1737.462,7.341007 + 1721.273,4.683862 + 1704.694,4.982325 + 1688.128,3.812349 + 1674.545,14.56831 + 1666.793,23.51281 + 1662.064,24.63626 + 1654.984,14.94999 + 1635.731,-15.84564 + 1610.997,-4.315684 + 1594.74,9.832749 + 1588.036,26.32848 + 1590.885,41.41418 + 1599,44.31393 + 1604.347,32.80503 + 1609.748,45.03335 + 1620.321,50.97161 + 1629.86,42.54122 + 1630.612,21.65488 + 1626.286,25.14294 + 1622.995,24.88023 + 1619.287,23.46855 + 1613.268,16.73643 + 1607.706,24.57117 + 1610.003,43.01642 + 1616.519,39.12624 + 1621.208,37.39355 + 1624.634,35.22969 + 1627.952,37.3392 + 1624.594,12.60667 + 1610.554,0.67381 + 1592.725,-0.8326931 + 1573.647,-3.764307 + 1556.383,4.200647 + 1540.61,-0.05308342 + 1524.676,2.95549 + 1506.149,-7.869933 + 1484.451,-6.838203 + 1463.063,-7.529763 + 1441.418,-8.017014 + 1419.842,-7.811407 + 1398.13,-8.783758 + 1377.628,-5.129324 + 1358.174,-6.480177 + 1330.162,-16.99247 + 1294.518,-16.31282 + 1264.088,-13.97139 + 1238.279,-14.27002 + 1205.672,-13.58043 + 1175.577,-8.778869 + 1153.073,-12.24656 + 1128.594,-11.99461 + 1095.57,-10.9451 + 1059.322,-10.66192 + 1040.862,6.466439 + 1046.922,32.05039 + 1070.836,46.81862 + 1105.593,59.44982 + 1144.421,60.56117 + 1185.277,69.68872 + 1225.22,63.52172 + 1258.217,56.72657 + 1292.812,72.29202 + 1331.452,72.35333 + 1366.88,68.45086 + 1393.737,51.85317 + 1417.343,62.23331 + 1449.023,79.29785 + 1486.588,84.81449 + 1520.337,72.50204 + 1545.353,61.22117 + 1565.129,58.47639 + 1583.576,59.16581 + 1597.441,45.13127 + 1602.506,30.88554 + 1600.343,21.15592 + 1593.612,15.33718 + 1586.666,19.96346 + 1587.996,42.56586 + 1600.719,58.4817 + 1618.574,61.39739 + 1637.37,63.87596 + 1655.736,62.19775 + 1672.167,59.32374 + 1687.886,61.68731 + 1702.047,55.59766 + 1710.914,44.22459 + 1715.953,42.70472 + 1719.231,38.34271 + 1721.891,40.7861 + 1725.048,40.4108 + 1728.743,43.06327 + 1735.541,52.16247 + 1744.341,51.14399 + 1753.557,54.70576 + 1763.137,53.5337 + 1773.912,60.3172 + 1790.531,76.9442 + 1814.647,91.22339 + 1844.93,104.5918 + 1876.086,99.57632 + 1900.511,82.78519 + 1919.052,79.66685 + 1921.161,18.51604 + 1896.575,-24.33028 + 1849.753,-24.22952 + 1809.65,-2.914296 + 1783.061,-16.90625 + 1283.055,17.62789 + 1281.148,47.45848 + 1288.122,63.8209 + 1299.731,73.06547 + 1314.197,81.21303 + 1332.148,94.84081 + 1352.77,99.70914 + 1374.041,103.1989 + 1391.799,84.65783 + 1404.758,79.80271 + 1417.834,88.10941 + 1433.956,100.3611 + 1452.571,106.4864 + 1469.02,91.7476 + 1477.869,64.48682 + 1482.045,65.40362 + 1486.32,65.86734 + 1494.467,89.83578 + 1506.898,93.77473 + 1519.525,93.85491 + 1531.702,93.87712 + 1542.725,89.39608 + 1552.242,86.8752 + 1559.959,80.07738 + 1564.449,67.961 + 1567.041,68.89693 + 1570.2,72.11388 + 1572.977,67.08501 + 1574.21,62.75511 + 1574.21,59.41563 + 1573.936,60.99732 + 1572.4,51.27596 + 1568.263,44.06831 + 1559.519,21.27699 + 1545.63,10.24199 + 1530.617,12.39669 + 1515.183,5.857883 + 1498.36,2.09445 + 1486.505,33.94199 + 1482.349,47.08876 + 1480.05,44.51606 + 1479.463,57.02282 + 1482.084,63.77707 + 1487.796,76.23621 + 1495.289,75.71186 + 1501.538,70.15787 + 1507.818,77.17599 + 1514.703,75.15352 + 1520.865,74.11327 + 1527.096,76.84986 + 1532.231,68.53654 + 1536.417,71.96849 + 1540.564,69.12055 + 1543.713,66.52328 + 1546.735,68.94624 + 1547.489,52.78967 + 1545.386,51.08469 + 1542.256,45.96298 + 1539.361,52.00807 + 1537.405,51.35246 + 1535.859,54.2338 + 1536.554,65.10095 + 1540.671,75.84949 + 1547.195,81.08743 + 1550.257,55.29021 + 1545.806,34.30048 + 1535.243,16.24277 + 1523.33,24.33566 + 1512.464,21.15258 + 1502.918,30.91319 + 1494.076,24.17211 + 1485.987,34.19572 + 1480.725,40.09128 + 1478.27,50.29652 + 1478.016,52.946 + 1478.182,52.7861 + 1478.378,53.15138 + 1480.079,61.90357 + 1482.192,55.92644 + 1482.075,48.81292 + 1479.982,43.98728 + 1478.104,49.7599 + 1476.93,47.92091 + 1476.646,54.91663 + 1477.908,57.17506 + 1478.681,52.18999 + 1479.786,59.31868 + 1481.165,54.03209 + 1482.339,58.32693 + 1484.236,58.61423 + 1487.024,64.06499 + 1489.743,58.70241 + 1491.484,58.62561 + 1492.824,56.57703 + 1493.381,54.10405 + 1492.256,46.44337 + 1490.926,52.65959 + 1491.445,57.45026 + 1492.804,57.86545 + 1494.702,60.97232 + 1495.856,53.67446 + 1488.354,8.644087 + 1473.771,9.854107 + 1459.911,11.31598 + 1449.71,29.82105 + 1444.35,38.53183 + 1441.259,42.37823 + 1436.486,28.24177 + 1429.513,28.8433 + 1421.864,23.41715 + 1414.392,28.83934 + 1409.071,34.798 + 1403.584,27.19031 + 1396.982,27.69853 + 1388.531,15.91847 + 1377.224,10.64097 + 1366.25,16.52416 + 1358.612,27.90209 + 1355.629,41.29479 + 1355.726,44.49744 + 1358.876,58.18682 + 1366.27,68.5884 + 1376.618,76.04653 + 1388.952,81.80117 + 1400.522,74.14407 + 1408.504,63.53102 + 1415.252,68.5932 + 1420.651,56.93834 + 1423.263,53.41837 + 1425.219,53.58304 + 1426.207,48.11959 + 1426.852,51.75898 + 1427.38,47.54124 + 1423.742,27.67442 + 1415.125,18.26986 + 1402.381,3.03742 + 1388.482,10.29751 + 1373.977,-1.384802 + 1355.462,-10.03899 + 1330.062,-15.91993 + 1282.331,-13.68837 + 1209.601,-11.78776 + 1130.279,-10.6761 + 1056.59,-9.85384 + 995.0887,-9.493731 + 932.1101,-8.854118 + 860.5636,-8.522646 + 799.4923,-8.632871 + 742.3431,-8.777902 + 916.95,-7.472395 + 784.6405,-6.526037 + 659.1023,-7.239723 + 802.2018,-4.796231 + 600,-4.862612 + 980.1921,3.036931 + 655.1318,-1.243356 + 600,-3.643281 + 600,-2.117112 + 600,-0.4603643 + 600,-2.24E-05 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,-2.38E-07 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,2.38E-07 + 600,0 + 600,2.38E-07 + 600,0 + 600,0 + 600,-2.38E-07 + 600,-2.38E-07 + 644.4445,1.714838 + 644.4445,1.621784 + 644.4445,3.298661 + 755.8596,3.870013 + 644.4445,3.134853 + 644.4445,1.420932 + 644.4445,1.825752 + 644.4445,1.360866 + 991.1098,0.8516321 + 644.4445,2.159252 + 644.4445,1.824742 + 644.4445,1.209069 + 645.8011,2.986922 + 651.5524,2.650311 + 659.7339,0.760689 + 685.8124,4.595871 + 737.2534,3.604281 + 762.7693,2.212489 + 770.3373,1.737349 + 772.536,1.632224 + 772.3826,1.47518 + 768.9055,1.248654 + 770.1327,2.003068 + 775.6552,1.749856 + 776.7802,1.519026 + 774.1212,1.315794 + 769.7236,1.307899 + 770.2861,1.870355 + 770.2861,1.245239 + 768.343,1.646059 + 768.3942,1.467183 + 762.5137,0.9683771 + 717.0042,-2.388535 + 628.3375,-2.716046 + 644.4445,1.232642 + 1006.313,0.3278913 + 950.627,-0.5628872 + 846.9909,-1.407126 + 722.4837,-1.039502 + 621.8163,-0.4376612 + 600,0.0385704 + 644.4445,1.879608 + 602.8344,0.04388237 + 600,-0.00674057 + 644.4445,1.93153 + 794.813,7.284958 + 644.8845,6.377717 + 738.2761,9.556376 + 924.2001,17.0417 + 1082.921,9.743132 + 1157.014,6.99104 + 775.9276,22.85481 + 919.729,33.17456 + 1086.138,42.19983 + 1261.492,50.43425 + 1375.494,19.51903 + 1401.449,6.091826 + 926.2782,23.43933 + 980.7605,39.51251 + 1054.848,47.15857 + 1133.927,51.68547 + 1226.62,71.72372 + 1337.942,86.13082 + 1457.344,97.89137 + 1580.828,109.5713 + 1657.092,36.67658 + 1123.368,1.461304 + 1122.441,25.1924 + 1136.454,37.02988 + 1161.309,52.76898 + 1193.459,57.73195 + 1230.285,68.77976 + 1273.533,79.75322 + 1318.352,79.31004 + 1356.562,67.54053 + 1392.273,77.71348 + 1426.908,69.05838 + 1460.725,80.27706 + 1498.424,86.01363 + 1534.793,81.56979 + 1565.21,71.81206 + 1590.119,67.43898 + 1612.582,66.8174 + 1634.24,67.57295 + 1656.032,70.10327 + 1677.488,69.22984 + 1696.042,62.52128 + 1711.774,61.43768 + 1725.102,55.68619 + 1731.578,37.91976 + 1722.254,-1.090255 + 1702.517,-0.3800182 + 1681.747,-5.168064 + 1664.59,11.20999 + 1654.514,18.04026 + 1645.996,15.99401 + 1635.436,10.42183 + 1621.665,4.338938 + 1605.22,0.5969486 + 1587.795,0.2512197 + 1570.517,0.3162355 + 1554.072,2.230137 + 1541.806,13.14601 + 1533.597,14.75539 + 1525.832,14.09572 + 1514.506,2.944591 + 1496.1,-7.84253 + 1471.352,-15.42717 + 1440.169,-20.01007 + 1400.468,-18.50732 + 1353.19,-17.0692 + 1315.531,-12.80798 + 1294.491,-3.285613 + 1284.173,13.58008 + 1289.225,37.47305 + 1302.015,35.04106 + 1311.339,28.96468 + 1316.942,25.44615 + 1328.926,47.30635 + 1352.921,60.59223 + 1385.233,74.25334 + 1422.945,80.9559 + 1461.329,81.75445 + 1495.643,73.77378 + 1525.133,71.24657 + 1553.333,73.6284 + 1578.726,65.64669 + 1596.568,51.4837 + 1607.732,45.11185 + 1612.851,32.04094 + 1610.876,21.44158 + 1605.126,19.07754 + 1598.368,17.63783 + 1591.677,18.84343 + 1582.676,9.494823 + 1569.455,4.294639 + 1552.541,-2.913902 + 1532.455,-5.940009 + 1507.855,-16.18926 + 1475.826,-18.23104 + 1433.29,-16.7917 + 1382.384,-15.64154 + 1326.494,-14.32655 + 1274.366,-13.89831 + 1227.275,-12.87859 + 1182.348,-12.34522 + 1151.286,-9.173134 + 1131.402,-6.310503 + 1119.781,8.727276 + 1118.289,16.43811 + 1118.921,13.66425 + 1120.828,19.48628 + 1124.819,18.68554 + 1130.757,24.36229 + 1141.048,29.49514 + 1158.46,42.48001 + 1180.763,43.03611 + 1203.146,44.87235 + 1225.918,46.25666 + 1248.597,46.92699 + 1272.592,52.15644 + 1299.516,57.51007 + 1329.074,62.6179 + 1359.343,63.1154 + 1380.947,40.95043 + 1388.403,23.98634 + 1388.417,19.74684 + 1385.165,14.44612 + 1379.603,12.82719 + 1372.187,8.792199 + 1363.065,7.554926 + 1349.723,-3.177336 + 1329.396,-11.0907 + 1300.833,-14.74182 + 1261.575,-13.61232 + 1217.468,-12.85518 + 1175.268,-12.22688 + 1141.546,-12.1833 + 1126.955,11.26167 + 1134.532,35.89684 + 1157.695,49.54621 + 1189.052,58.5972 + 1222.466,58.37698 + 1257.343,66.71474 + 1300.538,85.77503 + 1352.393,97.63816 + 1402.304,88.47597 + 1444.938,84.01994 + 1484.008,84.11902 + 1521.116,83.72038 + 1557.216,86.50259 + 1591.624,83.49979 + 1623.855,84.3294 + 1647.595,58.56056 + 1655.346,31.51854 + 1647.595,5.291959 + 1637.236,21.8509 + 1638.069,43.26761 + 1647.353,51.25405 + 1657.993,48.95843 + 1668.862,53.2352 + 1680.014,51.13348 + 1689.217,47.52374 + 1696.109,43.85042 + 1700.18,38.1036 + 1701.886,35.75303 + 1704.895,42.96144 + 1713.521,56.36014 + 1723.759,49.71629 + 1725.169,25.28842 + 1717.766,17.81898 + 1708.886,19.36817 + 1699.602,15.74377 + 1685.428,1.331335 + 1668.258,4.265698 + 1651.088,0.4824829 + 1632.682,-0.7735591 + 1616.546,7.333869 + 1601.297,1.405253 + 1587.109,10.06296 + 1578.108,17.9458 + 1571.148,16.3085 + 1567.669,28.97894 + 1571.471,40.18153 + 1577.49,36.66446 + 1581.507,34.05357 + 1584.664,34.14597 + 1581.897,14.52561 + 1573.567,15.4157 + 1560.951,-0.06234074 + 1539.428,-12.5987 + 1514.842,-9.453217 + 1487.81,-18.44072 + 1460.886,-9.728415 + 1437.804,-9.730576 + 1416.16,-6.372715 + 1395.067,-8.671995 + 1373.544,-7.898953 + 1360.901,15.09554 + 1358.859,20.97911 + 1363.857,35.19839 + 1379.617,52.60059 + 1405.99,68.11739 + 1434.069,60.73365 + 1456.748,55.0891 + 1477.304,56.83291 + 1499.552,62.82561 + 1522.835,62.77331 + 1543.606,57.48309 + 1563.611,62.81192 + 1585.403,65.84775 + 1604.911,57.73931 + 1619.407,51.10355 + 1625.279,29.70323 + 1619.824,12.86922 + 1606.134,1.337738 + 1587.701,-3.369208 + 1572.465,11.06384 + 1564.538,19.60567 + 1563.638,33.72519 + 1569.052,40.41961 + 1578.041,46.10619 + 1586.653,40.0111 + 1594.445,44.22099 + 1602.896,42.9819 + 1610.231,41.26826 + 1616.559,40.2604 + 1624.123,46.1275 + 1634.065,49.20351 + 1644.907,50.29093 + 1656.059,51.45343 + 1668.943,57.63499 + 1688.625,77.20282 + 1711.116,70.17025 + 1728.34,61.05583 + 1744.61,68.95058 + 1762.868,70.50829 + 1779.366,64.74032 + 1794.387,67.11285 + 1807.486,59.31385 + 1818.275,59.92589 + 1828.835,59.76006 + 1834.155,40.87052 + 1824.254,1.570856 + 1803.939,0.1671991 + 1785.896,8.91948 + 1769.089,3.76696 + 1750.548,1.465682 + 1734.198,10.69146 + 1720.507,10.2054 + 1707.327,11.65767 + 1695.45,14.03399 + 1684.931,15.71651 + 1675.325,16.56543 + 1665.933,15.82545 + 1654.339,8.25458 + 1639.587,4.160066 + 1622.202,-1.38369 + 1608.431,15.49589 + 1602.748,25.05814 + 1601.189,29.03644 + 1603.151,36.84112 + 1608.673,41.2834 + 1614.087,36.97735 + 1619.031,40.19678 + 1622.941,33.88109 + 1623.505,29.08438 + 1621.114,23.80924 + 1615.149,16.70804 + 1607.464,17.53648 + 1602.546,25.54437 + 1600.706,27.58181 + 1600.195,29.89292 + 1602.318,36.44426 + 1608.995,45.53632 + 1616.116,38.564 + 1619.327,32.86123 + 1617.164,20.48985 + 1607.571,7.451408 + 1591.973,-0.2941513 + 1573.177,-3.498985 + 1552.541,-6.302647 + 1531.81,-4.429373 + 1511.698,-5.13943 + 1493.265,-0.3575616 + 1477.143,0.7890692 + 1461.141,-0.5568328 + 1445.449,1.121991 + 1430.375,0.6806421 + 1410.706,-11.54041 + 1385.824,-13.42626 + 1360.619,-12.66673 + 1335.24,-14.07331 + 1309.62,-13.46232 + 1274.366,-13.88826 + 1237.862,-13.81937 + 1212.241,-11.44095 + 1184.081,-12.65552 + 1148.102,-11.87495 + 1115.508,-11.77358 + 1087.442,-11.19799 + 1054.593,-10.48865 + 1033.607,5.6588 + 1040.043,33.29015 + 1064.535,46.21249 + 1097.908,56.06443 + 1138.16,66.53667 + 1181.515,68.95843 + 1223.258,68.46669 + 1261.723,66.08852 + 1300.779,75.51466 + 1341.756,76.87059 + 1377.36,65.75189 + 1406.339,62.23019 + 1433.908,65.22336 + 1459.475,59.45428 + 1483.82,64.64926 + 1510.354,69.41556 + 1536.862,67.94376 + 1560.467,63.31855 + 1581.225,61.46338 + 1596.42,47.04777 + 1600.343,25.01183 + 1593.115,9.831497 + 1584.181,18.76838 + 1581.493,30.10958 + 1586.962,45.85008 + 1600.37,57.38508 + 1617.769,60.89524 + 1636.443,63.86408 + 1655.078,63.03837 + 1671.496,58.34701 + 1686.221,59.03419 + 1700.287,57.73484 + 1710.955,48.39701 + 1717.229,43.00974 + 1721.3,41.04623 + 1725.115,42.49238 + 1729.374,43.04696 + 1732.33,38.14999 + 1734.453,40.29311 + 1737.193,40.62325 + 1742.259,49.12432 + 1749.527,49.27705 + 1758.905,57.77568 + 1780.186,95.1664 + 1817.066,120.4318 + 1863.283,138.34 + 1894.667,69.34295 + 1907.269,68.27747 + 1919.079,67.84028 + 1917.762,16.49406 + 1889.951,-25.8662 + 1839.596,-23.89131 + 1797.746,-6.402427 + 1288.914,-15.27851 + 1277.128,32.77653 + 1281.275,63.12198 + 1290.283,58.78977 + 1302.49,81.71949 + 1320.926,94.45592 + 1342.199,101.122 + 1364.574,105.4511 + 1384.497,92.51437 + 1399.036,79.38459 + 1412.044,86.92896 + 1425.375,83.94568 + 1438.726,89.94231 + 1452.996,92.26556 + 1465.477,82.38766 + 1473.311,67.06986 + 1478.475,67.91246 + 1485.547,79.625 + 1497.763,100.7359 + 1512.278,96.41169 + 1525.707,97.44376 + 1538.334,94.52263 + 1549.249,89.58551 + 1557.71,81.4274 + 1564.057,77.99872 + 1569.036,74.02861 + 1572.312,68.13066 + 1575.041,71.18874 + 1576.86,62.82628 + 1576.352,56.58434 + 1574.357,53.18288 + 1571.52,50.82687 + 1567.755,46.73517 + 1562.385,39.9514 + 1553.406,22.98973 + 1541.513,20.22375 + 1527.653,9.152882 + 1512.63,11.24 + 1497.871,9.012047 + 1484.578,18.34523 + 1477.82,46.65918 + 1476.558,50.44249 + 1476.832,55.68708 + 1479.131,62.68777 + 1483.698,69.81506 + 1490.535,77.33602 + 1498.018,75.10793 + 1505.011,75.88093 + 1512.151,77.44696 + 1520.327,83.79372 + 1527.986,75.92196 + 1532.671,66.83388 + 1536.348,70.5734 + 1539.762,65.89542 + 1543.273,71.87601 + 1547.303,69.85374 + 1549.034,58.16096 + 1547.87,51.91158 + 1546.364,55.78762 + 1544.672,50.47578 + 1541.356,45.2815 + 1538.324,51.6749 + 1537.356,57.68959 + 1538.872,67.07841 + 1544.251,82.28827 + 1545.288,40.75605 + 1538.011,30.25864 + 1530.314,36.96606 + 1522.196,26.52944 + 1511.906,22.36277 + 1500.12,15.97792 + 1489.616,28.55366 + 1482.329,34.04303 + 1478.945,50.99249 + 1479.502,57.25879 + 1480.607,54.3908 + 1481.048,53.44007 + 1481.713,55.82595 + 1482.329,53.25982 + 1482.818,55.16615 + 1481.811,44.30854 + 1479.307,45.96726 + 1476.646,42.96669 + 1473.575,43.07121 + 1471.717,49.74657 + 1470.788,48.34003 + 1472.177,63.49163 + 1475.942,62.85665 + 1479.972,65.78904 + 1484.334,65.62042 + 1488.217,63.7094 + 1490.124,54.34649 + 1490.183,52.82955 + 1489.342,48.89529 + 1488.755,54.22676 + 1487.777,46.42638 + 1486.192,50.38337 + 1485.576,52.02367 + 1487.601,66.28146 + 1491.67,64.79538 + 1494.985,62.46672 + 1496.091,51.93176 + 1492.462,33.85468 + 1486.104,34.78819 + 1476.089,10.9714 + 1464.117,21.67854 + 1454.757,25.02648 + 1445.866,23.2522 + 1436.829,23.01534 + 1428.603,26.81799 + 1421.473,28.30663 + 1413.345,20.16391 + 1404.963,25.78935 + 1396.278,17.4505 + 1387.201,22.49283 + 1379.914,26.44587 + 1372.432,20.53219 + 1364.392,22.42527 + 1357.027,23.32439 + 1350.679,27.14028 + 1350.269,55.12245 + 1357.262,67.91344 + 1367.101,72.15673 + 1377.987,75.64056 + 1389.636,78.59641 + 1399.104,65.48586 + 1405.217,61.24613 + 1409.795,57.77759 + 1413.922,59.46923 + 1417.404,54.76487 + 1420.857,59.91445 + 1423.595,51.20931 + 1424.886,51.9877 + 1425.776,49.09315 + 1423.556,34.09339 + 1418.059,29.80763 + 1405.119,-7.826694 + 1385.391,-8.599997 + 1365.175,-11.35708 + 1344.4,-11.20156 + 1318.843,-15.60458 + 1278.125,-14.10385 + 1212.223,-11.80592 + 1143.825,-11.62002 + 1080.622,-10.19347 + 1005.036,-8.704713 + 942.2039,-9.229837 + 877.6898,-7.629379 + 796.7341,-8.281475 + 1005.85,-9.090136 + 922.6464,-8.02299 + 814.1037,-6.777267 + 680.4239,-6.171268 + 600,-6.54746 + 881.2298,-1.826855 + 625.3334,-5.014571 + 600,-5.152775 + 600,-4.932726 + 600,-1.280655 + 600,-0.4310925 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 + 600,0 \ No newline at end of file diff --git a/VectoCoreTest/TestData/Cycles/Cycle time field missing.vdri b/VectoCoreTest/TestData/Cycles/Cycle time field missing.vdri index 83052339fe6c96e1210a22b1d0bb0b5dc797dbec..dd935c134113ebdd25d45bc956ecd29be3ca98f9 100644 --- a/VectoCoreTest/TestData/Cycles/Cycle time field missing.vdri +++ b/VectoCoreTest/TestData/Cycles/Cycle time field missing.vdri @@ -1,14 +1,24 @@ -<v>,<grad>,<Padd>,<Aux_ALT1>,<Aux_ALT2>,<Aux_ALT3> -0,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 -64,-0.020237973,6.1,0.25,0.25,0.25 \ No newline at end of file +<v> + , + <grad> + , + <Padd> + , + <Aux_ALT1> + , + <Aux_ALT2> + , + <Aux_ALT3> + 0,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 + 64,-0.020237973,6.1,0.25,0.25,0.25 \ No newline at end of file diff --git a/VectoCoreTest/TestData/Cycles/EngineOnly_FullLoad.vdri b/VectoCoreTest/TestData/Cycles/EngineOnly_FullLoad.vdri index 574eead06b48d123c9d9a417ba0e00582d5d4b54..afc1a15cfd46a69ffbd09b616b474e13ceb0cddf 100644 --- a/VectoCoreTest/TestData/Cycles/EngineOnly_FullLoad.vdri +++ b/VectoCoreTest/TestData/Cycles/EngineOnly_FullLoad.vdri @@ -1,18 +1,20 @@ -<n>,<Pe> -# [rpm],[kW] -600,0 -600,0 -600,0 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 -1600,999 \ No newline at end of file +<n> + , + <Pe> + # [rpm],[kW] + 600,0 + 600,0 + 600,0 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 + 1600,999 \ No newline at end of file diff --git a/VectoCoreTest/Utils/DelauneyMapTest.cs b/VectoCoreTest/Utils/DelauneyMapTest.cs index 98f85ec71eacf7eacea1b0a994f83ae65d24e60a..61d68a9c6a30abd3a10a32903dbfb02c7ceae4eb 100644 --- a/VectoCoreTest/Utils/DelauneyMapTest.cs +++ b/VectoCoreTest/Utils/DelauneyMapTest.cs @@ -5,159 +5,145 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Utils { - [TestClass] - public class DelauneyMapTest - { - private const double tolerance = 0.00001; - - public static void AssertException<T>(Action func, string message) where T : Exception - { - try - { - func(); - Assert.Fail(); - } - catch (T ex) - { - Assert.AreEqual(message, ex.Message); - } - } - - [TestMethod] - public void Test_Simple_DelauneyMap() - { - var map = new DelauneyMap(); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 0); - map.AddPoint(0, 1, 0); - - map.Triangulate(); - - var result = map.Interpolate(0.25, 0.25); - - Assert.AreEqual(0, result, tolerance); - } - - [TestMethod] - public void Test_DelauneyMapTriangle() - { - var map = new DelauneyMap(); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 1); - map.AddPoint(0, 1, 2); - - map.Triangulate(); - - // fixed points - Assert.AreEqual(0, map.Interpolate(0, 0), tolerance); - Assert.AreEqual(1, map.Interpolate(1, 0), tolerance); - Assert.AreEqual(2, map.Interpolate(0, 1), tolerance); - - // interpolations - Assert.AreEqual(0.5, map.Interpolate(0.5, 0), tolerance); - Assert.AreEqual(1, map.Interpolate(0, 0.5), tolerance); - Assert.AreEqual(1.5, map.Interpolate(0.5, 0.5), tolerance); - - Assert.AreEqual(0.25, map.Interpolate(0.25, 0), tolerance); - Assert.AreEqual(0.5, map.Interpolate(0, 0.25), tolerance); - Assert.AreEqual(0.75, map.Interpolate(0.25, 0.25), tolerance); - - Assert.AreEqual(0.75, map.Interpolate(0.75, 0), tolerance); - Assert.AreEqual(1.5, map.Interpolate(0, 0.75), tolerance); - - // extrapolation (should fail) - AssertException<VectoException>(() => map.Interpolate(1, 1), "Interpolation failed. x: 1, y: 1"); - AssertException<VectoException>(() => map.Interpolate(-1, -1), "Interpolation failed. x: -1, y: -1"); - AssertException<VectoException>(() => map.Interpolate(1, -1), "Interpolation failed. x: 1, y: -1"); - AssertException<VectoException>(() => map.Interpolate(-1, 1), "Interpolation failed. x: -1, y: 1"); - } - - - - public void Test_DelauneyMapPlane() - { - var map = new DelauneyMap(); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 1); - map.AddPoint(0, 1, 2); - map.AddPoint(1, 1, 3); - - map.Triangulate(); - - // fixed points - Assert.AreEqual(0, map.Interpolate(0, 0), tolerance); - Assert.AreEqual(1, map.Interpolate(1, 0), tolerance); - Assert.AreEqual(2, map.Interpolate(0, 1), tolerance); - Assert.AreEqual(3, map.Interpolate(1, 1), tolerance); - - // interpolations - Assert.AreEqual(0.5, map.Interpolate(0.5, 0), tolerance); - Assert.AreEqual(1, map.Interpolate(0, 0.5), tolerance); - Assert.AreEqual(2, map.Interpolate(1, 0.5), tolerance); - Assert.AreEqual(2.5, map.Interpolate(0.5, 1), tolerance); - - Assert.AreEqual(1.5, map.Interpolate(0.5, 0.5), tolerance); - - Assert.AreEqual(0.75, map.Interpolate(0.25, 0.25), tolerance); - Assert.AreEqual(2.25, map.Interpolate(0.75, 0.75), tolerance); - - Assert.AreEqual(1.75, map.Interpolate(0.25, 0.75), tolerance); - Assert.AreEqual(1.25, map.Interpolate(0.75, 0.25), tolerance); - - // extrapolation (should fail) - AssertException<VectoException>(() => map.Interpolate(1.5, 0.5), "Interpolation failed."); - AssertException<VectoException>(() => map.Interpolate(1.5, 1.5), "Interpolation failed."); - AssertException<VectoException>(() => map.Interpolate(0.5, 1.5), "Interpolation failed."); - AssertException<VectoException>(() => map.Interpolate(-0.5, 1.5), "Interpolation failed."); - AssertException<VectoException>(() => map.Interpolate(-0.5, 0.5), "Interpolation failed."); - AssertException<VectoException>(() => map.Interpolate(-1.5, -1.5), "Interpolation failed."); - AssertException<VectoException>(() => map.Interpolate(0.5, -0.5), "Interpolation failed."); - AssertException<VectoException>(() => map.Interpolate(-1.5, -0.5), "Interpolation failed."); - } - - [TestMethod] - public void Test_Delauney_LessThan3Points() - { - DelauneyMap map; - try - { - map = new DelauneyMap(); - map.Triangulate(); - Assert.Fail(); - } - catch (ArgumentException ex) - { - Assert.AreEqual("Triangulations needs at least 3 Points. Got 0 Points.", ex.Message); - } - try - { - map = new DelauneyMap(); - map.AddPoint(0, 0, 0); - map.Triangulate(); - Assert.Fail(); - } - catch (ArgumentException ex) - { - Assert.AreEqual("Triangulations needs at least 3 Points. Got 1 Points.", ex.Message); - } - try - { - map = new DelauneyMap(); - map.AddPoint(0, 0, 0); - map.AddPoint(0, 0, 0); - map.Triangulate(); - Assert.Fail(); - } - catch (ArgumentException ex) - { - Assert.AreEqual("Triangulations needs at least 3 Points. Got 2 Points.", ex.Message); - } - - map = new DelauneyMap(); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 0); - map.AddPoint(0, 1, 0); - map.Triangulate(); - } - } -} + [TestClass] + public class DelauneyMapTest + { + private const double tolerance = 0.00001; + + public static void AssertException<T>(Action func, string message) where T : Exception + { + try { + func(); + Assert.Fail(); + } catch (T ex) { + Assert.AreEqual(message, ex.Message); + } + } + + [TestMethod] + public void Test_Simple_DelauneyMap() + { + var map = new DelauneyMap(); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 0); + map.AddPoint(0, 1, 0); + + map.Triangulate(); + + var result = map.Interpolate(0.25, 0.25); + + Assert.AreEqual(0, result, tolerance); + } + + [TestMethod] + public void Test_DelauneyMapTriangle() + { + var map = new DelauneyMap(); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 1); + map.AddPoint(0, 1, 2); + + map.Triangulate(); + + // fixed points + Assert.AreEqual(0, map.Interpolate(0, 0), tolerance); + Assert.AreEqual(1, map.Interpolate(1, 0), tolerance); + Assert.AreEqual(2, map.Interpolate(0, 1), tolerance); + + // interpolations + Assert.AreEqual(0.5, map.Interpolate(0.5, 0), tolerance); + Assert.AreEqual(1, map.Interpolate(0, 0.5), tolerance); + Assert.AreEqual(1.5, map.Interpolate(0.5, 0.5), tolerance); + + Assert.AreEqual(0.25, map.Interpolate(0.25, 0), tolerance); + Assert.AreEqual(0.5, map.Interpolate(0, 0.25), tolerance); + Assert.AreEqual(0.75, map.Interpolate(0.25, 0.25), tolerance); + + Assert.AreEqual(0.75, map.Interpolate(0.75, 0), tolerance); + Assert.AreEqual(1.5, map.Interpolate(0, 0.75), tolerance); + + // extrapolation (should fail) + AssertException<VectoException>(() => map.Interpolate(1, 1), "Interpolation failed. x: 1, y: 1"); + AssertException<VectoException>(() => map.Interpolate(-1, -1), "Interpolation failed. x: -1, y: -1"); + AssertException<VectoException>(() => map.Interpolate(1, -1), "Interpolation failed. x: 1, y: -1"); + AssertException<VectoException>(() => map.Interpolate(-1, 1), "Interpolation failed. x: -1, y: 1"); + } + + public void Test_DelauneyMapPlane() + { + var map = new DelauneyMap(); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 1); + map.AddPoint(0, 1, 2); + map.AddPoint(1, 1, 3); + + map.Triangulate(); + + // fixed points + Assert.AreEqual(0, map.Interpolate(0, 0), tolerance); + Assert.AreEqual(1, map.Interpolate(1, 0), tolerance); + Assert.AreEqual(2, map.Interpolate(0, 1), tolerance); + Assert.AreEqual(3, map.Interpolate(1, 1), tolerance); + + // interpolations + Assert.AreEqual(0.5, map.Interpolate(0.5, 0), tolerance); + Assert.AreEqual(1, map.Interpolate(0, 0.5), tolerance); + Assert.AreEqual(2, map.Interpolate(1, 0.5), tolerance); + Assert.AreEqual(2.5, map.Interpolate(0.5, 1), tolerance); + + Assert.AreEqual(1.5, map.Interpolate(0.5, 0.5), tolerance); + + Assert.AreEqual(0.75, map.Interpolate(0.25, 0.25), tolerance); + Assert.AreEqual(2.25, map.Interpolate(0.75, 0.75), tolerance); + + Assert.AreEqual(1.75, map.Interpolate(0.25, 0.75), tolerance); + Assert.AreEqual(1.25, map.Interpolate(0.75, 0.25), tolerance); + + // extrapolation (should fail) + AssertException<VectoException>(() => map.Interpolate(1.5, 0.5), "Interpolation failed."); + AssertException<VectoException>(() => map.Interpolate(1.5, 1.5), "Interpolation failed."); + AssertException<VectoException>(() => map.Interpolate(0.5, 1.5), "Interpolation failed."); + AssertException<VectoException>(() => map.Interpolate(-0.5, 1.5), "Interpolation failed."); + AssertException<VectoException>(() => map.Interpolate(-0.5, 0.5), "Interpolation failed."); + AssertException<VectoException>(() => map.Interpolate(-1.5, -1.5), "Interpolation failed."); + AssertException<VectoException>(() => map.Interpolate(0.5, -0.5), "Interpolation failed."); + AssertException<VectoException>(() => map.Interpolate(-1.5, -0.5), "Interpolation failed."); + } + + [TestMethod] + public void Test_Delauney_LessThan3Points() + { + DelauneyMap map; + try { + map = new DelauneyMap(); + map.Triangulate(); + Assert.Fail(); + } catch (ArgumentException ex) { + Assert.AreEqual("Triangulations needs at least 3 Points. Got 0 Points.", ex.Message); + } + try { + map = new DelauneyMap(); + map.AddPoint(0, 0, 0); + map.Triangulate(); + Assert.Fail(); + } catch (ArgumentException ex) { + Assert.AreEqual("Triangulations needs at least 3 Points. Got 1 Points.", ex.Message); + } + try { + map = new DelauneyMap(); + map.AddPoint(0, 0, 0); + map.AddPoint(0, 0, 0); + map.Triangulate(); + Assert.Fail(); + } catch (ArgumentException ex) { + Assert.AreEqual("Triangulations needs at least 3 Points. Got 2 Points.", ex.Message); + } + + map = new DelauneyMap(); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 0); + map.AddPoint(0, 1, 0); + map.Triangulate(); + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Utils/SITest.cs b/VectoCoreTest/Utils/SITest.cs index 683269b4e1260c20acc3d6921c213586fd0973ae..05e6394e4fb702ef27e9da163f3c07853c9f9a45 100644 --- a/VectoCoreTest/Utils/SITest.cs +++ b/VectoCoreTest/Utils/SITest.cs @@ -4,68 +4,65 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Utils { - [TestClass] - public class SITest - { - public static void AssertException<T>(Action func, string message) where T : Exception - { - try - { - func(); - Assert.Fail(); - } - catch (T ex) - { - Assert.AreEqual(message, ex.Message); - } - } + [TestClass] + public class SITest + { + public static void AssertException<T>(Action func, string message) where T : Exception + { + try { + func(); + Assert.Fail(); + } catch (T ex) { + Assert.AreEqual(message, ex.Message); + } + } - [TestMethod] - public void TestSI() - { - var si = new SI(); - Assert.AreEqual(0.0, (double)si); - Assert.AreEqual("0 [-]", si.ToString()); - Assert.IsTrue(si.HasEqualUnit(new SI())); + [TestMethod] + public void TestSI() + { + var si = new SI(); + Assert.AreEqual(0.0, (double) si); + Assert.AreEqual("0 [-]", si.ToString()); + Assert.IsTrue(si.HasEqualUnit(new SI())); - var si2 = 5.0.SI().Watt; - Assert.AreEqual("5 [W]", si2.ToString()); + var si2 = 5.0.SI().Watt; + Assert.AreEqual("5 [W]", si2.ToString()); - var si3 = 2.SI().Radian.Per.Second; - Assert.AreEqual("2 [rad/s]", si3.ToString()); + var si3 = 2.SI().Radian.Per.Second; + Assert.AreEqual("2 [rad/s]", si3.ToString()); - var si4 = si2 * si3; - Assert.AreEqual("10 [W/s]", si4.ToString()); - Assert.IsTrue(si4.HasEqualUnit(new SI().Watt.Per.Second)); - Assert.AreEqual("10 [kgmm/ssss]", si4.ToBasicUnits().ToString()); + var si4 = si2 * si3; + Assert.AreEqual("10 [W/s]", si4.ToString()); + Assert.IsTrue(si4.HasEqualUnit(new SI().Watt.Per.Second)); + Assert.AreEqual("10 [kgmm/ssss]", si4.ToBasicUnits().ToString()); - var kg = 5.0.SI().Kilo.Gramm; - Assert.AreEqual(5.0, (double)kg); - Assert.AreEqual("5 [kg]", kg.ToString()); + var kg = 5.0.SI().Kilo.Gramm; + Assert.AreEqual(5.0, (double) kg); + Assert.AreEqual("5 [kg]", kg.ToString()); - kg = kg.To().Kilo.Gramm.Value(); - Assert.AreEqual(5.0, (double)kg); - Assert.AreEqual("5 [kg]", kg.ToString()); + kg = kg.To().Kilo.Gramm.Value(); + Assert.AreEqual(5.0, (double) kg); + Assert.AreEqual("5 [kg]", kg.ToString()); - kg = kg.To().Gramm.Value(); - Assert.AreEqual(5000, (double)kg); - Assert.AreEqual("5000 [g]", kg.ToString()); + kg = kg.To().Gramm.Value(); + Assert.AreEqual(5000, (double) kg); + Assert.AreEqual("5000 [g]", kg.ToString()); - var x = 5.SI(); - Assert.AreEqual((2.0 / 5.0).SI(), 2 / x); - Assert.AreEqual((5.0 / 2.0).SI(), x / 2); - Assert.AreEqual((2.0 * 5.0).SI(), 2 * x); - Assert.AreEqual((5.0 * 2.0).SI(), x * 2); + var x = 5.SI(); + Assert.AreEqual((2.0 / 5.0).SI(), 2 / x); + Assert.AreEqual((5.0 / 2.0).SI(), x / 2); + Assert.AreEqual((2.0 * 5.0).SI(), 2 * x); + Assert.AreEqual((5.0 * 2.0).SI(), x * 2); - Assert.AreEqual((2.0 / 5.0).SI(), 2.0 / x); - Assert.AreEqual((5.0 / 2.0).SI(), x / 2.0); - Assert.AreEqual((2 * 5).SI(), 2.0 * x); - Assert.AreEqual((5 * 2).SI(), x * 2.0); + Assert.AreEqual((2.0 / 5.0).SI(), 2.0 / x); + Assert.AreEqual((5.0 / 2.0).SI(), x / 2.0); + Assert.AreEqual((2 * 5).SI(), 2.0 * x); + Assert.AreEqual((5 * 2).SI(), x * 2.0); - var y = 2.SI(); - Assert.AreEqual((2 * 5).SI(), y * x); - } - } -} + var y = 2.SI(); + Assert.AreEqual((2 * 5).SI(), y * x); + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/Utils/TestModalDataWriter.cs b/VectoCoreTest/Utils/TestModalDataWriter.cs index 4c88770ec8a85c842e6293c3c4a0236ba4ad221b..542895a19113536aafaffb0eb440064b30fde38f 100644 --- a/VectoCoreTest/Utils/TestModalDataWriter.cs +++ b/VectoCoreTest/Utils/TestModalDataWriter.cs @@ -1,52 +1,48 @@ using System; using System.Data; using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Utils { - /// <summary> - /// Fake Data Writer Class for Tests. - /// </summary> - class TestModalDataWriter : IModalDataWriter - { - public ModalResults Data { get; set; } - public DataRow CurrentRow { get; set; } + /// <summary> + /// Fake Data Writer Class for Tests. + /// </summary> + internal class TestModalDataWriter : IModalDataWriter + { + public TestModalDataWriter() + { + Data = new ModalResults(); + CurrentRow = Data.NewRow(); + } - public TestModalDataWriter() - { - Data = new ModalResults(); - CurrentRow = Data.NewRow(); - } + public ModalResults Data { get; set; } + public DataRow CurrentRow { get; set; } - public void CommitSimulationStep() - { + public void CommitSimulationStep() + { Data.Rows.Add(CurrentRow); - CurrentRow = Data.NewRow(); - } + CurrentRow = Data.NewRow(); + } + + public void Finish() {} + + public object this[ModalResultField key] + { + get { return CurrentRow[key.GetName()]; } + set { CurrentRow[key.GetName()] = value; } + } public void CommitSimulationStep(TimeSpan absTime, TimeSpan simulationInterval) { - CurrentRow[ModalResultField.time.GetName()] = (absTime + TimeSpan.FromTicks(simulationInterval.Ticks / 2)).TotalSeconds; + CurrentRow[ModalResultField.time.GetName()] = + (absTime + TimeSpan.FromTicks(simulationInterval.Ticks / 2)).TotalSeconds; CurrentRow[ModalResultField.simulationInterval.GetName()] = simulationInterval.TotalSeconds; CommitSimulationStep(); - } + } - public void Finish() - { - - } - - public object this[ModalResultField key] - { - get { return CurrentRow[key.GetName()]; } - set { CurrentRow[key.GetName()] = value; } - } - - public double GetDouble(ModalResultField key) - { + public double GetDouble(ModalResultField key) + { return CurrentRow.Field<double>(key.GetName()); - } - - } -} + } + } +} \ No newline at end of file diff --git a/VectoCoreTest/app.config b/VectoCoreTest/app.config index d91dcf3c83cfadd501d684a13f218d337e1e6527..275e46a27e77b434708c616ce57bc44e44093d6f 100644 --- a/VectoCoreTest/app.config +++ b/VectoCoreTest/app.config @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> + <configuration> <configSections> <sectionGroup name="common"> @@ -6,14 +7,14 @@ </sectionGroup> <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" /> </configSections> - <runtime> - <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> - <dependentAssembly> - <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" /> - </dependentAssembly> - </assemblyBinding> - </runtime> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> <common> <logging> <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog31"> @@ -24,7 +25,8 @@ <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target xsi:type="Console" name="ConsoleLogger" error="true" /> - <target xsi:type="File" name="LogFile" filename="${basedir}/logs/log.txt" layout="${longdate} [${processid}@${machinename}] ${callsite} ${level:uppercase=true}: ${message}" /> + <target xsi:type="File" name="LogFile" filename="${basedir}/logs/log.txt" + layout="${longdate} [${processid}@${machinename}] ${callsite} ${level:uppercase=true}: ${message}" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="LogFile" /> diff --git a/VectoCoreTest/packages.config b/VectoCoreTest/packages.config index 13ccd21a7c065d08605db8562feb621b77d2ba85..98ab3a90aabf4fa10c001d853b73ce05fc7e81f3 100644 --- a/VectoCoreTest/packages.config +++ b/VectoCoreTest/packages.config @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> + <packages> - <package id="Common.Logging" version="3.0.0" targetFramework="net45" /> - <package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" /> - <package id="Common.Logging.NLog31" version="3.0.0" targetFramework="net45" /> - <package id="NLog" version="3.2.0.0" targetFramework="net45" /> + <package id="Common.Logging" version="3.0.0" targetFramework="net45" /> + <package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" /> + <package id="Common.Logging.NLog31" version="3.0.0" targetFramework="net45" /> + <package id="NLog" version="3.2.0.0" targetFramework="net45" /> </packages> \ No newline at end of file