190 lines
8.7 KiB
C#
190 lines
8.7 KiB
C#
using adas_core.Domain.Models;
|
|
using adas_core.Domain.Models.MongoModels;
|
|
using adas_core.Domain.Models.Providers;
|
|
using Microsoft.Extensions.Options;
|
|
using Newtonsoft.Json;
|
|
using Serilog;
|
|
|
|
namespace adas_core.Application.Providers;
|
|
|
|
/// <summary>
|
|
/// Represents an ADAS (Advanced Driver Assistance Systems) data provider that retrieves driver assistance observations through the shared infrastructure defined by <see cref="BaseProvider"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The constructor forwards the supplied <paramref name="providerSettings"/> of type <see cref="IOptions{ProvidersSettings}"/> and the <paramref name="httpClientFactory"/> of type <see cref="IHttpClientFactory"/> to <see cref="BaseProvider"/>, ensuring consistent configuration and HTTP client management across all providers.
|
|
/// </remarks>
|
|
/// <!-- aidoc:v1 sig=42c9a02 -->
|
|
public class AdasProvider(IOptions<ProvidersSettings> providerSettings, IHttpClientFactory httpClientFactory)
|
|
: BaseProvider(providerSettings, httpClientFactory)
|
|
{
|
|
/*
|
|
* Get observations of:
|
|
* Predict of UCI stay duration
|
|
* Predict of medications for patients
|
|
*/
|
|
/// <summary>
|
|
/// Retrieves patient observations from the ADAS system, including stay duration predictions (most and less confident scenarios) and medication predictions.
|
|
/// Logs an error and skips stay prediction observations if the prediction result is null or contains an error.
|
|
/// Skips the medication prediction observation if no medication predictions are returned.
|
|
/// </summary>
|
|
/// <param name="patient">The patient for whom observations are being calculated.</param>
|
|
/// <returns>A task that represents the asynchronous operation, returning a list of patient observations.</returns>
|
|
/// <!-- aidoc:v1 sig=ab999e4 body=ac14195 -->
|
|
public override async Task<List<PatientObservation>> GetObservations(Patient patient)
|
|
{
|
|
var calculatedObservations = new List<PatientObservation>();
|
|
|
|
//get data from two endpoints one from UCI stay another for medication
|
|
var predictOfStay = await GetPredictOfStay(patient.PatientNumber);
|
|
|
|
if (predictOfStay == null || predictOfStay.Result.ToLower().Contains("error"))
|
|
Log.Error("Error retrieving predict of stay in ADAS result, message: {predictOfStay}", predictOfStay);
|
|
else
|
|
{
|
|
var durationPredicted1 = predictOfStay.Payload.MaxBy(i => i.PercentageMin)!.Duration;
|
|
var durationPredicted2 = predictOfStay.Payload.MinBy(i => i.PercentageMin)!.Duration;
|
|
|
|
calculatedObservations.Add(
|
|
new PatientObservation
|
|
{
|
|
PatientId = patient.Id,
|
|
CodingSystem = "ADAS",
|
|
Name = "Stay_Predict_Days_Most_Confident",
|
|
//get the most confident interval to show the most probable scenario
|
|
Value = durationPredicted1,
|
|
Time = DateTime.UtcNow
|
|
});
|
|
|
|
calculatedObservations.Add(new PatientObservation
|
|
{
|
|
PatientId = patient.Id,
|
|
CodingSystem = "ADAS",
|
|
Name = "Stay_Predict_Days_Less_Confident",
|
|
//get the less confident interval to show the less probable scenario
|
|
Value = durationPredicted2,
|
|
Time = DateTime.UtcNow
|
|
});
|
|
}
|
|
|
|
|
|
var predictMedication = await GetPredictMedications(patient.PatientNumber);
|
|
|
|
|
|
if (predictMedication != null && predictMedication.Any())
|
|
calculatedObservations.Add(new PatientObservation
|
|
{
|
|
PatientId = patient.Id,
|
|
CodingSystem = "ADAS",
|
|
Name = "Medication_Predict",
|
|
Value = ParseAdasMedicationsToMedicationObservation(predictMedication),
|
|
Time = DateTime.UtcNow
|
|
});
|
|
|
|
|
|
return calculatedObservations;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Concatenates up to the first five ADAS medication prediction results into a single caret-delimited string for use as a medication observation value.
|
|
/// </summary>
|
|
/// <param name="medicationPredict">The list of ADAS medication prediction results to be serialized. Only the first five entries are included.</param>
|
|
/// <returns>A string containing the selected medication prediction entries joined by the "^" delimiter.</returns>
|
|
/// <!-- aidoc:v1 sig=4474eb5 body=ea7295b -->
|
|
private static string ParseAdasMedicationsToMedicationObservation(
|
|
List<ResultModelPredictMedicationAdas> medicationPredict)
|
|
{
|
|
return string.Join("^", medicationPredict.Take(5));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the ADAS prediction of length of stay for the specified patient from an external service.
|
|
/// Returns null if the patient number is null, if the service response is unsuccessful, or if an exception occurs during the request.
|
|
/// </summary>
|
|
/// <param name="patientNumber">The unique identifier of the patient whose ADAS stay prediction is being requested.</param>
|
|
/// <returns>A task containing the deserialized <see cref="ResultModelPredictOfStayAdas"/> result on success, or null if the patient number is null, the response is unsuccessful, or the call throws.</returns>
|
|
/// <!-- aidoc:v1 sig=7c8fb5e body=5aa481c -->
|
|
private async Task<ResultModelPredictOfStayAdas?> GetPredictOfStay(string? patientNumber)
|
|
{
|
|
if (patientNumber == null)
|
|
{
|
|
Log.Error("Error retrieving ADAS predict of stay patient number is null");
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
var client = GetClient();
|
|
var response = await client.GetAsync($"predictStay?patientNumber={patientNumber}");
|
|
|
|
if (response.IsSuccessStatusCode)
|
|
{
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
return JsonConvert.DeserializeObject<ResultModelPredictOfStayAdas>(content);
|
|
}
|
|
|
|
Log.Error(
|
|
"Error retrieving calculated ADAS observation length of stay for patient: {patientNumber}, status code: {response.StatusCode} ",
|
|
patientNumber, response.StatusCode);
|
|
return null;
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
{
|
|
Log.Error("Exception retrieving ADAS predict of stay for patient: {patientNumber} exception: {e}",
|
|
patientNumber, e.Message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the predicted medication needs for a given patient by calling the pharmacy prediction service.
|
|
/// Returns null if the patient number is null, the service response is unsuccessful, or an exception occurs during the request.
|
|
/// </summary>
|
|
/// <param name="patientNumber">The unique identifier of the patient whose ADAS medication predictions are being retrieved.</param>
|
|
/// <returns>A task containing a list of <see cref="ResultModelPredictMedicationAdas"/> with the predicted medication data, or null if the request fails or the patient number is null.</returns>
|
|
/// <!-- aidoc:v1 sig=1381cb8 body=f17df11 -->
|
|
private async Task<List<ResultModelPredictMedicationAdas>?> GetPredictMedications(string? patientNumber)
|
|
{
|
|
if (patientNumber == null)
|
|
{
|
|
Log.Error("Error retrieving ADAS predict of stay for patient number is null");
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
var client = GetClient();
|
|
|
|
var response = await client.GetAsync($"predictMedicationNeedsPharmacy?patientNumber={patientNumber}");
|
|
if (response.IsSuccessStatusCode)
|
|
{
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
return JsonConvert.DeserializeObject<List<ResultModelPredictMedicationAdas>>(content);
|
|
}
|
|
|
|
Log.Error(
|
|
"Error retrieving calculated ADAS medicines for patient: {patientNumber}, status code: {response.StatusCode}",
|
|
patientNumber, response.StatusCode);
|
|
return null;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error("Exception retrieving ADAS predict medicines for patient: {patientNumber} exception: {e}",
|
|
patientNumber, e.Message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new <see cref="HttpClient"/> instance and configures it with the configured base address URL.
|
|
/// </summary>
|
|
/// <returns>An <see cref="HttpClient"/> with its <see cref="HttpClient.BaseAddress"/> set to the configured <c>Url</c>.</returns>
|
|
/// <!-- aidoc:v1 sig=12d10b8 body=3c7c671 -->
|
|
private HttpClient GetClient()
|
|
{
|
|
var client = HttpClientFactory.CreateClient();
|
|
client.BaseAddress = new Uri(Url);
|
|
return client;
|
|
}
|
|
} |