public GetCompoundAssetLevelStatsOutput GetCompoundAssetLevelStats(GetCompoundAssetLevelStatsInput input) { var localize = _localizationManager.GetSource("AssetManager"); string[] localizedDirectionNames = new string[4] { localize.GetString("DirectionNone"), localize.GetString("DirectionLow"), localize.GetString("DirectionFocus"), localize.GetString("DirectionHigh") }; int? minCriticality = input.MinCriticality; int? maxCriticality = input.MaxCriticality; Asset asset = _assetManager.GetAsset(input.AssetId, input.AssetName); Asset assetParent = (asset != null) ? _assetManager.GetAssetParent(asset.Id, asset.Name) : null; AssetType assetType = (asset == null) ? _assetManager.GetAssetType(input.AssetTypeId, input.AssetTypeName) : null; List<Asset> assets = new List<Asset>(); List<AssetLevelStats> childAssetStats = null; // Which children to include? // If an asset or asset type is specified, then the flag is either present or absent. Treat "none" as absent. // If neither an asset nor an asset type are specified, then the flag determines whether to return // all top level assets OR all asset types. string children = !string.IsNullOrEmpty(input.IncludeChildren) ? input.IncludeChildren.ToLower().Substring(0,1) : "n"; WhichChildren includeChildren = WhichChildren.None; // Case 1: string is empty or contains "none" (first letter only) ==> no children if (String.Compare(children,"n") == 0) includeChildren = WhichChildren.None; // Case 2: either an asset or an asset type are specified and the string isn't empty ==> include children (and they will be assets) else if (asset != null || assetType != null) // "asset" includeChildren = WhichChildren.Assets; // Case 3: neither asset nor type are specified and the string looks like "type" ==> return overall metrics and children are asset types else if ( string.Compare(children,"t") == 0) // "type" includeChildren = WhichChildren.Types; // Case 4: neither asset nor type are specified and the string looks like anything else ==> return overall metrics and children are assets else includeChildren = WhichChildren.Assets; GetCompoundAssetLevelStatsOutput output = new GetCompoundAssetLevelStatsOutput { }; output.StartTimestamp = _iowManager.NormalizeStartDay(input.StartTimestamp); output.EndTimestamp = _iowManager.NormalizeEndTimestamp(output.StartTimestamp, input.EndTimestamp); output.DurationHours = (output.EndTimestamp - output.StartTimestamp).TotalHours; output.AssetParentId = (assetParent != null) ? assetParent.Id : -1; output.AssetParentName = (assetParent != null) ? assetParent.Name : null; // Case A: Asset was specified with children if (asset != null && includeChildren != WhichChildren.None) { childAssetStats = _assetHealthManager.GetAssetLevelStatsForChildren(asset.Id, asset.Name, output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality); // Need to include the parent in this query (third argument=true) in case this asset does not have children assets = _assetManager.GetAssetChildren(asset.Id, asset.Name, true); } else if (asset != null && includeChildren == WhichChildren.None) { childAssetStats = _assetHealthManager.GetAssetLevelStatsForAsset(asset.Id, asset.Name, output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality); assets.Add(asset); } else if (assetType != null && includeChildren != WhichChildren.None) { childAssetStats = _assetHealthManager.GetAssetLevelStatsForAssetType(assetType.Id, assetType.Name, output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality); assets = _assetManager.GetAssetListForType(assetType.Id); } else if (assetType != null && includeChildren != WhichChildren.None) { //TODO: This isn't implemented childAssetStats = _assetHealthManager.GetAssetLevelStatsForAssetType(assetType.Id, assetType.Name, output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality); assets = _assetManager.GetAssetListForType(assetType.Id); } else if (includeChildren == WhichChildren.Types) //Both asset and assettype are null AND we want children AND the children are specified as asset types { childAssetStats = _assetHealthManager.GetAssetLevelStatsByAssetType(output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality); assets = _assetManager.GetAssetList(); } else // Basically, if nothing is specified, return top level assets { childAssetStats = _assetHealthManager.GetAssetLevelStatsForTopLevel(output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality); assets = _assetManager.GetAssetChildren(null, null, false); } // Save the number of assets and get overall statistics for all assets together output.NumberAssets = (assets != null) ? assets.Count : 0; output.OverallStats = new AssetLevelStats { AssetId = (asset != null) ? asset.Id : -1, AssetName = (asset != null) ? asset.Name : null, AssetDescription = (asset != null) ? asset.Description : null, AssetTypeId = (assetType != null) ? assetType.Id : (asset != null ? asset.AssetTypeId : 0), AssetTypeName = (assetType != null) ? assetType.Name : (asset != null ? asset.AssetType.Name : null), AssetMaterials = (asset != null) ? asset.Materials : null, NumberChildren = childAssetStats.Count, Levels = _assetHealthManager.GetLevelStatsForAssets(assets, output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality) }; // Get the unique list of levels. The overall statistics will include all levels that are used in the overall list, which includes all levels used in any of the children. if (output.OverallStats.Levels != null && output.OverallStats.Levels.Count > 0) output.Levels = output.OverallStats.Levels.Select(p => new LevelInfo { Criticality = p.Criticality, LevelName = p.LevelName }).Distinct().OrderBy(p => p.Criticality).ThenBy(p => p.LevelName).ToList(); else output.Levels = null; // Get the list of problematic limits for the specified asset (or the top level, if an asset isn't specified List<IOWLimit> limits = _assetHealthManager.GetProblematicLimitsForAsset(output.OverallStats.AssetId, output.OverallStats.AssetName, output.StartTimestamp, output.EndTimestamp, minCriticality, maxCriticality); if( limits != null && limits.Count > 0 ) { output.ProblemLimits = new List<VariableLimitStatusDto>(); foreach(IOWLimit limit in limits) { string severityMessage1 = ""; string severityMessage2 = ""; string severityClass = ""; if (limit.LastStatus == IOWStatus.OpenDeviation) { severityMessage1 = limit.Level.Name; severityMessage2 = localize.GetString("IowMsgActive"); if (limit.Level.Criticality == 1) severityClass = "label label-danger"; else if (limit.Level.Criticality == 2) severityClass = "label label-warning"; else if (limit.Level.Criticality == 3) severityClass = "label label-default"; } else if (limit.LastDeviationEndTimestamp.HasValue && (DateTime.Now - limit.LastDeviationEndTimestamp.Value).TotalHours <= 24) { severityMessage1 = limit.Level.Name; severityMessage2 = localize.GetString("IowMsgLast24Hours"); if (limit.Level.Criticality == 1) severityClass = "label label-danger"; else if (limit.Level.Criticality == 2) severityClass = "label label-warning"; } else if (limit.LastDeviationEndTimestamp.HasValue) { double days = Math.Round((DateTime.Now - limit.LastDeviationEndTimestamp.Value).TotalDays, 0); severityMessage1 = ""; severityMessage2 = String.Format(localize.GetString("IowMsgNotRecent"), days); severityClass = ""; } output.ProblemLimits.Add(new VariableLimitStatusDto { VariableId = limit.IOWVariableId, VariableName = limit.Variable.Name, VariableDescription = limit.Variable.Description, TagId = limit.Variable.TagId, TagName = limit.Variable.Tag.Name, UOM = limit.Variable.UOM, LastTimestamp = limit.Variable.Tag.LastTimestamp, LastValue = limit.Variable.Tag.LastValue, LastQuality = limit.Variable.Tag.LastQuality, IOWLevelId = limit.IOWLevelId, LevelName = limit.Level.Name, LevelDescription = limit.Level.Description, Criticality = limit.Level.Criticality, ResponseGoal = limit.Level.ResponseGoal, MetricGoal = limit.Level.MetricGoal, LimitName = string.Format("{0}-", limit.Level.Criticality) + limit.Level.Name + "-" + localizedDirectionNames[Convert.ToInt32(limit.Direction)], Direction = limit.Direction, LimitValue = limit.Value, Cause = limit.Cause, Consequences = limit.Consequences, Action = limit.Action, LastStatus = limit.LastStatus, LastDeviationStartTimestamp = limit.LastDeviationStartTimestamp, LastDeviationEndTimestamp = limit.LastDeviationEndTimestamp, SeverityMessage1 = severityMessage1, SeverityMessage2 = severityMessage2, SeverityClass = severityClass }); } } // Transform the asset stats we have (which includes only levels in use for that asset) to a form that includes all levels output.ChildStats = new List<AssetLevelStats>(); foreach(AssetLevelStats a in childAssetStats) { AssetLevelStats assetStat = new AssetLevelStats { AssetId = a.AssetId, AssetName = a.AssetName, AssetDescription = a.AssetDescription, AssetTypeId = a.AssetTypeId, AssetTypeName = a.AssetTypeName, AssetMaterials = a.AssetMaterials, NumberChildren = a.NumberChildren, Levels = new List<LevelStats>() }; // j = index into the complete list of levels (output.AllLevels) // i = index into the list of levels for this asset (inStats.Levels) int j = 0; for(int i=0; a.Levels != null && i< a.Levels.Count; i++ ) { // Add dummy records until we find a match. for(; output.Levels != null && j < output.Levels.Count && CompareLevels(output.Levels[j].Criticality, output.Levels[j].LevelName, a.Levels[i].Criticality, a.Levels[i].LevelName) < 0; j++) assetStat.Levels.Add(new LevelStats { LevelName = output.Levels[j].LevelName, Criticality = output.Levels[j].Criticality }); // Add the record from the list of levels for this asset assetStat.Levels.Add(new LevelStats { LevelName = a.Levels[i].LevelName, Criticality = a.Levels[i].Criticality, MetricType = a.Levels[i].MetricType, GoodDirection = a.Levels[i].GoodDirection, WarningLevel = a.Levels[i].WarningLevel, ErrorLevel = a.Levels[i].ErrorLevel, NumberDeviations = a.Levels[i].NumberDeviations, DurationHours = a.Levels[i].DurationHours, NumberLimits = a.Levels[i].NumberLimits, NumberDeviatingLimits = a.Levels[i].NumberDeviatingLimits, MetricValue = a.Levels[i].MetricValue }); j++; } // We're at the end of the list of levels for this asset. Add anything remaining from the master list of levels. for (; output.Levels != null && j < output.Levels.Count; j++) assetStat.Levels.Add(new LevelStats { LevelName = output.Levels[j].LevelName, Criticality = output.Levels[j].Criticality }); output.ChildStats.Add(assetStat); } return output; }
public GetAssetLevelStatsforTypeOutput GetAssetLevelStatsForType(GetAssetLevelStatsForTypeInput input) { GetAssetLevelStatsforTypeOutput output = new GetAssetLevelStatsforTypeOutput { }; output.StartTimestamp = _iowManager.NormalizeStartDay(input.StartTimestamp); output.EndTimestamp = _iowManager.NormalizeEndTimestamp(output.StartTimestamp, input.EndTimestamp); output.DurationHours = (output.EndTimestamp - output.StartTimestamp).TotalHours; AssetType assetType = _assetManager.GetAssetType(input.AssetTypeId, input.AssetTypeName); // If a valid asset was specified in the input, return stats for that asset. // Otherwise, if a valid asset type was specified, return details for all assets of that type. // Otherwise, return details for all top level assets that do not have a parent. if (assetType != null) { output.AssetTypeId = assetType.Id; output.AssetTypeName = assetType.Name; List<AssetLevelStats> stats =_assetHealthManager.GetAssetLevelStatsForAssetType(assetType.Id, assetType.Name, output.StartTimestamp, output.EndTimestamp, null, null); if( stats != null && stats.Count > 0 ) { // Get all unique levels in the output var query = from a in stats // Next two lines handle the case that the child list ("Levels") is null let subList = a.Levels ?? new List<LevelStats>() from b in subList.DefaultIfEmpty(new LevelStats { LevelName="",Criticality=-1, MetricType=MetricType.None, GoodDirection=Direction.None, WarningLevel=0, ErrorLevel=0, MetricValue=0 }) where b.Criticality > 0 group b.MetricValue by new { b.LevelName, b.Criticality, b.MetricType, b.GoodDirection, b.WarningLevel, b.ErrorLevel } into g select new { LevelName = g.Key.LevelName, Criticality = g.Key.Criticality, MetricType = g.Key.MetricType, GoodDirection = g.Key.GoodDirection, WarningLevel = g.Key.WarningLevel, ErrorLevel = g.Key.ErrorLevel }; var allLevels = query.Distinct().OrderBy(t => t.Criticality).ThenBy(t => t.LevelName).ToList(); if( allLevels != null && allLevels.Count > 0 ) { // Transform the asset stats we have (which includes only levels in use for that asset) to a form that includes all levels output.AssetStats = new List<AssetLevelStats>(); foreach (AssetLevelStats a in stats) { AssetLevelStats assetStat = new AssetLevelStats { AssetId = a.AssetId, AssetName = a.AssetName, AssetDescription = a.AssetDescription, AssetTypeId = a.AssetTypeId, AssetTypeName = a.AssetTypeName, AssetMaterials = a.AssetMaterials, NumberChildren = a.NumberChildren, Levels = new List<LevelStats>() }; // j = index into the complete list of levels (allLevels) // i = index into the list of levels for this asset (a.Levels) int j = 0; for (int i = 0; a.Levels != null && i < a.Levels.Count; i++) { // Add dummy records until we find a match. for (; allLevels != null && j < allLevels.Count && CompareLevels(allLevels[j].Criticality, allLevels[j].LevelName, a.Levels[i].Criticality, a.Levels[i].LevelName) < 0; j++) assetStat.Levels.Add(new LevelStats { LevelName = allLevels[j].LevelName, Criticality = allLevels[j].Criticality, MetricType = allLevels[j].MetricType, GoodDirection = allLevels[j].GoodDirection, WarningLevel = allLevels[j].WarningLevel, ErrorLevel = allLevels[j].ErrorLevel }); // Add the record from the list of levels for this asset assetStat.Levels.Add(new LevelStats { LevelName = a.Levels[i].LevelName, Criticality = a.Levels[i].Criticality, MetricType = a.Levels[i].MetricType, GoodDirection = a.Levels[i].GoodDirection, WarningLevel = a.Levels[i].WarningLevel, ErrorLevel = a.Levels[i].ErrorLevel, NumberDeviations = a.Levels[i].NumberDeviations, DurationHours = a.Levels[i].DurationHours, NumberLimits = a.Levels[i].NumberLimits, NumberDeviatingLimits = a.Levels[i].NumberDeviatingLimits, MetricValue = a.Levels[i].MetricValue }); j++; } // We're at the end of the list of levels for this asset. Add anything remaining from the master list of levels. for (; allLevels != null && j < allLevels.Count; j++) assetStat.Levels.Add(new LevelStats { LevelName = allLevels[j].LevelName, Criticality = allLevels[j].Criticality, MetricType = allLevels[j].MetricType, GoodDirection = allLevels[j].GoodDirection, WarningLevel = allLevels[j].WarningLevel, ErrorLevel = allLevels[j].ErrorLevel }); output.AssetStats.Add(assetStat); } } } } return output; }