public async Task TimeSeriesInsightsTypeWithNumericVariable_ExpectsError() { // Arrange TimeSeriesInsightsClient client = GetClient(); var timeSeriesTypes = new List <TimeSeriesType>(); var tsiTypeNamePrefix = "type"; var timeSeriesTypesName = Recording.GenerateAlphaNumericId(tsiTypeNamePrefix); string timeSeriesTypeId = Recording.GenerateId(); // Build Numeric variable // Below is an invalid expression var numExpression = new TimeSeriesExpression("$event"); var aggregation = new TimeSeriesExpression("avg($value)"); var numericVariable = new NumericVariable(numExpression, aggregation); var variables = new Dictionary <string, TimeSeriesVariable>(); var variableNamePrefix = "numericVariableName"; variables.Add(Recording.GenerateAlphaNumericId(variableNamePrefix), numericVariable); var type = new TimeSeriesType(timeSeriesTypesName, variables); type.Id = timeSeriesTypeId; timeSeriesTypes.Add(type); // Act and Assert await TestTimeSeriesTypeWhereErrorIsExpected(client, timeSeriesTypes, timeSeriesTypesName).ConfigureAwait(false); }
private async Task RunQueryAggregateSeriesSample(TimeSeriesInsightsQueries queriesClient, TimeSeriesId tsId) { #region Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithNumericVariable Console.WriteLine("\n\nQuery for the average temperature over the past 30 seconds, in 2-second time slots.\n"); var numericVariable = new NumericVariable( new TimeSeriesExpression("$event.Temperature"), new TimeSeriesExpression("avg($value)")); var requestOptions = new QueryAggregateSeriesRequestOptions(); requestOptions.InlineVariables["Temperature"] = numericVariable; requestOptions.ProjectedVariableNames.Add("Temperature"); QueryAnalyzer aggregateSeriesQuery = queriesClient.CreateAggregateSeriesQuery( tsId, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(30), null, requestOptions); await foreach (TimeSeriesPoint point in aggregateSeriesQuery.GetResultsAsync()) { double?averageTemperature = point.GetNullableDouble("Temperature"); if (averageTemperature != null) { Console.WriteLine($"{point.Timestamp} - Average temperature: {averageTemperature}."); } } #endregion Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithNumericVariable #region Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithAggregateVariable Console.WriteLine("\n\nCount the number of temperature events over the past 3 minutes, in 1-minute time slots.\n"); // Get the count of events in 60-second time slots over the past 3 minutes DateTimeOffset endTime = DateTime.UtcNow; DateTimeOffset startTime = endTime.AddMinutes(-3); var aggregateVariable = new AggregateVariable( new TimeSeriesExpression("count()")); var countVariableName = "Count"; var aggregateSeriesRequestOptions = new QueryAggregateSeriesRequestOptions(); aggregateSeriesRequestOptions.InlineVariables[countVariableName] = aggregateVariable; aggregateSeriesRequestOptions.ProjectedVariableNames.Add(countVariableName); QueryAnalyzer query = queriesClient.CreateAggregateSeriesQuery( tsId, startTime, endTime, TimeSpan.FromSeconds(60), aggregateSeriesRequestOptions); await foreach (TimeSeriesPoint point in query.GetResultsAsync()) { long?temperatureCount = (long?)point.GetValue(countVariableName); Console.WriteLine($"{point.Timestamp} - Temperature count: {temperatureCount}"); } #endregion Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithAggregateVariable }
private async Task RunQuerySeriesSampleWithInlineVariables(TimeSeriesInsightsQueries queriesClient, TimeSeriesId tsId) { // Query for two series, one with the temperature values in Celsius and another in Fahrenheit #region Snippet:TimeSeriesInsightsSampleQuerySeriesWithInlineVariables Console.WriteLine("\n\nQuery for temperature series in Celsius and Fahrenheit over the past 10 minutes.\n"); var celsiusVariable = new NumericVariable( new TimeSeriesExpression("$event.Temperature"), new TimeSeriesExpression("avg($value)")); var fahrenheitVariable = new NumericVariable( new TimeSeriesExpression("$event.Temperature * 1.8 + 32"), new TimeSeriesExpression("avg($value)")); var querySeriesRequestOptions = new QuerySeriesRequestOptions(); querySeriesRequestOptions.InlineVariables["TemperatureInCelsius"] = celsiusVariable; querySeriesRequestOptions.InlineVariables["TemperatureInFahrenheit"] = fahrenheitVariable; QueryAnalyzer seriesQuery = queriesClient.CreateSeriesQuery( tsId, TimeSpan.FromMinutes(10), null, querySeriesRequestOptions); await foreach (TimeSeriesPoint point in seriesQuery.GetResultsAsync()) { double?tempInCelsius = (double?)point.GetValue("TemperatureInCelsius"); double?tempInFahrenheit = (double?)point.GetValue("TemperatureInFahrenheit"); Console.WriteLine($"{point.Timestamp} - Average temperature in Celsius: {tempInCelsius}. Average temperature in Fahrenheit: {tempInFahrenheit}."); } #endregion Snippet:TimeSeriesInsightsSampleQuerySeriesWithInlineVariables }
public void NumericVariableChangeValueTest() { var variable = new NumericVariable(3.14); Assert.AreEqual(3.14, variable.Value); variable.Value = -36; Assert.AreEqual(-36, variable.Value); }
private void CartesianToPolar(NumericVariable[] input, NumericVariable[] output) { double x = input[0].GetValue(); double y = input[1].GetValue(); NumericVariable r = output[0]; NumericVariable phi = output[1]; r.Set(Math.Sqrt(x * x + y * y)); phi.Set(Math.Atan2(y, x)); }
public void ExitSimplenumericvariable(BASICParser.SimplenumericvariableContext context) { currentSimpleNumericVariable = new SimpleNumericVariable(context.GetText()); wasArray = false; if (!varFound) { letNumericVar = currentSimpleNumericVariable; varFound = true; } }
public void ExitNumericvariable(BASICParser.NumericvariableContext context) { currentNumericVariable = wasArray ? (NumericVariable)currentNumericArrayElement : (NumericVariable)currentSimpleNumericVariable; primaryOp = PrimaryOptions.VAR; if (currentInputLine != null) { currentInputLine.vars.Add(currentNumericVariable); } }
public void TestRangeConstraint() { { var solver = new SimpleConstraintSolver(); NumericVariable a = solver.CreateVariable("a"); var r = new Range(3, 4, EPS); RangeConstraint.CreateRangeConstraint(a, r); solver.Solve(_noAbortCheck); Assert.AreEqual(r, a.Value); } }
public async Task SeedAsync(InventoryDbContext context, ILogger <InventoryContextSeed> logger) { var policy = CreatePolicy(logger, nameof(InventoryContextSeed)); await policy.ExecuteAsync(async() => { if (!context.Groups.Any()) { var operatingSystems = GetOperatingSystems(); var servers = GetFakeServers(operatingSystems); var groups = GetFakeGroups(); var sv = new StringVariable() { Name = "a", Value = "a" }; var nv = new NumericVariable() { Name = "b", Value = 1 }; var lv = new List <Variable>() { sv, nv }; groups[0].Variables = lv; foreach (Server srv in servers) { //srv.Variables = lv; var group = groups.Single(grp => grp.Name == srv.OperatingSystem.Name); group.AddServer(srv); } context.OperatingSystems.AddRange(operatingSystems); context.Groups.AddRange(groups); context.Servers.AddRange(servers); await context.SaveChangesAsync(); } }); }
public async Task TimeSeriesInsightsQuery_AggregateSeriesWithNumericVariable() { // Arrange TimeSeriesInsightsClient tsiClient = GetClient(); DeviceClient deviceClient = await GetDeviceClient().ConfigureAwait(false); // Figure out what the Time Series Id is composed of TimeSeriesModelSettings modelSettings = await tsiClient.ModelSettings.GetAsync().ConfigureAwait(false); // Create a Time Series Id where the number of keys that make up the Time Series Id is fetched from Model Settings TimeSeriesId tsiId = await GetUniqueTimeSeriesInstanceIdAsync(tsiClient, modelSettings.TimeSeriesIdProperties.Count) .ConfigureAwait(false); try { // Send some events to the IoT hub with with a second between each event await QueryTestsHelper.SendEventsToHubAsync( deviceClient, tsiId, modelSettings.TimeSeriesIdProperties.ToArray(), 30) .ConfigureAwait(false); DateTimeOffset now = Recording.UtcNow; DateTimeOffset endTime = now.AddMinutes(10); DateTimeOffset startTime = now.AddMinutes(-10); var temperatureNumericVariable = new NumericVariable( new TimeSeriesExpression($"$event.{QueryTestsHelper.Temperature}"), new TimeSeriesExpression("avg($value)")); var queryAggregateSeriesRequestOptions = new QueryAggregateSeriesRequestOptions(); queryAggregateSeriesRequestOptions.InlineVariables[QueryTestsHelper.Temperature] = temperatureNumericVariable; queryAggregateSeriesRequestOptions.ProjectedVariables.Add(QueryTestsHelper.Temperature); // This retry logic was added as the TSI instance are not immediately available after creation await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() => { QueryAnalyzer queryAggregateSeriesPages = tsiClient.Queries.CreateAggregateSeriesQueryAnalyzer( tsiId, startTime, endTime, TimeSpan.FromSeconds(5), queryAggregateSeriesRequestOptions); var nonNullFound = false; await foreach (Page <TimeSeriesPoint> aggregateSeriesPage in queryAggregateSeriesPages.GetResultsAsync().AsPages()) { foreach (TimeSeriesPoint point in aggregateSeriesPage.Values) { point.GetUniquePropertyNames().Should().HaveCount(1).And.Contain((property) => property == QueryTestsHelper.Temperature); var value = (double?)point.GetValue(QueryTestsHelper.Temperature); if (value != null) { nonNullFound = true; } } nonNullFound.Should().BeTrue(); } queryAggregateSeriesPages.Progress.Should().Be(100); return(null); }, MaxNumberOfRetries, s_retryDelay); // Add an interpolated variable var linearInterpolationNumericVariable = new NumericVariable( new TimeSeriesExpression($"$event.{QueryTestsHelper.Temperature}"), new TimeSeriesExpression("left($value)")); linearInterpolationNumericVariable.Interpolation = new InterpolationOperation { Kind = InterpolationKind.Linear, Boundary = new InterpolationBoundary() { Span = TimeSpan.FromSeconds(1), }, }; const string linearInterpolation = "linearInterpolation"; queryAggregateSeriesRequestOptions.InlineVariables[linearInterpolation] = linearInterpolationNumericVariable; queryAggregateSeriesRequestOptions.ProjectedVariables.Add(linearInterpolation); await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() => { QueryAnalyzer queryAggregateSeriesPages = tsiClient.Queries.CreateAggregateSeriesQueryAnalyzer( tsiId, startTime, endTime, TimeSpan.FromSeconds(5), queryAggregateSeriesRequestOptions); await foreach (Page <TimeSeriesPoint> aggregateSeriesPage in queryAggregateSeriesPages.GetResultsAsync().AsPages()) { aggregateSeriesPage.Values.Should().HaveCountGreaterThan(0); foreach (var point in aggregateSeriesPage.Values) { point.GetUniquePropertyNames().Should().HaveCount(2) .And .Contain((property) => property == QueryTestsHelper.Temperature) .And .Contain((property) => property == linearInterpolation); } } return(null); }, MaxNumberOfRetries, s_retryDelay); // Send 2 events with a special condition that can be used later to query on IDictionary <string, object> messageBase = QueryTestsHelper.BuildMessageBase(modelSettings.TimeSeriesIdProperties.ToArray(), tsiId); messageBase[QueryTestsHelper.Temperature] = 1.2; messageBase[QueryTestsHelper.Humidity] = 3.4; string messageBody = JsonSerializer.Serialize(messageBase); var message = new Message(Encoding.ASCII.GetBytes(messageBody)) { ContentType = "application/json", ContentEncoding = "utf-8", }; Func <Task> sendEventAct = async() => await deviceClient.SendEventAsync(message).ConfigureAwait(false); sendEventAct.Should().NotThrow(); // Send it again sendEventAct.Should().NotThrow(); // Query for the two events with a filter queryAggregateSeriesRequestOptions.Filter = "$event.Temperature.Double = 1.2"; await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() => { QueryAnalyzer queryAggregateSeriesPages = tsiClient.Queries.CreateAggregateSeriesQueryAnalyzer( tsiId, startTime, endTime, TimeSpan.FromSeconds(5), queryAggregateSeriesRequestOptions); var valueFound = false; await foreach (TimeSeriesPoint point in queryAggregateSeriesPages.GetResultsAsync()) { point.GetUniquePropertyNames().Should().HaveCount(2) .And .Contain((property) => property == QueryTestsHelper.Temperature) .And .Contain((property) => property == linearInterpolation); var value = (double?)point.GetValue(QueryTestsHelper.Temperature); if (value == 1.2) { valueFound = true; } } valueFound.Should().BeTrue(); return(null); }, MaxNumberOfRetries, s_retryDelay); } finally { deviceClient?.Dispose(); } }
private async Task RunQuerySeriesSampleWithPreDefinedVariables(TimeSeriesInsightsClient client, TimeSeriesId tsId) { // Setup TimeSeriesInsightsInstances instancesClient = client.GetInstancesClient(); TimeSeriesInsightsTypes typesClient = client.GetTypesClient(); TimeSeriesInsightsQueries queriesClient = client.GetQueriesClient(); // First create the Time Series type along with the numeric variables var timeSeriesTypes = new List <TimeSeriesType>(); var celsiusVariable = new NumericVariable( new TimeSeriesExpression("$event.Temperature"), new TimeSeriesExpression("avg($value)")); var fahrenheitVariable = new NumericVariable( new TimeSeriesExpression("$event.Temperature * 1.8 + 32"), new TimeSeriesExpression("avg($value)")); var celsiusVariableName = "TemperatureInCelsius"; var fahrenheitVariableName = "TemperatureInFahrenheit"; var variables = new Dictionary <string, TimeSeriesVariable> { { celsiusVariableName, celsiusVariable }, { fahrenheitVariableName, fahrenheitVariable } }; timeSeriesTypes.Add(new TimeSeriesType("TemperatureSensor", variables) { Id = "TemperatureSensorTypeId" }); Response <TimeSeriesTypeOperationResult[]> createTypesResult = await typesClient .CreateOrReplaceAsync(timeSeriesTypes) .ConfigureAwait(false); if (createTypesResult.Value.First().Error != null) { Console.WriteLine($"\n\nFailed to create a Time Series Insights type. " + $"Error Message: '{createTypesResult.Value.First().Error.Message}.' " + $"Code: '{createTypesResult.Value.First().Error.Code}'."); } // Get the Time Series instance and replace its type with the one we just created Response <InstancesOperationResult[]> getInstanceResult = await instancesClient .GetAsync(new List <TimeSeriesId> { tsId }); if (getInstanceResult.Value.First().Error != null) { Console.WriteLine($"\n\nFailed to retrieve Time Series instance with Id '{tsId}'. " + $"Error Message: '{getInstanceResult.Value.First().Error.Message}.' " + $"Code: '{getInstanceResult.Value.First().Error.Code}'."); } TimeSeriesInstance instanceToReplace = getInstanceResult.Value.First().Instance; instanceToReplace.TypeId = createTypesResult.Value.First().TimeSeriesType.Id; Response <InstancesOperationResult[]> replaceInstanceResult = await instancesClient .ReplaceAsync(new List <TimeSeriesInstance> { instanceToReplace }); if (replaceInstanceResult.Value.First().Error != null) { Console.WriteLine($"\n\nFailed to retrieve Time Series instance with Id '{tsId}'. " + $"Error Message: '{replaceInstanceResult.Value.First().Error.Message}.' " + $"Code: '{replaceInstanceResult.Value.First().Error.Code}'."); } // Now that we set up the instance with the property type, query for the data #region Snippet:TimeSeriesInsightsSampleQuerySeries Console.WriteLine($"\n\nQuery for temperature series in Celsius and Fahrenheit over the past 10 minutes. " + $"The Time Series instance belongs to a type that has predefined numeric variable that represents the temperature " + $"in Celsuis, and a predefined numeric variable that represents the temperature in Fahrenheit.\n"); DateTimeOffset endTime = DateTime.UtcNow; DateTimeOffset startTime = endTime.AddMinutes(-10); QueryAnalyzer seriesQuery = queriesClient.CreateSeriesQuery( tsId, startTime, endTime); await foreach (TimeSeriesPoint point in seriesQuery.GetResultsAsync()) { double?tempInCelsius = point.GetNullableDouble(celsiusVariableName); double?tempInFahrenheit = point.GetNullableDouble(fahrenheitVariableName); Console.WriteLine($"{point.Timestamp} - Average temperature in Celsius: {tempInCelsius}. " + $"Average temperature in Fahrenheit: {tempInFahrenheit}."); } #endregion Snippet:TimeSeriesInsightsSampleQuerySeries }
public async Task TimeSeriesInsightsQuery_GetSeriesLifecycle() { // Arrange TimeSeriesInsightsClient tsiClient = GetClient(); DeviceClient deviceClient = await GetDeviceClient().ConfigureAwait(false); // Figure out what the Time Series Id is composed of TimeSeriesModelSettings modelSettings = await tsiClient.ModelSettings.GetAsync().ConfigureAwait(false); // Create a Time Series Id where the number of keys that make up the Time Series Id is fetched from Model Settings TimeSeriesId tsiId = await GetUniqueTimeSeriesInstanceIdAsync(tsiClient, modelSettings.TimeSeriesIdProperties.Count) .ConfigureAwait(false); try { // Send some events to the IoT hub await QueryTestsHelper.SendEventsToHubAsync( deviceClient, tsiId, modelSettings.TimeSeriesIdProperties.ToArray(), 10) .ConfigureAwait(false); // Act // Query for temperature events with two calculateions. First with the temperature value as is, and the second // with the temperature value multiplied by 2. DateTimeOffset now = Recording.UtcNow; DateTimeOffset endTime = now.AddMinutes(10); DateTimeOffset startTime = now.AddMinutes(-10); var temperatureNumericVariable = new NumericVariable( new TimeSeriesExpression($"$event.{QueryTestsHelper.Temperature}"), new TimeSeriesExpression("avg($value)")); var temperatureNumericVariableTimesTwo = new NumericVariable( new TimeSeriesExpression($"$event.{QueryTestsHelper.Temperature} * 2"), new TimeSeriesExpression("avg($value)")); var temperatureTimesTwoVariableName = $"{QueryTestsHelper.Temperature}TimesTwo"; var querySeriesRequestOptions = new QuerySeriesRequestOptions(); querySeriesRequestOptions.InlineVariables[QueryTestsHelper.Temperature] = temperatureNumericVariable; querySeriesRequestOptions.InlineVariables[temperatureTimesTwoVariableName] = temperatureNumericVariableTimesTwo; // This retry logic was added as the TSI instance are not immediately available after creation await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() => { AsyncPageable <QueryResultPage> querySeriesEventsPages = tsiClient.Query.GetSeriesAsync( tsiId, startTime, endTime, querySeriesRequestOptions); await foreach (QueryResultPage seriesEventsPage in querySeriesEventsPages) { seriesEventsPage.Timestamps.Should().HaveCount(10); seriesEventsPage.Timestamps.Should().OnlyContain(timeStamp => timeStamp >= startTime) .And .OnlyContain(timeStamp => timeStamp <= endTime); seriesEventsPage.Properties.Count.Should().Be(3); // EventCount, Temperature and TemperatureTimesTwo seriesEventsPage.Properties.Should().Contain((property) => property.Name == QueryTestsHelper.Temperature) .And .Contain((property) => property.Name == temperatureTimesTwoVariableName); // Assert that the values for the Temperature property is equal to the values for the other property, multiplied by 2 var temperatureValues = seriesEventsPage .Properties .First((property) => property.Name == QueryTestsHelper.Temperature) .Values.Cast <double>().ToList(); var temperatureTimesTwoValues = seriesEventsPage .Properties .First((property) => property.Name == temperatureTimesTwoVariableName) .Values.Cast <double>().ToList(); temperatureTimesTwoValues.Should().Equal(temperatureValues.Select((property) => property * 2).ToList()); } return(null); }, MaxNumberOfRetries, s_retryDelay); // Query for all the series events using a timespan AsyncPageable <QueryResultPage> querySeriesEventsPagesWithTimespan = tsiClient.Query.GetSeriesAsync(tsiId, TimeSpan.FromMinutes(10), null, querySeriesRequestOptions); await foreach (QueryResultPage seriesEventsPage in querySeriesEventsPagesWithTimespan) { seriesEventsPage.Timestamps.Should().HaveCount(10); seriesEventsPage.Properties.Count.Should().Be(3); // EventCount, Temperature and TemperatureTimesTwo } // Query for temperature and humidity var humidityNumericVariable = new NumericVariable( new TimeSeriesExpression("$event.Humidity"), new TimeSeriesExpression("avg($value)")); querySeriesRequestOptions.InlineVariables[QueryTestsHelper.Humidity] = humidityNumericVariable; querySeriesRequestOptions.ProjectedVariables.Add(QueryTestsHelper.Temperature); querySeriesRequestOptions.ProjectedVariables.Add(QueryTestsHelper.Humidity); await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() => { AsyncPageable <QueryResultPage> querySeriesEventsPages = tsiClient.Query.GetSeriesAsync(tsiId, startTime, endTime, querySeriesRequestOptions); await foreach (QueryResultPage seriesEventsPage in querySeriesEventsPages) { seriesEventsPage.Timestamps.Should().HaveCount(10); seriesEventsPage.Timestamps.Should().OnlyContain(timeStamp => timeStamp >= startTime) .And .OnlyContain(timeStamp => timeStamp <= endTime); seriesEventsPage.Properties.Count.Should().Be(2); // Temperature and Humidity seriesEventsPage.Properties.Should().Contain((property) => property.Name == QueryTestsHelper.Temperature) .And .Contain((property) => property.Name == QueryTestsHelper.Humidity); } return(null); }, MaxNumberOfRetries, s_retryDelay); // Send 2 events with a special condition that can be used later to query on IDictionary <string, object> messageBase = QueryTestsHelper.BuildMessageBase(modelSettings.TimeSeriesIdProperties.ToArray(), tsiId); messageBase[QueryTestsHelper.Temperature] = 1.2; messageBase[QueryTestsHelper.Humidity] = 3.4; string messageBody = JsonSerializer.Serialize(messageBase); var message = new Message(Encoding.ASCII.GetBytes(messageBody)) { ContentType = "application/json", ContentEncoding = "utf-8", }; Func <Task> sendEventAct = async() => await deviceClient.SendEventAsync(message).ConfigureAwait(false); sendEventAct.Should().NotThrow(); // Send it again sendEventAct.Should().NotThrow(); // Query for the two events with a filter querySeriesRequestOptions.Filter = "$event.Temperature.Double = 1.2"; await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() => { AsyncPageable <QueryResultPage> querySeriesEventsPages = tsiClient.Query.GetSeriesAsync(tsiId, startTime, endTime, querySeriesRequestOptions); await foreach (QueryResultPage seriesEventsPage in querySeriesEventsPages) { seriesEventsPage.Timestamps.Should().HaveCount(2); seriesEventsPage.Properties.Should().HaveCount(2) .And .Contain((property) => property.Name == QueryTestsHelper.Temperature) .And .Contain((property) => property.Name == QueryTestsHelper.Humidity); var temperatureValues = seriesEventsPage .Properties .First((property) => property.Name == QueryTestsHelper.Temperature) .Values.Cast <double>().ToList(); temperatureValues.Should().AllBeEquivalentTo(1.2); } return(null); }, MaxNumberOfRetries, s_retryDelay); // Query for the two events with a filter, but only take 1 querySeriesRequestOptions.MaximumNumberOfEvents = 1; AsyncPageable <QueryResultPage> querySeriesEventsPagesWithFilter = tsiClient.Query.GetSeriesAsync(tsiId, startTime, endTime, querySeriesRequestOptions); await foreach (QueryResultPage seriesEventsPage in querySeriesEventsPagesWithFilter) { seriesEventsPage.Timestamps.Should().HaveCount(1); seriesEventsPage.Properties.Should().HaveCount(2) .And .Contain((property) => property.Name == QueryTestsHelper.Temperature) .And .Contain((property) => property.Name == QueryTestsHelper.Humidity); var temperatureValues = seriesEventsPage .Properties .First((property) => property.Name == QueryTestsHelper.Temperature) .Values.Cast <double>().ToList(); temperatureValues.Should().AllBeEquivalentTo(1.2); } } finally { deviceClient?.Dispose(); } }
private static void Check(Node node, [NotNull] FunctionCall call, [NotNull] FunctionDeclaration definition) { var table = node.SymbolTable; var parameters = definition.Profile.Parameters; var callerProfile = call.AsProfile(node); var callArgsCount = call.Arguments != null ? call.Arguments.Length : 0; if (callArgsCount > parameters.Count) { var m = string.Format("Function '{0}' only takes {1} parameter(s)", call.FunctionName, parameters.Count); DiagnosticUtils.AddError(node, m); } if (callerProfile.InputParameters.Count != definition.Profile.InputParameters.Count || callerProfile.InoutParameters.Count != definition.Profile.InoutParameters.Count || callerProfile.OutputParameters.Count != definition.Profile.OutputParameters.Count) { var m = string.Format("No suitable function signature found for '{0}' {1}", call.FunctionName, callerProfile.GetSignature()); DiagnosticUtils.AddError(node, m); } for (int c = 0; c < parameters.Count; c++) { var expected = parameters[c]; if (c < callArgsCount) { //Omitted if (call.Arguments[c].IsOmitted) { if (expected.IsOmittable) { continue; } else { DiagnosticUtils.AddError(node, "Omitted not allowed for this parameter"); return; } } var actual = call.Arguments[c].StorageAreaOrValue; if (actual.IsLiteral) { continue; //TODO } var callArgName = actual.StorageArea.ToString(); var found = node.GetDataDefinitionFromStorageAreaDictionary(actual.StorageArea); if (found == null) { continue; } var actualDataDefinition = found; var actualSpecialRegister = actual.StorageArea as StorageAreaPropertySpecialRegister; if (actualSpecialRegister != null) { var tokenType = actualSpecialRegister.SpecialRegisterName.TokenType; if (tokenType == TokenType.LENGTH) { if (call is ProcedureCall) { ProcedureCall procedureCall = call as ProcedureCall; if (procedureCall.OutputParameters.Contains(call.Arguments[c])) { DiagnosticUtils.AddError(node, "LENGTH cannot be used as an output", actualSpecialRegister.SpecialRegisterName); continue; } } // accepted format is "PIC [S]9(5..9) comp-5" if (expected.PrimitiveDataType.Name != "Numeric" || expected.Length < 5 || expected.Length > 9 || expected.Usage != DataUsage.NativeBinary) { DiagnosticUtils.AddError(node, "LENGTH can only be used as PIC S9(5..9) comp-5", actualSpecialRegister.SpecialRegisterName); continue; } } else if (tokenType == TokenType.ADDRESS && expected.Usage == DataUsage.Pointer) { if (!actualDataDefinition.IsFlagSet(Node.Flag.LinkageSectionNode) && call.Arguments[c].SharingMode.Value == ParameterSharingMode.ByReference) { DiagnosticUtils.AddError(node, "ADDRESS OF can only be used with a LINKAGE variable, or with a sharing mode BY CONTENT/BY VALUE", actualSpecialRegister.SpecialRegisterName); } continue; } else if (tokenType == TokenType.LINAGE_COUNTER) { //Do not know what to do : RFC DiagnosticUtils.AddError(node, "LINAGE_COUNTER not allowed yet with procedure"); return; } continue; //If it's a special register we don't want to check more rules. } //TODO use SubscriptExpression and ReferenceModifier of the StorageArea to correct the type //Ex: MyVar1(1:10) has a length of 10 and is of type Alphanumeric //Ex: MyArray(1) only target one element of the array, so we need to get the type of this element. //If the actual dataDefinition is a table occurence try to match it with subscripts //If the actual dataDefinition is under a table occurence, then don't care about subscripts long actualMinOccurencesCount = actualDataDefinition.MinOccurencesCount; long actualMaxOccurencesCount = actualDataDefinition.MaxOccurencesCount; bool actualHasUnboundedNumberOfOccurences = actualDataDefinition.HasUnboundedNumberOfOccurences; NumericVariable actualOccursDependingOn = actualDataDefinition.OccursDependingOn; bool actualIsTableOccurence = actualDataDefinition.IsTableOccurence; if (actualDataDefinition.IsTableOccurence) { var subscriptedStorageArea = actual.StorageArea as DataOrConditionStorageArea; if (subscriptedStorageArea != null && subscriptedStorageArea.Subscripts.Count > 0) { //if there are subscripts //Do not allow ALL if (subscriptedStorageArea.Subscripts.Any(s => s.ALL != null)) { DiagnosticUtils.AddError(node, "You cannot use ALL for procedure argument"); return; } actualMinOccurencesCount = 0; actualMaxOccurencesCount = 0; actualHasUnboundedNumberOfOccurences = false; actualOccursDependingOn = null; actualIsTableOccurence = false; } } //Cobol 85 Type will be checked with their picture if (actualDataDefinition.DataType.CobolLanguageLevel > CobolLanguageLevel.Cobol85 || expected.DataType.CobolLanguageLevel > CobolLanguageLevel.Cobol85) { if (actualDataDefinition.DataType.CobolLanguageLevel == CobolLanguageLevel.Cobol85 || expected.DataType.CobolLanguageLevel == CobolLanguageLevel.Cobol85) { var m = string.Format( "Function '{0}' expected parameter '{1}' of type {2} and received '{3}' of type {4} ", call.FunctionName, expected.Name, expected.DataType, callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.DataType); DiagnosticUtils.AddError(node, m); } else if (actualDataDefinition.DataType != expected.DataType) { TypeDefinition callerType = actualDataDefinition.TypeDefinition; TypeDefinition calleeType = expected.TypeDefinition; if (callerType == null || calleeType == null) { //Ignore, it's an unknown DataType. It's already checked } else if (!Equals(callerType.QualifiedName, calleeType.QualifiedName)) { var m = string.Format( "Function '{0}' expected parameter '{1}' of type {2} and received '{3}' of type {4} ", call.FunctionName, calleeType.Name, calleeType.DataType, callArgName ?? string.Format("position {0}", c + 1), callerType.DataType); DiagnosticUtils.AddError(node, m); } } } if (actualDataDefinition.Picture != null && expected.Picture != null && actualDataDefinition.Picture.NormalizedValue != expected.Picture.NormalizedValue) { var m = string.Format( "Function '{0}' expected parameter '{1}' with picture {2} and received '{3}' with picture {4}", call.FunctionName, expected.Name, expected.Picture.Value, callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.Picture.Value); DiagnosticUtils.AddError(node, m); } // if (dataDefinitionOfActual.Length != expectedParameter.Length) // { // var m = // string.Format( // "Function '{0}' expected parameter '{1}' of length {2} and received '{3}' of length {4}", // call.FunctionName, expectedParameter.Name, expectedParameter.Length, // callArgName ?? string.Format("position {0}", c + 1), dataDefinitionOfActual.Length); // DiagnosticUtils.AddError(e, m); // } if (actualDataDefinition.Usage != expected.Usage) { var m = string.Format( "Function '{0}' expected parameter '{1}' of usage {2} and received '{3}' of usage {4}", call.FunctionName, expected.Name, expected.Usage, callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.Usage); DiagnosticUtils.AddError(node, m); } if (actualDataDefinition.IsJustified != expected.IsJustified) { var m = string.Format( "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}", call.FunctionName, expected.Name, expected.IsJustified ? "justified" : "non-justified", callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.IsJustified ? "justified" : "non-justified"); DiagnosticUtils.AddError(node, m); } if (actualDataDefinition.IsGroupUsageNational != expected.IsGroupUsageNational) { var m = string.Format( "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}", call.FunctionName, expected.Name, expected.IsGroupUsageNational ? "national group-usage" : "non national group-usage", callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.IsGroupUsageNational ? "national group-usage" : "non national group-usage"); DiagnosticUtils.AddError(node, m); } //Array if (actualIsTableOccurence != expected.IsTableOccurence) { var m = string.Format( "Function '{0}' expected parameter '{1}' to {2} an array and received '{3}' which {4} an array", call.FunctionName, expected.Name, expected.IsTableOccurence ? "be" : "be NOT", actualDataDefinition.Name, actualIsTableOccurence ? "is" : "is NOT "); DiagnosticUtils.AddError(node, m); } else if (actualIsTableOccurence && expected.IsTableOccurence) { if (actualMinOccurencesCount != expected.MinOccurencesCount) { var m = string.Format( "Function '{0}' expected parameter '{1}' to have at least {2} occurences and received '{3}' with a minimum of {4} occurences", call.FunctionName, expected.Name, expected.MinOccurencesCount, callArgName ?? string.Format("position {0}", c + 1), actualMinOccurencesCount); DiagnosticUtils.AddError(node, m); } if (actualMaxOccurencesCount != expected.MaxOccurencesCount) { var m = string.Format( "Function '{0}' expected parameter '{1}' to have at most {2} occurences and received '{3}' with a maximum of {4} occurences", call.FunctionName, expected.Name, expected.MaxOccurencesCount, callArgName ?? string.Format("position {0}", c + 1), actualMaxOccurencesCount); DiagnosticUtils.AddError(node, m); } } if (actualOccursDependingOn != expected.OccursDependingOn) { var m = string.Format( "Function '{0}' expected parameter '{1}' occurs depending on ({2}) occurences and received '{3}' occurs depending on ({4})", call.FunctionName, expected.Name, expected.OccursDependingOn, callArgName ?? string.Format("position {0}", c + 1), actualOccursDependingOn); DiagnosticUtils.AddError(node, m); } if (actualHasUnboundedNumberOfOccurences != expected.HasUnboundedNumberOfOccurences) { var m = string.Format( "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}", call.FunctionName, expected.Name, expected.HasUnboundedNumberOfOccurences ? "has unbounded number of occurences" : "hasn't unbounded number of occurences", callArgName ?? string.Format("position {0}", c + 1), actualHasUnboundedNumberOfOccurences ? "has unbounded number of occurences" : "hasn't unbounded number of occurences"); DiagnosticUtils.AddError(node, m); } if (actualDataDefinition.SignIsSeparate != expected.SignIsSeparate) { var m = string.Format( "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}", call.FunctionName, expected.Name, expected.HasUnboundedNumberOfOccurences ? "has unbounded number of occurences" : "hasn't unbounded number of occurences", callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.HasUnboundedNumberOfOccurences ? "has unbounded number of occurences" : "hasn't unbounded number of occurences"); DiagnosticUtils.AddError(node, m); } if (actualDataDefinition.SignPosition != expected.SignPosition) { var m = string.Format( "Function '{0}' expected parameter '{1}' with sign position {2} and received '{3}' with sign position {4}", call.FunctionName, expected.Name, expected.SignPosition == null ? "empty" : expected.SignPosition.ToString(), callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.SignPosition == null ? "empty" : actualDataDefinition.SignPosition.ToString()); DiagnosticUtils.AddError(node, m); } if (actualDataDefinition.IsSynchronized != expected.IsSynchronized) { var m = string.Format( "Function '{0}' expected parameter '{1}' {2} and received '{3}' {4}", call.FunctionName, expected.Name, expected.IsSynchronized ? "synchonized" : "not synchronized", callArgName ?? string.Format("position {0}", c + 1), actualDataDefinition.IsSynchronized ? "synchonized" : "not synchronized"); DiagnosticUtils.AddError(node, m); } if (actualDataDefinition.ObjectReferenceClass != expected.ObjectReferenceClass) { var m = string.Format( "Function '{0}' expected parameter '{1}' and received '{2}' with wrong object reference.", call.FunctionName, expected.Name, callArgName ?? string.Format("position {0}", c + 1)); DiagnosticUtils.AddError(node, m); } } else { var m = string.Format("Function '{0}' is missing parameter '{1}' of type {2} and length {3}", call.FunctionName, expected.Name, expected.DataType, expected.Length); DiagnosticUtils.AddError(node, m); } } }
protected override void PlaceObjects([NotNull, ItemNotNull] IEnumerable <Dependency> dependencies) { // ASCII-art sketch of what I want to accomplish: // // | | | | | |<--------+-----+ // | | | | |<-----------------| | // | | | |<----------------------------| Top | // | | |<------------------------------------------| | // | |<----------------------------------------------------+-----+ // | | | | | | // | | | | |<-------+-----+ // | | | |<------------------| | // | | |<--------------------------------| IMP | // | |<------------------------------------------| | // |<----------------------------------------------------+-----+ // | | | | | | // | | | |<---------+-----+ | // | | |<-----------------------| | | // | |<---------------------------------| WLG | | // |<-------------------------------------------+-----+ | // | | | | | | | | // | | |<------------| | | | | // | | | |<::::::::::+-----+ | | | | // | |<----------|-----------| VKF |----|--------->| // |<--------------------|-----------+-----+ | | | | // | | | | | | | | | Imp.MI // |<--------------------|---------------| | | | // |<--------------------|-------------| | | | | // | | | | ... | | | | | // | | | | | | | | | // | | +-----+=================>| | | // | | | KAH |---------->| | | // | | +-----+-------->| | | | // | | | | | | | // | +-----+------------------------------->| // | | |----------------------------->| | // | | KST |-------------------->| | | // | | |------------------>| | | | // |<--------+-----+---->| | | | | // | | | | | | // | ... | | | | | // | Kah Vkf1 Vkf2 Wlg1 Wlg2 // +-----+ .MI .MI .MI .MI .MI // | BAC | // +-----+ // // ===> is a dependency from a "lower" to a "higher" module // that circumvents the MI. It should most probably be flagged // as incorrect and then red in the diagram. // :::> is a dependency from a "higher" to a "lower" module // via an MI ("module interface"). This is ok, it is only // highlighted to show that the Renderer must be able to deal // with this. // The itemtype is expected to have 3 fields Name:Module:Order. // In the example diagram above, we would have items about like the following: // BAC :BAC:0100 // KST :KST:0200 // KAH :KAH:0300 // Kah.MI :KAH:0301 // VKF :VKF:0400 // Vkf1.MI:VKF:0401 // Vkf2.MI:VKF:0402 // WLG :WLG:0500 // Wlg1.MI:WLG:0501 // Wlg2.MI:WLG:0502 // IMP :IMP:0600 // Imp.MI :IMP:0601 // Top :TOP:0700 VariableVector itemDistance = new VariableVector(nameof(itemDistance), Solver); VariableVector pos = F(0, 30); //itemDistance.MaxY(80); //itemDistance.SetX(300); Arrow(F(0, 0), F(100, 0), 1, Color.Chartreuse, "100px", textFont: _lineFont); Box(F(200, 0), _title + "(" + DateTime.Now + ")", boxAnchoring: BoxAnchoring.LowerLeft); const int DELTA_Y_MAIN = 8; IEnumerable <Item> items = dependencies.SelectMany(e => new[] { e.UsingItem, e.UsedItem }).Distinct(); IEnumerable <Item> parents = items.Where(i => !IsMI(i)); IEnumerable <Item> misWithoutParent = items.Where(i => IsMI(i) && parents.All(p => GetModule(p) != GetModule(i))); var mainBoxes = new Dictionary <Item, IBox>(); var interfaceBoxes = new Dictionary <Item, IBox>(); var mainBoxesNextFreePos = new Dictionary <Item, VariableVector>(); var interfaceBoxesNextFreePos = new Dictionary <Item, VariableVector>(); var mainItems = new Dictionary <Item, Item>(); // Main modules along diagonal, separated by itemDistance foreach (var i in parents.Concat(misWithoutParent).OrderBy(_orderSupport.OrderSelector)) { string name = GetName(i); string countText = "\n<" + Sum(dependencies, d => d.UsingItem.Equals(i) && !d.UsedItem.Equals(i)) + " =" + Sum(dependencies, d => d.UsingItem.Equals(i) && d.UsedItem.Equals(i)) + " >" + Sum(dependencies, d => !d.UsingItem.Equals(i) && d.UsedItem.Equals(i)); // TODO: Add option and computation to split this into .,?,! pos.AlsoNamed(name); IBox mainBox = Box(pos, boxAnchoring: BoxAnchoring.LowerLeft, text: name + countText, borderWidth: 3, boxColor: IsMI(i) ? Color.LemonChiffon : Color.Coral, textFont: _boxFont, drawingOrder: 1, fixingOrder: 4); //mainBox.Diagonal.Y.Set(100); //mainBox.Diagonal.Y.Min(40); mainBox.Diagonal.Y.Max(60 + dependencies.Count(d => Equals(d.UsingItem, i)) * DELTA_Y_MAIN); // Help for solving mainBox.Diagonal.Y.Min(10 + dependencies.Count(d => Equals(d.UsingItem, i)) * DELTA_Y_MAIN); // Help for solving mainBoxes[i] = mainBox; mainBoxesNextFreePos[i] = mainBox.LowerLeft; { IBox interfaceBox = Box(new VariableVector(name + ".I", Solver).SetX(mainBox.LowerLeft.X), text: "", boxAnchoring: BoxAnchoring.LowerLeft, borderWidth: 1, boxColor: Color.Coral, fixingOrder: 3); interfaceBox.Diagonal.SetX(10); interfaceBox.UpperLeft.MinY(mainBox.UpperLeft.Y + 7); interfaceBox.LowerLeft.MaxY(mainBox.LowerLeft.Y - 7); interfaceBoxes[i] = interfaceBox; interfaceBoxesNextFreePos[i] = mainBox.LowerLeft - F(0, 10); } NumericVariable interfacePos = Solver.CreateConstant("", 18); foreach (var mi in items.Where(mi => IsMI(mi) && GetModule(mi) == GetModule(i)).OrderBy(_orderSupport.OrderSelector)) { VariableVector miPos = new VariableVector(name + _interfaceSelector, Solver).SetX(mainBox.CenterLeft.X + interfacePos); var miBox = Box(miPos, text: GetName(mi), boxAnchoring: BoxAnchoring.UpperLeft, boxTextPlacement: BoxTextPlacement.LeftUp, borderWidth: 1, boxColor: Color.LemonChiffon, textFont: _interfaceFont, fixingOrder: 3); mainItems[mi] = i; interfaceBoxes[mi] = miBox; miBox.UpperLeft.MinY(mainBox.UpperLeft.Y + 7); miBox.LowerLeft.MaxY(mainBox.LowerLeft.Y - miBox.TextBox.Y); interfacePos += 18; } mainBox.Diagonal.MinX(interfacePos); itemDistance.MinX(mainBox.Diagonal.X + 12); itemDistance.MinY(mainBox.Diagonal.Y + 15); pos += itemDistance; } foreach (var d in dependencies) { Item from = d.UsingItem; Item to = d.UsedItem; if (IsMI(from)) { IBox fromBox = interfaceBoxes[from]; Item mainItem = mainItems[from]; VariableVector nextFreePos = interfaceBoxesNextFreePos[mainItem]; VariableVector fromPos = new VariableVector(from + "->" + to, fromBox.LowerLeft.X, nextFreePos.Y); ArrowToInterfaceBox(fromBox, interfaceBoxes[to], fromPos, d, "(I)"); interfaceBoxesNextFreePos[mainItem] -= F(0, 15); } else { IBox mainBox = mainBoxes[from]; VariableVector fromPos = mainBoxesNextFreePos[from]; ArrowToInterfaceBox(mainBox, interfaceBoxes[to], fromPos, d, ""); mainBoxesNextFreePos[from] += F(0, DELTA_Y_MAIN); itemDistance.MinY(fromPos.Y - mainBox.LowerLeft.Y); // mainBox.Diagonal.MinY(fromPos.Y - mainBox.LowerLeft.Y); ==> NO SOLUTION; therefore explcit computation above } } }
protected override void PlaceObjects([NotNull, ItemNotNull] IEnumerable <Dependency> dependencies) { // ASCII-art sketch of what I want to accomplish: // +-----+ // | |--------------------------------------------->| // | VKF |--------->| | // +-----+ | | // | | // +-----+ | | // | |--------------------------------------------->| // | WLG |--------------------->| | // +-----+ | | | // | | | // +-----+ | | | // | |--------------------------------->| | // | KST |--------------------->| | | // | |--------->| | | | // +-----+ | | | | // +-------+ +-------+ +-------+ +-------+ // | IMP.A | | IMP.B | | IMP.C | | IMP.D | // +-------+ +-------+ +-------+ +-------+ // // The itemtype is expected to have 1 or 2 fields Name[:HtmlRef] // In the example diagram above, we would have items about like the following: // BAC: // WLG: // KST: // IMP.A: // IMP.B: // IMP.C: // IMP.D: Arrow(F(0, 0), F(100, 0), 1, Color.Chartreuse, "100px", textFont: _lineFont); Box(F(-20, -20), _title + "(" + DateTime.Now + ")", boxAnchoring: BoxAnchoring.UpperRight); List <Item> yItems = dependencies.Select(e => e.UsingItem).Distinct().ToList(); List <Item> xItems = dependencies.Select(e => e.UsedItem).Distinct(). Where(i => _bottomItemMatch == null || _bottomItemMatch.Matches(i).Success). ToList(); Dependency[] relevantDependencies = dependencies.Where(d => yItems.Contains(d.UsingItem) && xItems.Contains(d.UsedItem)).ToArray(); if (_showOnlyReferencedOnBottom) { xItems.RemoveAll(ix => !relevantDependencies.Any(d => d.UsedItem.Equals(ix))); } if (_showOnlyReferencingOnLeft) { yItems.RemoveAll(iy => !relevantDependencies.Any(d => d.UsingItem.Equals(iy))); } _orderSupport.SortWithEdgeCount(xItems, relevantDependencies, (i, d) => d.UsedItem.Equals(i)); _orderSupport.SortWithEdgeCount(yItems, relevantDependencies, (i, d) => d.UsingItem.Equals(i)); double x = 100; var xBoxes = new Dictionary <Item, IBox>(); foreach (var ix in xItems) { string name = GetName(ix); var xPos = new VariableVector(name + ".POS", Solver); IBox box = Box(xPos, boxAnchoring: BoxAnchoring.LowerLeft, text: name, borderWidth: 3, boxColor: Color.LemonChiffon, boxTextPlacement: BoxTextPlacement.LeftUp, textFont: _boxFont, drawingOrder: 1, fixingOrder: 4, htmlRef: GetXHtmlRef(ix)); xPos.SetX(x).SetY(-box.TextBox.Y); xBoxes[ix] = box; x += 40; } const int DELTA_Y_MAIN = 12; NumericVariable y = Solver.CreateConstant("y", 10); foreach (var iy in yItems) { string name = GetName(iy); var yPos = new VariableVector(name + ".POS", Solver); IBox box = Box(yPos, boxAnchoring: BoxAnchoring.LowerRight, text: name, borderWidth: 3, boxColor: Color.Coral, boxTextPlacement: BoxTextPlacement.Left, textFont: _boxFont, drawingOrder: 1, fixingOrder: 4, htmlRef: GetYHtmlRef(iy) ?? GetXHtmlRef(iy)); yPos.SetX(0).SetY(y); double minBoxHeight = 45; foreach (var d in relevantDependencies.Where(d => iy.Equals(d.UsingItem))) { IBox usedBox = xBoxes[d.UsedItem]; yPos += F(0, 3); Arrow(yPos, new VariableVector(name + "->...", usedBox.LowerLeft.X, yPos.Y), width: 2, color: d.NotOkCt > 0 ? Color.Red : d.QuestionableCt > 0 ? Color.Blue : Color.Black, text: "#=" + d.Ct, placement: LineTextPlacement.Left, textLocation: -85, edgeInfo: d.ExampleInfo, drawingOrder: 1); usedBox.UpperRight.MinY(yPos.Y + 5); yPos += F(0, DELTA_Y_MAIN); minBoxHeight += DELTA_Y_MAIN; box.UpperRight.MinY(yPos.Y); } box.Diagonal.MinY(minBoxHeight); //Console.WriteLine(name + ".LR.Y=" + y + " .H>=" + minBoxHeight + " H.ShortName=" + box.Diagonal.Y.ShortName); y += minBoxHeight + 10; } //string countText = "\n<" + SumAsString(dependencies, d => d.UsingItem.Equals(i) && !d.UsedItem.Equals(i)) // + " =" + SumAsString(dependencies, d => d.UsingItem.Equals(i) && d.UsedItem.Equals(i)) // + " >" + SumAsString(dependencies, d => !d.UsingItem.Equals(i) && d.UsedItem.Equals(i)); // TODO: Add option and computation to split this into .,?,! }
public void NumericVariableInitialValueTest() { var variable = new NumericVariable(3.14); Assert.AreEqual(3.14, variable.Value); }