Files
adas-core/adas-core.Application/Services/ObservationDemoService.cs

271 lines
10 KiB
C#

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<IAlarmService> alarmService)
: IObservationDemoService
{
public async Task<List<PatientObservationAlarm>> GenerateAlarmByField(Patient patient, List<Field> dataAlarmfields)
{
var listToReturn = new List<PatientObservationAlarm>();
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<List<PatientObservation>> GenerateObservationByField(Patient patient, List<Field> dataFields)
{
var listToReturn = new List<PatientObservation>();
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<GroupedObservation> 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<object>();
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<object> { 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<object>().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);
}
}