271 lines
10 KiB
C#
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);
|
|
}
|
|
} |