You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
807 lines
26 KiB
Dart
807 lines
26 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:diplomaticquarterapp/config/config.dart';
|
|
import 'package:diplomaticquarterapp/core/model/labs/LabOrderResult.dart';
|
|
import 'package:diplomaticquarterapp/core/model/labs/lab_result.dart';
|
|
import 'package:diplomaticquarterapp/core/model/labs/patient_lab_orders.dart';
|
|
import 'package:diplomaticquarterapp/core/model/labs/patient_lab_special_result.dart';
|
|
import 'package:diplomaticquarterapp/core/model/labs/request_patient_lab_special_result.dart';
|
|
import 'package:diplomaticquarterapp/core/model/labs/request_send_lab_report_email.dart';
|
|
import 'package:diplomaticquarterapp/core/service/base_service.dart';
|
|
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
|
|
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
|
|
import 'package:diplomaticquarterapp/widgets/data_display/medical/LabResult/lab_result_graph.dart';
|
|
|
|
class LabsService extends BaseService {
|
|
List<PatientLabOrders> patientLabOrdersList = [];
|
|
|
|
String labReportPDF = "";
|
|
|
|
Future getPatientLabOrdersList() async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
body['isDentalAllowedBackend'] = false;
|
|
await baseAppClient.post(GET_Patient_LAB_ORDERS,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
patientLabOrdersList.clear();
|
|
response['ListPLO'].forEach((hospital) {
|
|
patientLabOrdersList.add(PatientLabOrders.fromJson(hospital));
|
|
});
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
}
|
|
|
|
RequestPatientLabSpecialResult _requestPatientLabSpecialResult =
|
|
RequestPatientLabSpecialResult();
|
|
|
|
List<PatientLabSpecialResult> patientLabSpecialResult = [];
|
|
List<LabResult> labResultList = [];
|
|
List<LabOrderResult> labOrdersResultsList = [];
|
|
|
|
Future getLaboratoryResult(
|
|
{String? projectID,
|
|
int? clinicID,
|
|
String? invoiceNo,
|
|
String? invoiceType,
|
|
String? orderNo,
|
|
String? setupID,
|
|
bool? isVidaPlus}) async {
|
|
hasError = false;
|
|
_requestPatientLabSpecialResult.projectID = projectID;
|
|
_requestPatientLabSpecialResult.clinicID = clinicID;
|
|
|
|
_requestPatientLabSpecialResult.invoiceNo = isVidaPlus! ? "0" : invoiceNo;
|
|
_requestPatientLabSpecialResult.invoiceNoVP = isVidaPlus ? invoiceNo : "0";
|
|
|
|
_requestPatientLabSpecialResult.invoiceType = invoiceType ?? "";
|
|
|
|
_requestPatientLabSpecialResult.orderNo = orderNo;
|
|
_requestPatientLabSpecialResult.setupID = setupID;
|
|
|
|
await baseAppClient.post(GET_Patient_LAB_SPECIAL_RESULT,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
patientLabSpecialResult.clear();
|
|
response['ListPLSR'].forEach((hospital) {
|
|
patientLabSpecialResult.add(PatientLabSpecialResult.fromJson(hospital));
|
|
});
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: _requestPatientLabSpecialResult.toJson());
|
|
}
|
|
|
|
Future getPatientLabResult(
|
|
{PatientLabOrders? patientLabOrder, bool? isVidaPlus}) async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
body['InvoiceNo_VP'] = isVidaPlus! ? patientLabOrder!.invoiceNo : "0";
|
|
body['InvoiceNo'] = isVidaPlus ? "0" : patientLabOrder!.invoiceNo;
|
|
body['InvoiceType'] = patientLabOrder!.invoiceType;
|
|
body['OrderNo'] = patientLabOrder!.orderNo;
|
|
body['isDentalAllowedBackend'] = false;
|
|
body['SetupID'] = patientLabOrder.setupID;
|
|
body['ProjectID'] = patientLabOrder.projectID;
|
|
body['ClinicID'] = patientLabOrder.clinicID;
|
|
await baseAppClient.post(GET_Patient_LAB_RESULT,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
patientLabSpecialResult.clear();
|
|
labResultList.clear();
|
|
response['ListPLR'].forEach((lab) {
|
|
labResultList.add(
|
|
LabResult.fromJson(lab),
|
|
);
|
|
});
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
}
|
|
|
|
Future generateCovidLabReport(
|
|
LabResult covidLabResult, String isOutsideKSA) async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
|
|
body['To'] = user.emailAddress;
|
|
body['OrderNo'] = covidLabResult.orderNo;
|
|
body['OrderLineItemNo'] = covidLabResult.orderLineItemNo;
|
|
body['LineItemNo'] = covidLabResult.resultValueBasedLineItemNo;
|
|
body['CertificateFormat'] = 5;
|
|
body['GeneratedBy'] = 102;
|
|
body['ShowPassportNumber'] = isOutsideKSA;
|
|
body['isDentalAllowedBackend'] = false;
|
|
body['SetupID'] = covidLabResult.setupID;
|
|
body['ProjectID'] = covidLabResult.projectID;
|
|
|
|
dynamic localRes;
|
|
|
|
await baseAppClient.post(SEND_COVID_LAB_RESULT_EMAIL,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
localRes = response;
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
return Future.value(localRes);
|
|
}
|
|
|
|
Future updateCovidPassportNumber(String passportNumber) async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
|
|
body['PassportNo'] = passportNumber;
|
|
|
|
dynamic localRes;
|
|
|
|
await baseAppClient.post(COVID_PASSPORT_UPDATE,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
localRes = response;
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
return Future.value(localRes);
|
|
}
|
|
|
|
Future updateWorkplaceName(
|
|
String workplaceName,
|
|
String workplaceNameAR,
|
|
String occupation,
|
|
String occupationAR,
|
|
int requestNumber,
|
|
String setupID,
|
|
int projectID) async {
|
|
// Future updateWorkplaceName(String workplaceName, String workplaceNameAR, int requestNumber, String setupID, int projectID) async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
|
|
body['Placeofwork'] = workplaceName;
|
|
body['PlaceofworkAr'] = workplaceNameAR;
|
|
body['Occupation'] = occupation;
|
|
body['OccupationAr'] = occupationAR;
|
|
body['Req_ID'] = requestNumber;
|
|
body['TargetSetupID'] = setupID;
|
|
body['ProjectID'] = projectID;
|
|
body['UserID'] = 102;
|
|
body['RequestType'] = 1;
|
|
|
|
dynamic localRes;
|
|
|
|
await baseAppClient.post(UPDATE_WORKPLACE_NAME,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
localRes = response;
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
return Future.value(localRes);
|
|
}
|
|
|
|
Future getCovidPassportNumber() async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
|
|
dynamic localRes;
|
|
|
|
await baseAppClient.post(GET_PATIENT_PASSPORT_NUMBER,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
localRes = response;
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
return Future.value(localRes);
|
|
}
|
|
|
|
Future getSickLeaveStatusByAdmissionNo(int projectID, int admissionNo) async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
|
|
body['AdmissionNo'] = admissionNo;
|
|
body['ProjectID'] = projectID;
|
|
|
|
dynamic localRes;
|
|
|
|
await baseAppClient.post(GET_SICKLEAVE_STATUS_ADMISSION_NO,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
localRes = response;
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
return Future.value(localRes);
|
|
}
|
|
|
|
Future getPatientLabOrdersResults(
|
|
{PatientLabOrders? patientLabOrder,
|
|
String? procedure,
|
|
bool isVidaPlus = false}) async {
|
|
hasError = false;
|
|
Map<String, dynamic> body = Map();
|
|
body['InvoiceNo_VP'] = isVidaPlus ? patientLabOrder!.invoiceNo : "0";
|
|
body['InvoiceNo'] = isVidaPlus ? "0" : patientLabOrder!.invoiceNo;
|
|
body['OrderNo'] = patientLabOrder!.orderNo;
|
|
body['isDentalAllowedBackend'] = false;
|
|
body['SetupID'] = patientLabOrder!.setupID;
|
|
body['ProjectID'] = patientLabOrder.projectID;
|
|
body['ClinicID'] = patientLabOrder.clinicID;
|
|
body['Procedure'] = procedure;
|
|
body['Procedure'] = procedure;
|
|
body['LanguageID'] = 1;
|
|
await baseAppClient.post(GET_Patient_LAB_ORDERS_RESULT,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
labOrdersResultsList.clear();
|
|
response['ListPLR'].forEach((lab) {
|
|
labOrdersResultsList.add(LabOrderResult.fromJson(lab));
|
|
});
|
|
}, onFailure: (String error, int statusCode) {
|
|
labOrdersResultsList.clear();
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: body);
|
|
}
|
|
|
|
RequestSendLabReportEmail _requestSendLabReportEmail =
|
|
RequestSendLabReportEmail();
|
|
|
|
Future sendLabReportEmail(
|
|
{PatientLabOrders? patientLabOrder,
|
|
AuthenticatedUser? userObj,
|
|
bool isVidaPlus = false,
|
|
bool isDownload = false,
|
|
int languageID = 1}) async {
|
|
_requestSendLabReportEmail.projectID = patientLabOrder!.projectID;
|
|
_requestSendLabReportEmail.invoiceNo =
|
|
isVidaPlus ? "0" : patientLabOrder.invoiceNo;
|
|
_requestSendLabReportEmail.invoiceNoVP =
|
|
isVidaPlus ? patientLabOrder.invoiceNo : "0";
|
|
_requestSendLabReportEmail.invoiceType = patientLabOrder.invoiceType;
|
|
_requestSendLabReportEmail.doctorName = patientLabOrder.doctorName;
|
|
_requestSendLabReportEmail.clinicName = patientLabOrder.clinicDescription;
|
|
_requestSendLabReportEmail.patientName =
|
|
userObj!.firstName! + " " + userObj.lastName!;
|
|
_requestSendLabReportEmail.patientIditificationNum =
|
|
userObj.patientIdentificationNo;
|
|
_requestSendLabReportEmail.dateofBirth = userObj.dateofBirth;
|
|
_requestSendLabReportEmail.to = userObj.emailAddress;
|
|
_requestSendLabReportEmail.orderDate =
|
|
'${patientLabOrder.orderDate!.year}-${patientLabOrder.orderDate!.month}-${patientLabOrder.orderDate!.day}';
|
|
_requestSendLabReportEmail.patientMobileNumber = userObj.mobileNumber;
|
|
_requestSendLabReportEmail.projectName = patientLabOrder.projectName;
|
|
_requestSendLabReportEmail.setupID = patientLabOrder.setupID;
|
|
_requestSendLabReportEmail.orderNo = patientLabOrder.orderNo;
|
|
_requestSendLabReportEmail.orderNo = patientLabOrder.orderNo;
|
|
_requestSendLabReportEmail.isDownload = isDownload;
|
|
_requestSendLabReportEmail.doctorID = patientLabOrder.doctorID;
|
|
_requestSendLabReportEmail.languageID = languageID;
|
|
|
|
// await baseAppClient.post(SEND_LAB_RESULT_EMAIL, onSuccess: (dynamic response, int statusCode) {
|
|
await baseAppClient
|
|
.post(isVidaPlus ? SEND_LAB_RESULT_EMAIL : SEND_LAB_RESULT_EMAIL_NEW,
|
|
onSuccess: (dynamic response, int statusCode) {
|
|
if (isDownload) {
|
|
labReportPDF = isVidaPlus
|
|
? response['LabReportsPDFContent']
|
|
: response['PdfContent'];
|
|
}
|
|
}, onFailure: (String error, int statusCode) {
|
|
hasError = true;
|
|
super.error = error;
|
|
}, body: _requestSendLabReportEmail.toJson());
|
|
}
|
|
|
|
List<LabOrderResult> sortByFlagAndValue(List<LabOrderResult> original) {
|
|
const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];
|
|
|
|
int getFlagPriority(String? flag) {
|
|
if (flag == null) return priorityOrder.length;
|
|
final index = priorityOrder.indexOf(flag);
|
|
return index == -1 ? priorityOrder.length : index;
|
|
}
|
|
|
|
double parseResultValue(String? value) {
|
|
if (value == null) return double.nan;
|
|
return double.tryParse(value) ?? double.nan;
|
|
}
|
|
|
|
final copy = List<LabOrderResult>.from(original);
|
|
copy.sort((a, b) {
|
|
final aFlagPriority = getFlagPriority(a.calculatedResultFlag);
|
|
final bFlagPriority = getFlagPriority(b.calculatedResultFlag);
|
|
|
|
if (aFlagPriority != bFlagPriority) {
|
|
return aFlagPriority.compareTo(bFlagPriority);
|
|
}
|
|
|
|
final aValue = parseResultValue(a.resultValue);
|
|
final bValue = parseResultValue(b.resultValue);
|
|
|
|
return aValue.compareTo(bValue);
|
|
});
|
|
|
|
return copy;
|
|
}
|
|
|
|
Map<String, LabOrderResult> mapFirstItemByPriority(
|
|
List<LabOrderResult> sortedResults) {
|
|
final Map<String, LabOrderResult> priorityMap = {};
|
|
const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];
|
|
for (final result in sortedResults) {
|
|
final priority = result.calculatedResultFlag?.trim();
|
|
if (priority != null &&
|
|
priorityOrder.contains(priority) &&
|
|
!priorityMap.containsKey(priority)) {
|
|
priorityMap[priority] = result;
|
|
}
|
|
|
|
// Early exit if all priorities are found
|
|
if (priorityMap.length == priorityOrder.length) break;
|
|
}
|
|
print("the map of priority is :\n $priorityMap");
|
|
return priorityMap;
|
|
}
|
|
|
|
List<LabOrderResult> getMostRecentThree(List<LabOrderResult> original) {
|
|
DateTime? parseVerifiedDate(String? raw) {
|
|
if (raw == null) return null;
|
|
final regex = RegExp(r'\/Date\((\d+)\)\/');
|
|
final match = regex.firstMatch(raw);
|
|
if (match != null) {
|
|
print("the match iss not null");
|
|
final millis = int.tryParse(match.group(1)!);
|
|
if (millis != null) {
|
|
print(
|
|
"the data and time is ${DateTime.fromMillisecondsSinceEpoch(millis)}");
|
|
return DateTime.fromMillisecondsSinceEpoch(millis);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
final copy = List<LabOrderResult>.from(original);
|
|
copy.sort((a, b) {
|
|
final aDate = DateUtil.convertStringToDate(a.verifiedOnDateTime);
|
|
final bDate = DateUtil.convertStringToDate(b.verifiedOnDateTime);
|
|
if (aDate == null && bDate == null) return 0;
|
|
if (aDate == null) return 1;
|
|
if (bDate == null) return -1;
|
|
return bDate.compareTo(aDate); // descending
|
|
});
|
|
|
|
print("the copied item are $copy");
|
|
labOrdersResultsList = copy;
|
|
return copy.take(3).toList();
|
|
}
|
|
|
|
List<ThresholdRange> buildThresholdList(List<LabOrderResult> topResults) {
|
|
var mapOfPriority = mapFirstItemByPriority(topResults);
|
|
return mapResultToThreshold(topResults, mapOfPriority);
|
|
}
|
|
|
|
List<ThresholdRange> mapResultToThreshold(
|
|
List<LabOrderResult> results, Map<String, LabOrderResult> mapOfPriority) {
|
|
// Extract valid numeric results
|
|
List<double> actualValues = results
|
|
.map((e) => double.tryParse(e.resultValue ?? ''))
|
|
.where((v) => v != null)
|
|
.cast<double>()
|
|
.toList();
|
|
|
|
if (actualValues.isEmpty) return [];
|
|
|
|
actualValues.sort();
|
|
double min = actualValues.first;
|
|
double max = actualValues.last;
|
|
|
|
double baseRange = max - min;
|
|
|
|
// Handle single value or equal values
|
|
if (baseRange == 0) {
|
|
baseRange = max * 0.2; // ±10%
|
|
min = max - baseRange / 2;
|
|
max = max + baseRange / 2;
|
|
}
|
|
|
|
// Adjust range scale based on number of actual values
|
|
// >5 = compress thresholds; <5 = expand thresholds
|
|
int valueCount = actualValues.length;
|
|
double scalingFactor = valueCount >= 5 ? 1.0 : (5 / valueCount);
|
|
|
|
double adjustedRange = baseRange * scalingFactor;
|
|
|
|
// Recalculate thresholds based on adjusted range
|
|
// double criticalLow = min;
|
|
// double low = min + 0.25 * adjustedRange;
|
|
// double normal = min + 0.5 * adjustedRange;
|
|
// double high = min + 0.75 * adjustedRange;
|
|
// double criticalHigh = min + adjustedRange;
|
|
const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];
|
|
|
|
var mapOfValues = inferThresholds(mapOfPriority);
|
|
var item = results.first;
|
|
String? realCriticalLow =
|
|
(item.criticalLow == "0") ? null : item.criticalLow;
|
|
String? realReferenceHigh =
|
|
(item.referenceHigh == "0") ? null : item.referenceHigh;
|
|
String? realCriticalHigh =
|
|
(item.criticalHigh == "0") ? null : item.criticalHigh;
|
|
String? realReferenceLow =
|
|
(item.referenceLow == "0") ? null : item.referenceLow;
|
|
final adjustedValues = adjustValues(
|
|
criticalLow: mapOfValues['criticalLow'],
|
|
low: mapOfValues['low'],
|
|
normal: mapOfValues['normal'],
|
|
high: mapOfValues['high'],
|
|
criticalHigh: mapOfValues['criticalHigh'],
|
|
);
|
|
|
|
return [
|
|
ThresholdRange(
|
|
label: 'Critical Low',
|
|
value: adjustedValues["criticalLow"]!,
|
|
color: Color(0xffffffff),
|
|
lineColor: Color(0xFFe9a2a4),
|
|
actualValue: realCriticalLow),
|
|
ThresholdRange(
|
|
label: 'Low',
|
|
value: adjustedValues['low']!,
|
|
color: Color(0xFFf2fbf5),
|
|
lineColor: Color(0xFFefc481),
|
|
actualValue: realReferenceLow),
|
|
ThresholdRange(
|
|
label: 'Normal',
|
|
value: adjustedValues['normal']!,
|
|
color: Color(0xFFf2fbf5),
|
|
lineColor: Color(0xFF5dc36b)),
|
|
ThresholdRange(
|
|
label: 'High',
|
|
value: adjustedValues['high']!,
|
|
color: Color(0xffffffff),
|
|
lineColor: Color(0xFFefc481),
|
|
actualValue: realReferenceHigh),
|
|
ThresholdRange(
|
|
label: 'Critical High',
|
|
value: adjustedValues['criticalHigh']!,
|
|
color: Color(0xffffffff),
|
|
lineColor: Color(0xFFe9a2a4),
|
|
actualValue: realCriticalHigh),
|
|
];
|
|
}
|
|
|
|
Map<String, double> inferThresholds(
|
|
Map<String, LabOrderResult> mapOfPriority) {
|
|
double? parse(String? v) {
|
|
final parsed = double.tryParse(v ?? '');
|
|
return (parsed == null || parsed < 0) ? null : parsed;
|
|
}
|
|
|
|
// Parse inputs
|
|
double? criticalLow = parse(
|
|
mapOfPriority['LCL']?.resultValue ?? mapOfPriority['CL']?.resultValue);
|
|
double? low = parse(mapOfPriority['L']?.resultValue);
|
|
double? normal = parse(mapOfPriority['N']?.resultValue);
|
|
double? high = parse(mapOfPriority['H']?.resultValue);
|
|
double? criticalHigh = parse(
|
|
mapOfPriority['CH']?.resultValue ?? mapOfPriority['HCH']?.resultValue);
|
|
|
|
const step = 5.0;
|
|
List<double?> values = [criticalLow, low, normal, high, criticalHigh];
|
|
// Find the index of the known value (priority: central -> left -> right)
|
|
int anchorIndex = values.indexWhere((v) => v != null);
|
|
double anchorValue = values[anchorIndex] ?? 50;
|
|
|
|
// Infer all values around the anchor
|
|
List<double> inferred = List.generate(5, (i) {
|
|
double v = anchorValue + (i - anchorIndex) * step;
|
|
return v < 0 ? 0 : v;
|
|
});
|
|
var mapresult = {
|
|
'criticalLow': values[0]??-1,
|
|
'low': values[1]??-1,
|
|
'normal': values[2]??-1,
|
|
'high': values[3]??-1,
|
|
'criticalHigh': values[4]??-1,
|
|
};
|
|
|
|
print("the result is $mapresult");
|
|
return mapresult;
|
|
}
|
|
|
|
Map<String, double> adjustValues({
|
|
double? criticalLow,
|
|
double? low,
|
|
double? normal,
|
|
double? high,
|
|
double? criticalHigh,
|
|
double step = 10,
|
|
}) {
|
|
bool criticalLowHasValue = true;
|
|
bool lowHasValue = true;
|
|
bool normaHasValue = true;
|
|
bool highHasValue = true;
|
|
bool criticalHighHasValue = true;
|
|
|
|
if (criticalLow == null || criticalLow == -1) criticalLowHasValue = false;
|
|
if (low == null || low == -1) lowHasValue = false;
|
|
if (normal == null ||normal ==-1) normaHasValue = false;
|
|
if (high == null ||high ==-1) highHasValue = false;
|
|
if (criticalHigh == null ||criticalHigh ==-1) criticalHighHasValue = false;
|
|
|
|
print("the values arre $criticalLowHasValue $lowHasValue $normaHasValue $highHasValue $criticalHighHasValue");
|
|
if (!criticalLowHasValue) {
|
|
criticalLow = 0;
|
|
if (lowHasValue) {
|
|
low = low! - step;
|
|
} if (normaHasValue && (criticalLow!= 0 || criticalLow != -1)) {
|
|
low = normal! - step * 2;
|
|
} if (highHasValue && (criticalLow!= 0 || criticalLow != -1)) {
|
|
low = high! - step * 3;
|
|
} if (criticalHighHasValue && (criticalLow!= 0 || criticalLow != -1)) {
|
|
low = criticalHigh! - step * 4;
|
|
}
|
|
}
|
|
if (!lowHasValue) {
|
|
print("the low value is not set");
|
|
low = 0;
|
|
|
|
if (criticalLowHasValue && (low != 0 || low != -1)) {
|
|
low = criticalLow! + step;
|
|
} if (normaHasValue && (low != 0 || low != -1)) {
|
|
low = normal! - step;
|
|
} if (highHasValue && (low != 0 || low != -1)) {
|
|
low = high! - step * 2;
|
|
} if (criticalHighHasValue && (low != 0 || low != -1)) {
|
|
low = criticalHigh! - step * 3;
|
|
}
|
|
|
|
}
|
|
if (!normaHasValue) {
|
|
normal = 0;
|
|
|
|
if (criticalLowHasValue && (normal != 0 || normal != -1)) {
|
|
normal = criticalLow! + step * 2;
|
|
} if (lowHasValue) {
|
|
normal = low! + step;
|
|
} if (highHasValue) {
|
|
normal = high! - step;
|
|
} if (criticalHighHasValue) {
|
|
normal = criticalHigh! - step * 2;
|
|
}
|
|
}
|
|
if (!highHasValue) {
|
|
high = 0;
|
|
|
|
if (criticalLowHasValue) {
|
|
high = criticalLow! + step * 3;
|
|
} if (lowHasValue) {
|
|
high = low! + step * 2;
|
|
} if (normaHasValue) {
|
|
high = normal! + step;
|
|
} if (criticalHighHasValue) {
|
|
high = criticalHigh! - step;
|
|
}
|
|
}
|
|
if (!criticalHighHasValue) {
|
|
|
|
criticalHigh = 0;
|
|
|
|
if (criticalLowHasValue) {
|
|
criticalHigh = criticalLow! + step * 4;
|
|
} if (lowHasValue) {
|
|
criticalHigh = low! + step * 3;
|
|
} if (normaHasValue) {
|
|
criticalHigh = normal! + step * 2;
|
|
} if (highHasValue) {
|
|
criticalHigh = high! + step;
|
|
}
|
|
}
|
|
if(((criticalLow??0)<0) == true){
|
|
var mod = ((low ?? 0) + (normal??0) )/2;
|
|
criticalLow = mod;
|
|
}
|
|
|
|
if(((low??0)<0) == true){
|
|
var mod = ((criticalLow ?? 0) + (normal??0) )/2;
|
|
low = mod;
|
|
}
|
|
|
|
if(((normal??0)<0) == true){
|
|
var mod = ((low ?? 0) + (high??0) )/2;
|
|
normal = mod;
|
|
}
|
|
if(((high??0)<0) == true){
|
|
var mod = ((normal ?? 0) + (criticalHigh??0) )/2;
|
|
high = mod;
|
|
}
|
|
|
|
if(((criticalHigh??0)<0) == true){
|
|
criticalHigh = (high??0)+step;
|
|
}
|
|
|
|
|
|
|
|
Map<String, double?> values = {
|
|
'criticalLow':criticalLow ,
|
|
'low': low,
|
|
'normal': normal ,
|
|
'high': high ,
|
|
'criticalHigh': criticalHigh,
|
|
};
|
|
print("thee adjusted values `are $values");
|
|
|
|
// // Find the first known value
|
|
// int firstKnownIndex = values.values.toList().indexWhere((v) => v != null);
|
|
//
|
|
// if (firstKnownIndex == -1) {
|
|
// // No values at all, start from 0
|
|
// values = {
|
|
// 'criticalLow': 0,
|
|
// 'low': step,
|
|
// 'normal': step * 2,
|
|
// 'high': step * 3,
|
|
// 'criticalHigh': step * 4,
|
|
// };
|
|
// } else {
|
|
// // Fill backward
|
|
// for (int i = firstKnownIndex - 1; i >= 0; i--) {
|
|
// values[values.keys.elementAt(i)] =
|
|
// (values.values.elementAt(i + 1)! - step).clamp(0, double.infinity);
|
|
// }
|
|
//
|
|
// // Fill forward
|
|
// for (int i = firstKnownIndex + 1; i < values.length; i++) {
|
|
// values[values.keys.elementAt(i)] =
|
|
// values.values.elementAt(i - 1)! + step;
|
|
// }
|
|
// }
|
|
//
|
|
// // Ensure strictly increasing sequence
|
|
// double prev = -double.infinity;
|
|
// values.forEach((key, val) {
|
|
// if (val! <= prev) {
|
|
// values[key] = prev + step;
|
|
// }
|
|
// prev = values[key]!;
|
|
// });
|
|
|
|
return values.map((k, v) => MapEntry(k, v!));
|
|
}
|
|
|
|
void adjustLabOrderResults(List<LabOrderResult> results) {
|
|
const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];
|
|
|
|
// Sort results by priority order
|
|
results.sort((a, b) => priorityOrder
|
|
.indexOf(a.calculatedResultFlag ?? '')
|
|
.compareTo(priorityOrder.indexOf(b.calculatedResultFlag ?? '')));
|
|
|
|
// Extract values
|
|
List<double?> values = results.map((r) {
|
|
double? v = double.tryParse(r.resultValue ?? '');
|
|
return (v != null && v >= 0) ? v : null;
|
|
}).toList();
|
|
|
|
// Find first non-null index
|
|
int? firstIdx = values.indexWhere((v) => v != null);
|
|
if (firstIdx == -1) return; // All values missing
|
|
|
|
// Fill before first known value (decreasing with step 5, not less than 0)
|
|
for (int i = firstIdx - 1; i >= 0; i--) {
|
|
values[i] = (values[i + 1]! - 5).clamp(0, double.infinity);
|
|
}
|
|
|
|
// Fill after first known value (increasing with step 5)
|
|
for (int i = firstIdx + 1; i < values.length; i++) {
|
|
if (values[i] == null) {
|
|
values[i] = values[i - 1]! + 5;
|
|
}
|
|
}
|
|
|
|
// For gaps in the middle, interpolate
|
|
for (int i = 0; i < values.length; i++) {
|
|
if (values[i] == null) {
|
|
// find next non-null
|
|
int j = i + 1;
|
|
while (j < values.length && values[j] == null) j++;
|
|
if (j < values.length) {
|
|
double start = values[i - 1]!;
|
|
double end = values[j]!;
|
|
double step = (end - start) / (j - i + 1);
|
|
for (int k = i; k < j; k++) {
|
|
values[k] = start + step * (k - i + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update results list directly
|
|
for (int i = 0; i < results.length; i++) {
|
|
results[i].resultValue = values[i]?.toStringAsFixed(2) ?? '0.00';
|
|
}
|
|
}
|
|
|
|
double transformValueInRange(double inputValue, String flag) {
|
|
// Define range boundaries
|
|
double rangeStart, rangeEnd;
|
|
|
|
switch (flag) {
|
|
case 'CL':
|
|
rangeStart = 0.0;
|
|
rangeEnd = 19.0;
|
|
break;
|
|
case 'L':
|
|
rangeStart = 20.0;
|
|
rangeEnd = 39.0;
|
|
break;
|
|
case 'N':
|
|
rangeStart = 40.0;
|
|
rangeEnd = 59.0;
|
|
break;
|
|
case 'H':
|
|
rangeStart = 60.0;
|
|
rangeEnd = 79.0;
|
|
break;
|
|
case 'CH':
|
|
rangeStart = 80.0;
|
|
rangeEnd = 100.0;
|
|
break;
|
|
default:
|
|
throw ArgumentError('Invalid flag: $flag');
|
|
}
|
|
|
|
// Clamp input value to 0-100 and map it to the range bounds
|
|
final clampedValue = inputValue.clamp(0.0, 100.0);
|
|
final normalizedValue = clampedValue / 100.0; // Normalize input to 0-1
|
|
|
|
// Map the normalized value to the target range bounds
|
|
final transformedValue = rangeStart + (normalizedValue * (rangeEnd - rangeStart));
|
|
|
|
return transformedValue;
|
|
}
|
|
|
|
|
|
|
|
List<ThresholdRange> getThresholdValue() {
|
|
return [
|
|
ThresholdRange(
|
|
label: 'criticalLow',
|
|
value: 0,
|
|
color: Color(0xffffffff),
|
|
lineColor: Color(0xFFe9a2a4)),
|
|
ThresholdRange(
|
|
label: 'low',
|
|
value: 20,
|
|
color: Color(0xFFf2fbf5),
|
|
lineColor: Color(0xFFeecd94)),
|
|
ThresholdRange(
|
|
label: 'normal',
|
|
value: 40,
|
|
color: Color(0xFFf2fbf5),
|
|
lineColor: Color(0xFF5dc36b)),
|
|
ThresholdRange(
|
|
label: 'high',
|
|
value: 60,
|
|
color: Color(0xffffffff),
|
|
lineColor: Color(0xFFeecd94)),
|
|
ThresholdRange(
|
|
label: 'criticalHigh',
|
|
value: 80,
|
|
color: Color(0xffffffff),
|
|
lineColor: Color(0xFFe9a2a4)),
|
|
];
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|