using MxGateway.Server.Galaxy; namespace MxGateway.Server.Dashboard; /// /// Projects a into a /// for the Blazor pages. Top-templates and /// per-category breakdowns are computed here rather than stored on the cache so the /// Galaxy namespace stays free of dashboard-presentation concepts. /// internal static class DashboardGalaxyProjector { private const int TopTemplatesLimit = 10; private static readonly IReadOnlyDictionary CategoryNamesById = new Dictionary { [1] = "WinPlatform", [3] = "AppEngine", [4] = "InTouchViewApp", [10] = "UserDefined", [11] = "FieldReference", [13] = "Area", [17] = "DIObject", [24] = "DDESuiteLinkClient", [26] = "OPCClient", }; public static DashboardGalaxySummary Project(GalaxyHierarchyCacheEntry entry) { DashboardGalaxyStatus status = entry.Status switch { GalaxyCacheStatus.Healthy => DashboardGalaxyStatus.Healthy, GalaxyCacheStatus.Stale => DashboardGalaxyStatus.Stale, GalaxyCacheStatus.Unavailable => DashboardGalaxyStatus.Unavailable, _ => DashboardGalaxyStatus.Unknown, }; IReadOnlyList topTemplates; IReadOnlyList objectCategories; if (entry.Hierarchy.Count == 0) { topTemplates = Array.Empty(); objectCategories = Array.Empty(); } else { Dictionary objectsByCategory = new(); Dictionary templateUsage = new(StringComparer.OrdinalIgnoreCase); foreach (GalaxyHierarchyRow row in entry.Hierarchy) { objectsByCategory.TryGetValue(row.CategoryId, out int categoryCount); objectsByCategory[row.CategoryId] = categoryCount + 1; if (row.TemplateChain.Count > 0) { string immediate = row.TemplateChain[0]; if (!string.IsNullOrWhiteSpace(immediate)) { templateUsage.TryGetValue(immediate, out int templateCount); templateUsage[immediate] = templateCount + 1; } } } topTemplates = templateUsage .OrderByDescending(entry => entry.Value) .ThenBy(entry => entry.Key, StringComparer.OrdinalIgnoreCase) .Take(TopTemplatesLimit) .Select(entry => new DashboardGalaxyTemplateUsage(entry.Key, entry.Value)) .ToArray(); objectCategories = objectsByCategory .OrderByDescending(entry => entry.Value) .ThenBy(entry => entry.Key) .Select(entry => new DashboardGalaxyCategoryCount( entry.Key, CategoryNamesById.TryGetValue(entry.Key, out string? name) ? name : $"Category {entry.Key}", entry.Value)) .ToArray(); } return new DashboardGalaxySummary( Status: status, LastQueriedAt: entry.LastQueriedAt, LastSuccessAt: entry.LastSuccessAt, LastDeployTime: entry.LastDeployTime, LastError: entry.LastError, ObjectCount: entry.ObjectCount, AreaCount: entry.AreaCount, AttributeCount: entry.AttributeCount, HistorizedAttributeCount: entry.HistorizedAttributeCount, AlarmAttributeCount: entry.AlarmAttributeCount, TopTemplates: topTemplates, ObjectCategories: objectCategories); } }