using System.Collections; using adas_core.Application.Services.Interfaces; using adas_core.Domain.Enums; using adas_core.Domain.Models; using adas_core.Domain.Models.GroupedObservations; using adas_core.Domain.Models.MongoModels; using adas_core.Domain.Utils; namespace adas_core.Application.Services; public class ObservationDemoService( IConfigObservationService configObservationService, Lazy alarmService) : IObservationDemoService { public async Task> GenerateAlarmByField(Patient patient, List dataAlarmfields) { var listToReturn = new List(); foreach (var field in dataAlarmfields) { var sendingRandom = new Random(); if (sendingRandom.Next(0, 2) == 0 || string.IsNullOrEmpty(field.Name)) continue; var firstCof = await configObservationService.GetConfigObservationItemsByName(field.Name); var conf = firstCof.FirstOrDefault(); if (conf == null) continue; var alarmObs = new PatientObservationAlarm { Patient = patient, PatientId = patient.Id, AlarmConfig = conf.Alarm, InactivationState = new InactivationState { Audio = AlarmEnum.AudioVideoState.Enabled, Acknowledge = true, Visual = AlarmEnum.AudioVideoState.Enabled }, EventPhase = AlarmEnum.EventPhase.Continue, Type = AlarmEnum.ObservationAlarmType.Sp, Expires = conf.Expires, State = AlarmEnum.ObservationAlarmState.Active, Time = DateTime.UtcNow, Persist = false, MessageTime = DateTime.UtcNow, Code = conf.Code, PriorityLevel = conf.DemoConfig?.PriorityAlarm, Name = conf.Name, ParentData = new ParentDataClass { Code = conf.ParentCode, Name = conf.ParentName, CodingSystem = conf.CodingSystem }, Units = conf.Units, Value = GenerateValueRandom(conf, null) ?? 0 }; var obs = await alarmService.Value.MapObservationsByName(alarmObs); if (obs != null) listToReturn.Add(obs); } return listToReturn; } public async Task> GenerateObservationByField(Patient patient, List dataFields) { var listToReturn = new List(); var rnd = new Random(); foreach (var field in dataFields) { if (string.IsNullOrEmpty(field.Name)) continue; var conf = await configObservationService.GetConfigObservationItemsByName(field.Name); var firstCof = conf.FirstOrDefault(); if (firstCof == null) continue; var patientObs = new PatientObservation { Patient = patient, PatientId = patient.Id, Max = firstCof.MaxAlert, Min = firstCof.MinAlert, MaxWarn = firstCof.MaxWarn, MinWarn = firstCof.MinWarn, ShowOnExpired = firstCof.ShowOnExpired, Expires = firstCof.Expires, UiConfiguration = firstCof.UiConfiguration, MessageTime = DateTime.UtcNow, Code = firstCof.Code, ColorOnExpired = firstCof.ColorOnExpired, AlertColor = firstCof.AlertColor, WarnColor = firstCof.WarnColor, CodingSystem = firstCof.CodingSystem, Alarm = firstCof.Alarm, InsertMode = firstCof.InsertMode, Name = field.Name, Time = DateTime.UtcNow, ParentData = new ParentDataClass { Code = firstCof.ParentCode, Name = firstCof.ParentName, CodingSystem = firstCof.CodingSystem }, Units = firstCof.Units, Value = GenerateValueRandom(firstCof, null) ?? 0 }; var result = await configObservationService.Map(patientObs, true); if (firstCof.DemoConfig?.RequireInitDate == true && result != null) { var rndRestNmbHours = rnd.Next(3, 23); var initDate = DateTime.UtcNow.AddHours(-rndRestNmbHours); // Si se requiere fecha de fin, devolvemos un objeto con ambas if (firstCof.DemoConfig?.RequireEndDate == true) { result.Time = initDate; result.EndTime = initDate.AddHours(1); } // Si no, solo devolvemos la fecha inicial result.Time = initDate; } if (result != null) listToReturn.Add(result); } return listToReturn; } public async Task GenerateGroupedObservation(Patient patient, GroupedField groupedField) { if (groupedField.Names.IsNullOrEmpty() && groupedField.Name != null) groupedField.Names.Add(groupedField.Name); var rnd = new Random(); var startTime = DateTime.UtcNow; var go = new GroupedObservation { Name = groupedField.Name, PatientId = patient.Id, Group = groupedField.Group, Observations = [] }; foreach (var groupedFieldName in groupedField.Names) { var conf = await configObservationService.GetConfigObservationItemsByName(groupedFieldName); var firstCof = conf.FirstOrDefault(); if (firstCof == null) continue; foreach (var result in groupedField.Result) { object? prevValue = null; for (var i = 0; i <= groupedField.Max; i++) { var time = startTime; time = groupedField.Regularity switch { GroupedObservationEnum.Regularity.Day => time.AddDays(-i), GroupedObservationEnum.Regularity.Minute => time.AddMinutes(-i), GroupedObservationEnum.Regularity.Second => time.AddSeconds(-i), _ => time.AddHours(-i) }; var val = new GroupedObservation.GroupedObservationObs { Name = groupedFieldName, MaxAlert = firstCof?.MaxAlert, MinAlert = firstCof?.MinAlert, Time = time, IsFilled = false }; var value = new GroupedObservation.GroupedObservationObsValue( GenerateValueRandom(firstCof, prevValue) ?? rnd.Next(0, 30), time); prevValue = value.Value; var propertyInfo = val.GetType().GetProperty(result.ToString()); if (propertyInfo != null && propertyInfo.CanWrite) propertyInfo.SetValue(val, value); var valueType = await configObservationService.GroupedObservationStatus( groupedField, result, groupedFieldName, val, firstCof?.MaxAlert, firstCof?.MinAlert ); value.Type = valueType; go.Observations.Add( val ); } if (firstCof?.DemoConfig?.RequireInitDate.HasValue == true && firstCof.DemoConfig.RequireInitDate.Value) break; } } return go; } private static object? GenerateValueRandom(ConfigObservation? firstCof, object? prevValue) { if (firstCof?.DemoConfig == null) return "-"; // 1. Determinar cuántos valores necesitamos var count = firstCof.DemoConfig?.ValueIsArray == true ? firstCof.DemoConfig?.RandomCount ?? 1 : 1; var results = new List(); for (var i = 0; i < count; i++) { var singleValue = PickSingleValue(firstCof.DemoConfig, prevValue); if (singleValue != null) results.Add(singleValue); } // 2. Si no es un array, devolvemos solo el primer elemento return firstCof.DemoConfig?.ValueIsArray == true ? results : results.FirstOrDefault(); } private static object? PickSingleValue(DemoConfig? config, object? prevValue) { if (config == null) return null; var rnd = new Random(); // Prioridad 1: Selección de una lista de opciones (SetInValue) if (config is { SetInValue: true, ValueOption: not null }) { if (config.ValueOption is List { Count: > 0 } options) { var index = rnd.Next(options.Count); return options.ElementAt(index); } // Caso especial si ValueOption llega como un JArray o lista genérica if (config.ValueOption is IEnumerable list) { var tempList = list.Cast().ToList(); return tempList[rnd.Next(tempList.Count)]; } } // Prioridad 2: Generación numérica por rango (SetRandomValue) if (config.SetRandomValue == false) return null; // 1. Extraemos los límites primero para usarlos en cualquier caso var minLimit = config.MinValue ?? 0; var maxLimit = config.MaxValue ?? 100; if (prevValue is not int values) // Caso base: Si no hay valor previo, generamos uno aleatorio dentro del rango permitido return rnd.Next(minLimit, maxLimit + 1); if (values == 0) values = 1; // 2. Calculamos la variación (entre 5% y 10%) var porcentaje = rnd.Next(5, 10) / 100.0; var direccion = rnd.Next(0, 2) == 0 ? -1 : 1; // 3. Calculamos el valor base redondeado var calculado = (int)Math.Round(values + values * porcentaje * direccion); // 4. Forzamos que esté dentro del rango [minLimit, maxLimit] return Math.Clamp(calculado, minLimit, maxLimit); } }