using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Data.Entity; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.DTO; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.Core; using Tango.Core.DI; using Tango.Integration.ExternalBridge; using Tango.Integration.JobRuns; using Tango.PPC.Common.Connection; using Tango.PPC.Common.ExternalBridge; using Tango.PPC.Shared.Statistics; namespace Tango.PPC.Common.Statistics { [TangoCreateWhenRegistered] public class DefaultStatisticsService : ExtendedObject, IStatisticsService, IExternalBridgeRequestHandler { private IMachineProvider _machineProvider; private Dictionary _streamingReceivers; private List _catalogs; private List _color_catalog_Items; private List _colorSpaces; private Dictionary _liquidTypes; public bool Enabled { get; set; } = true; public DefaultStatisticsService(IPPCExternalBridgeService externalBridge, IMachineProvider machineProvider) { _streamingReceivers = new Dictionary(); try { _machineProvider = machineProvider; externalBridge.RegisterRequestHandler(this); } catch (Exception ex) { LogManager.Log(ex, "Error initializing the statistics service."); Enabled = false; } _machineProvider.MachineOperator.JobRunsLogger.JobRunAvailable += JobRunsLogger_JobRunAvailable; } private void JobRunsLogger_JobRunAvailable(object sender, JobRunAvailableEventArgs e) { Task.Factory.StartNew(async () => { var jobRunComposition = await CreateJobRunComposition(e.JobRun); foreach (var receiver in _streamingReceivers.ToList()) { try { var response = new StartJobRunsStreamingResponse(); response.JobRunComposition = jobRunComposition; await receiver.Key.SendGenericResponse(response, receiver.Value); } catch (Exception ex) { Debug.WriteLine(ex); } } }); } [ExternalBridgeRequestHandlerMethod(typeof(GetStatisticsRequiredFiltersRequest), RequestHandlerLoggingMode.LogRequestName)] public async Task OnGetStatisticsRequiredFiltersRequest(GetStatisticsRequiredFiltersRequest request, String token, ExternalBridgeReceiver receiver) { this.ThrowIfDisabled(); var response = new GetStatisticsRequiredFiltersResponse(); using (ObservablesContext db = ObservablesContext.CreateDefault()) { var jobNames = (await db.JobRuns.Select(x => x.JobName).ToListAsync()).Distinct().ToList(); var threadNames = await db.Rmls.Select(x => new { x.Guid, x.Name, x.DisplayName }).ToListAsync(); if (_machineProvider.Machine.SiteGuid != null) { var siteRmlsGuids = (await db.SitesRmls.Where(x => x.SiteGuid == _machineProvider.Machine.SiteGuid).ToListAsync()).Select(x => x.RmlGuid).Where(x => x != null).Distinct().ToList(); threadNames.RemoveAll(x => !siteRmlsGuids.Contains(x.Guid)); } response.FiltersData.Jobs = jobNames; response.FiltersData.Rmls = threadNames.Select(x => new ThreadFilterData() { Guid = x.Guid, Name = x.DisplayName.IsNotNullOrEmpty() ? x.DisplayName : x.Name }).ToList(); } await receiver.SendGenericResponse(response, token); } [ExternalBridgeRequestHandlerMethod(typeof(GetStatisticsRequest), RequestHandlerLoggingMode.LogRequestName)] public async Task OnGetStatisticsRequest(GetStatisticsRequest request, String token, ExternalBridgeReceiver receiver) { this.ThrowIfDisabled(); var response = new GetStatisticsResponse(); using (ObservablesContext db = ObservablesContext.CreateDefault()) { response.Result.LiquidTypes = db.LiquidTypes.ToList().Select(x => LiquidTypeDTO.FromObservable(x)).ToList(); var filters = request.Filters; var db_JobRuns = db.JobRuns.Where(x => (x.StartDate <= filters.EndDateUTC && x.StartDate >= filters.StartDateUTC)); int[] jobRunStatusArr = filters.EndStatuses.Distinct().ToArray(); if (jobRunStatusArr.Length > 0) { db_JobRuns = db_JobRuns.Where(x => jobRunStatusArr.Contains(x.Status)); } int[] jobDesignationArr = filters.JobDesignation.Distinct().ToArray(); if (jobDesignationArr.Length > 0) { db_JobRuns = db_JobRuns.Where(x => jobDesignationArr.Contains(x.JobDesignation)); } if (!filters.IncludeHeadCleaning) { db_JobRuns = db_JobRuns.Where(x => !x.IsHeadCleaning); } List rmlGuids = filters.RmlGuids; if (filters.RmlGuids.Count > 0) { db_JobRuns = db_JobRuns.Where(x => rmlGuids.Contains(x.RmlGuid)); } if (filters.JobName.IsNotNullOrEmpty()) { if (!filters.ExactJobName) { db_JobRuns = db_JobRuns.Where(x => x.JobName.ToLower().StartsWith(filters.JobName.ToLower())); } else { db_JobRuns = db_JobRuns.Where(x => x.JobName.ToLower() == filters.JobName.ToLower()); } } db_JobRuns = db_JobRuns.Where(x => x.JobLength >= filters.MinLength && x.JobLength <= filters.MaxLength); var jobRuns = await db_JobRuns.ToListAsync(); foreach (var jobRun in jobRuns) { JobRunComposition jobRunComposition = await CreateJobRunComposition(jobRun); response.Result.JobRuns.Add(jobRunComposition); } } await receiver.SendGenericResponse(response, token); } private async Task CreateJobRunComposition(JobRun jobRun) { if (_colorSpaces == null) { using (ObservablesContext db = ObservablesContext.CreateDefault()) { _colorSpaces = await db.ColorSpaces.ToListAsync(); _catalogs = await db.ColorCatalogs.ToListAsync(); _color_catalog_Items = await db.ColorCatalogsItems.ToListAsync(); } } if (_liquidTypes == null) { using (ObservablesContext db = ObservablesContext.CreateDefault()) { var types = await db.LiquidTypes.ToListAsync(); _liquidTypes = new Dictionary(); foreach (var t in types) { _liquidTypes.Add(t.Name, t); } } } JobRunComposition jobRunComposition = new JobRunComposition(); jobRunComposition.JobRun = JobRunDTO.FromObservable(jobRun); PresentationJob pj = new PresentationJob(); pj.ID = jobRun.ID; jobRunComposition.Job = pj; if (jobRun.JobFile != null) { foreach (var segment in jobRun.JobFile.Segments) { PresentationSegment ps = new PresentationSegment(); ps.Length = (int)segment.Length; pj.Segments.Add(ps); foreach (var stop in segment.BrushStops.OrderBy(x => x.StopIndex).DistinctBy(x => x.OffsetPercent).ToList()) { PresentationBrushStop pbs = new PresentationBrushStop(); pbs.ColorSpace = _colorSpaces.First(x => x.Guid == stop.ColorSpaceGuid).Space; pbs.StartMeters = segment.Length * (stop.OffsetPercent / 100d); ; foreach (var liquidType in stop.LiquidVolumes) { PresentationLiquidVolume plt = new PresentationLiquidVolume(); if (_liquidTypes.ContainsKey(liquidType.LiquidTypeName)) { plt.LiquidType = _liquidTypes[liquidType.LiquidTypeName]; plt.Volume = liquidType.Volume; pbs.LiquidVolumes.Add(plt); } } pbs.LiquidVolumes = pbs.LiquidVolumes.OrderBy(x => x.LiquidType.PreferredIndex).ToList(); switch (pbs.ColorSpace) { case ColorSpaces.RGB: pbs.Red = stop.Red; pbs.Green = stop.Green; pbs.Blue = stop.Blue; break; case ColorSpaces.LAB: pbs.L = stop.L; pbs.A = stop.A; pbs.B = stop.B; break; case ColorSpaces.Volume: //foreach (var lightInk in pbs.LiquidVolumes.Where(x => x.LiquidType.IsLightInk && x.Volume > 0)) //{ // var darkInk = pbs.LiquidVolumes.FirstOrDefault(x => x.LiquidType.Code == lightInk.LiquidType.DarkInkCode); // if (darkInk != null) // { // darkInk.Volume = (double)((decimal)lightInk.Volume / 10m); // lightInk.Volume = 0; // } //} break; case ColorSpaces.Catalog: pbs.Catalog = _catalogs.FirstOrDefault(x => x.Guid == stop.ColorCatalogGuid)?.Name; pbs.CatalogItem = _color_catalog_Items.FirstOrDefault(x => x.Guid == stop.ColorCatalogItemGuid)?.Name; break; } pbs.BestMatchR = stop.BestMatchR; pbs.BestMatchG = stop.BestMatchG; pbs.BestMatchB = stop.BestMatchB; ps.Stops.Add(pbs); } } } jobRunComposition.JobRun.JobString = null; jobRunComposition.JobRun.LiquidQuantityString = null; return jobRunComposition; } [ExternalBridgeRequestHandlerMethod(typeof(GetJobRunExtendedInfoRequest), RequestHandlerLoggingMode.LogRequestName)] public async Task OnGetJobRunExtendedInfoRequest(GetJobRunExtendedInfoRequest request, String token, ExternalBridgeReceiver receiver) { this.ThrowIfDisabled(); var response = new GetJobRunExtendedInfoResponse(); String filePath = Path.Combine((_machineProvider.MachineOperator.JobRunsLogger as BasicJobRunsLogger).JobRunsFolder, $"{request.JobRunID}.run"); String json = File.ReadAllText(filePath); JobRunInfo info = JsonConvert.DeserializeObject(json); response.ExtendedInfo.JobRunID = info.JobRunID; response.ExtendedInfo.JobTicket = info.JobTicket; response.ExtendedInfo.Events = info.Events; response.ExtendedInfo.StartMachineStatus = info.StartMachineStatus; response.ExtendedInfo.EndMachineStatus = info.EndMachineStatus; await receiver.SendGenericResponse(response, token); } [ExternalBridgeRequestHandlerMethod(typeof(StartJobRunsStreamingRequest), RequestHandlerLoggingMode.LogRequestName)] public async Task OnStartJobRunsStreamingRequest(StartJobRunsStreamingRequest request, String token, ExternalBridgeReceiver receiver) { this.ThrowIfDisabled(); if (!_streamingReceivers.ContainsKey(receiver)) { _streamingReceivers.Add(receiver, token); } var response = new StartJobRunsStreamingResponse(); await receiver.SendGenericResponse(response, token); } [ExternalBridgeRequestHandlerMethod(typeof(StopJobRunsStreamingRequest), RequestHandlerLoggingMode.LogRequestName)] public async Task OnStopJobRunsStreamingRequest(StopJobRunsStreamingRequest request, String token, ExternalBridgeReceiver receiver) { this.ThrowIfDisabled(); if (_streamingReceivers.ContainsKey(receiver)) { _streamingReceivers.Remove(receiver); } var response = new StopJobRunsStreamingResponse(); await receiver.SendGenericResponse(response, token); } public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) { if (_streamingReceivers.ContainsKey(receiver)) { _streamingReceivers.Remove(receiver); } } } }