@measurequick/measurequick-report-generator 1.5.221 → 1.5.223
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -254,6 +254,8 @@ export async function getReport(payload, _test) {
|
|
|
254
254
|
return isFinite(n) ? n : NaN;
|
|
255
255
|
}
|
|
256
256
|
var coAmbRaw = toNum(data && data.co_ambient);
|
|
257
|
+
var coRetRaw = toNum(data && data.co_return);
|
|
258
|
+
var coSupRaw = toNum(data && data.co_supply);
|
|
257
259
|
if (isFinite(coAmbRaw) && coAmbRaw > 9) {
|
|
258
260
|
safeSetText(
|
|
259
261
|
form,
|
|
@@ -511,16 +513,57 @@ export async function getReport(payload, _test) {
|
|
|
511
513
|
passFails.splice(3, 1);
|
|
512
514
|
pfLabels.splice(3, 1);
|
|
513
515
|
}
|
|
516
|
+
|
|
517
|
+
// CO threshold color helpers
|
|
518
|
+
function getCOIcon(coValue) {
|
|
519
|
+
if (coValue === null || coValue === undefined || isNaN(coValue)) {
|
|
520
|
+
return iconRangeGreen;
|
|
521
|
+
}
|
|
522
|
+
if (coValue <= 9) {
|
|
523
|
+
return iconRangeGreen;
|
|
524
|
+
} else if (coValue > 9 && coValue <= 35) {
|
|
525
|
+
return iconRangeYellow;
|
|
526
|
+
} else {
|
|
527
|
+
return iconRangeRed;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function getCOTextColor(coValue) {
|
|
532
|
+
if (coValue === null || coValue === undefined || isNaN(coValue)) {
|
|
533
|
+
return rgb(0, 0, 0);
|
|
534
|
+
}
|
|
535
|
+
if (coValue <= 9) {
|
|
536
|
+
return rgb(0, 0, 0); // black - OK
|
|
537
|
+
} else if (coValue > 9 && coValue <= 35) {
|
|
538
|
+
return rgb(1, 0.6, 0); // orange - Elevated
|
|
539
|
+
} else {
|
|
540
|
+
return rgb(0.96, 0.26, 0.21); // red - Dangerous
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function getCOStatus(coValue) {
|
|
545
|
+
if (coValue === null || coValue === undefined || isNaN(coValue)) {
|
|
546
|
+
return "";
|
|
547
|
+
}
|
|
548
|
+
if (coValue <= 9) {
|
|
549
|
+
return "OK";
|
|
550
|
+
} else {
|
|
551
|
+
return "Elevated";
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Collect valid items first (no gaps)
|
|
556
|
+
let validItems = [];
|
|
557
|
+
|
|
514
558
|
for (let i = 0; i < passFails.length; i++) {
|
|
515
559
|
const meas = test.testInfo[passFails[i]];
|
|
516
560
|
|
|
517
|
-
//
|
|
561
|
+
// Skip items with no value
|
|
518
562
|
if (meas === undefined || meas === null || meas === "") {
|
|
519
|
-
safeSetText(form, `SSR${i + 1}`, "");
|
|
520
563
|
continue;
|
|
521
564
|
}
|
|
522
565
|
|
|
523
|
-
//
|
|
566
|
+
// Determine icon based on value
|
|
524
567
|
let icon;
|
|
525
568
|
if (meas === "Caution") {
|
|
526
569
|
icon = iconRangeYellow;
|
|
@@ -529,53 +572,85 @@ export async function getReport(payload, _test) {
|
|
|
529
572
|
} else {
|
|
530
573
|
icon = iconRangeRed;
|
|
531
574
|
}
|
|
532
|
-
if (passFails[i] === "heating_efficiency_pass_fail")
|
|
575
|
+
if (passFails[i] === "heating_efficiency_pass_fail") {
|
|
533
576
|
icon = iconRangeGreen;
|
|
534
|
-
|
|
535
|
-
// Set the icon as before
|
|
536
|
-
safeSetImage(form, `ImageSubsystem${i + 1}_af_image`, icon);
|
|
577
|
+
}
|
|
537
578
|
|
|
538
579
|
const suffix = test.testInfo[passFails[i] + "_override"] ? " *" : "";
|
|
539
|
-
const fieldName = `SSR${i + 1}`;
|
|
540
|
-
|
|
541
|
-
// Default label for non-special cases
|
|
542
580
|
let label = pfLabels[i] + suffix;
|
|
581
|
+
let textColor = rgb(0, 0, 0); // default black
|
|
543
582
|
|
|
544
|
-
// Special handling
|
|
583
|
+
// Special handling for Ambient CO - show actual values
|
|
545
584
|
if (passFails[i] === "ambient_pass_fail") {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
)
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
585
|
+
// Calculate CO delta
|
|
586
|
+
const coDelta = (isFinite(coSupRaw) && isFinite(coRetRaw)) ? (coSupRaw - coRetRaw) : null;
|
|
587
|
+
const hasCODeltaWarning = test.testInfo.ambient_pass_fail_co_delta_warning || (coDelta !== null && coDelta >= 1);
|
|
588
|
+
|
|
589
|
+
// Add CO Ambient with value
|
|
590
|
+
if (isFinite(coAmbRaw)) {
|
|
591
|
+
const coAmbIcon = getCOIcon(coAmbRaw);
|
|
592
|
+
const coAmbColor = getCOTextColor(coAmbRaw);
|
|
593
|
+
const coAmbStatus = getCOStatus(coAmbRaw);
|
|
594
|
+
const coAmbLabel = "CO Ambient: " + Math.round(coAmbRaw) + " ppm (" + coAmbStatus + ")" + suffix;
|
|
595
|
+
validItems.push({ label: coAmbLabel, icon: coAmbIcon, textColor: coAmbColor });
|
|
596
|
+
} else if (meas) {
|
|
597
|
+
// No CO value but has pass/fail - show generic
|
|
598
|
+
const isFail = !(meas === "Pass" || meas === "High" || meas === "Mid" || meas === "Caution");
|
|
599
|
+
if (isFail) {
|
|
600
|
+
validItems.push({ label: "CO Ambient: Elevated" + suffix, icon: iconRangeYellow, textColor: rgb(1, 0.6, 0) });
|
|
601
|
+
} else {
|
|
602
|
+
validItems.push({ label: "CO Ambient: OK" + suffix, icon: iconRangeGreen, textColor: rgb(0, 0, 0) });
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// Add CO Return with value (if available and not boiler)
|
|
607
|
+
if (isFinite(coRetRaw) && !payload.meta.boiler_type) {
|
|
608
|
+
const coRetIcon = getCOIcon(coRetRaw);
|
|
609
|
+
const coRetColor = getCOTextColor(coRetRaw);
|
|
610
|
+
const coRetStatus = getCOStatus(coRetRaw);
|
|
611
|
+
const coRetLabel = "CO Return: " + Math.round(coRetRaw) + " ppm (" + coRetStatus + ")";
|
|
612
|
+
validItems.push({ label: coRetLabel, icon: coRetIcon, textColor: coRetColor });
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Add CO Supply with value (if available and not boiler)
|
|
616
|
+
if (isFinite(coSupRaw) && !payload.meta.boiler_type) {
|
|
617
|
+
const coSupIcon = getCOIcon(coSupRaw);
|
|
618
|
+
const coSupColor = getCOTextColor(coSupRaw);
|
|
619
|
+
const coSupStatus = getCOStatus(coSupRaw);
|
|
620
|
+
const coSupLabel = "CO Supply: " + Math.round(coSupRaw) + " ppm (" + coSupStatus + ")";
|
|
621
|
+
validItems.push({ label: coSupLabel, icon: coSupIcon, textColor: coSupColor });
|
|
569
622
|
}
|
|
623
|
+
|
|
624
|
+
// Add CO Delta (if both return and supply available and not boiler)
|
|
625
|
+
if (coDelta !== null && !payload.meta.boiler_type) {
|
|
626
|
+
const deltaIcon = hasCODeltaWarning ? iconRangeRed : iconRangeGreen;
|
|
627
|
+
const deltaColor = hasCODeltaWarning ? rgb(0.96, 0.26, 0.21) : rgb(0, 0, 0);
|
|
628
|
+
const deltaStatus = hasCODeltaWarning ? "Investigate Heat Exchanger" : "OK";
|
|
629
|
+
const deltaLabel = "CO Delta: " + Math.round(coDelta) + " ppm (" + deltaStatus + ")";
|
|
630
|
+
validItems.push({ label: deltaLabel, icon: deltaIcon, textColor: deltaColor });
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
continue; // Skip adding the default ambient_pass_fail item
|
|
570
634
|
}
|
|
571
635
|
|
|
572
|
-
|
|
636
|
+
validItems.push({ label, icon, textColor });
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Fill fields sequentially with valid items (no gaps)
|
|
640
|
+
for (let i = 0; i < validItems.length; i++) {
|
|
641
|
+
const item = validItems[i];
|
|
642
|
+
safeSetImage(form, `ImageSubsystem${i + 1}_af_image`, item.icon);
|
|
573
643
|
try {
|
|
574
|
-
const tf = form.getTextField(
|
|
575
|
-
tf.setText(label);
|
|
576
|
-
tf.setTextColor(
|
|
644
|
+
const tf = form.getTextField(`SSR${i + 1}`);
|
|
645
|
+
tf.setText(item.label);
|
|
646
|
+
tf.setTextColor(item.textColor);
|
|
577
647
|
} catch (e) {}
|
|
578
648
|
}
|
|
649
|
+
|
|
650
|
+
// Clear any remaining unused fields
|
|
651
|
+
for (let i = validItems.length; i < passFails.length + 3; i++) {
|
|
652
|
+
safeSetText(form, `SSR${i + 1}`, "");
|
|
653
|
+
}
|
|
579
654
|
} else safeSetText(form, `SSR1`, "Not yet reviewed");
|
|
580
655
|
|
|
581
656
|
if (payload.meta.report_type != "FullReport") {
|
|
@@ -330,13 +330,13 @@ export async function getReport(payload, _test) {
|
|
|
330
330
|
// Build warning message focused on ambient CO
|
|
331
331
|
var warningMsg, warningMsg2;
|
|
332
332
|
if (ambientReading) {
|
|
333
|
-
warningMsg = "WARNING: " + ambientReading.level + " Ambient CO
|
|
334
|
-
warningMsg2 = "WARNING: " + ambientReading.level + " Ambient CO
|
|
333
|
+
warningMsg = "WARNING: " + ambientReading.level + " Ambient CO " + Math.round(ambientReading.value) + " ppm\nVentilate the area and investigate source.";
|
|
334
|
+
warningMsg2 = "WARNING: " + ambientReading.level + " Ambient CO " + Math.round(ambientReading.value) + " ppm. Ventilate the area and investigate source.";
|
|
335
335
|
} else {
|
|
336
336
|
// Fallback if no ambient reading (use first reading)
|
|
337
337
|
var firstReading = reasons[0];
|
|
338
|
-
warningMsg = "WARNING: " + firstReading.level + " " + firstReading.type + " CO
|
|
339
|
-
warningMsg2 = "WARNING: " + firstReading.level + " " + firstReading.type + " CO
|
|
338
|
+
warningMsg = "WARNING: " + firstReading.level + " " + firstReading.type + " CO " + Math.round(firstReading.value) + " ppm\nVentilate the area and investigate source.";
|
|
339
|
+
warningMsg2 = "WARNING: " + firstReading.level + " " + firstReading.type + " CO " + Math.round(firstReading.value) + " ppm. Ventilate the area and investigate source.";
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
// Set text with color based on severity level
|
|
@@ -672,13 +672,23 @@ export async function getReport(payload, _test) {
|
|
|
672
672
|
// Use coAmbRaw which is already defined and validated earlier in the function
|
|
673
673
|
const coValue = isFinite(coAmbRaw) ? coAmbRaw : null;
|
|
674
674
|
|
|
675
|
+
// Check for CO delta warning (Supply - Return >= 1 ppm)
|
|
676
|
+
const coDelta = (isFinite(coSupRaw) && isFinite(coRetRaw)) ? (coSupRaw - coRetRaw) : null;
|
|
677
|
+
const hasCODeltaWarning = test.testInfo.ambient_pass_fail_co_delta_warning || (coDelta !== null && coDelta >= 1);
|
|
678
|
+
|
|
675
679
|
// Use CO-specific icon based on actual value
|
|
676
680
|
if (coValue !== null) {
|
|
677
681
|
icon = getCOIcon(coValue);
|
|
678
682
|
const stateText = getCOStateText(coValue);
|
|
679
683
|
|
|
680
|
-
// Format label based on CO level
|
|
681
|
-
if (
|
|
684
|
+
// Format label based on CO level and delta warning
|
|
685
|
+
if (hasCODeltaWarning) {
|
|
686
|
+
// CO delta detected - recommend heat exchanger investigation
|
|
687
|
+
icon = iconRangeRed;
|
|
688
|
+
textColor = rgb(0.96, 0.26, 0.21); // Red
|
|
689
|
+
const deltaValue = coDelta !== null ? Math.round(coDelta) : "";
|
|
690
|
+
label = "CO Delta " + deltaValue + " ppm: Investigate heat exchanger" + suffix;
|
|
691
|
+
} else if (coValue <= 8) {
|
|
682
692
|
// Normal - just show value
|
|
683
693
|
label = "Ambient CO: " + Math.round(coValue) + " ppm" + suffix;
|
|
684
694
|
} else {
|
|
@@ -686,15 +696,23 @@ export async function getReport(payload, _test) {
|
|
|
686
696
|
label = "CO Ambient " + stateText + " " + Math.round(coValue) + " ppm, Investigate!" + suffix;
|
|
687
697
|
}
|
|
688
698
|
|
|
689
|
-
// Set text color based on CO level
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
699
|
+
// Set text color based on CO level (if not already set by delta warning)
|
|
700
|
+
if (!hasCODeltaWarning) {
|
|
701
|
+
// Orange for Elevated, Red for Dangerous, Dark Red for Emergency
|
|
702
|
+
if (coValue >= 70) {
|
|
703
|
+
textColor = rgb(0.72, 0.11, 0.11); // Dark red for Emergency
|
|
704
|
+
} else if (coValue >= 36) {
|
|
705
|
+
textColor = rgb(0.96, 0.26, 0.21); // Red for Dangerous
|
|
706
|
+
} else if (coValue >= 9) {
|
|
707
|
+
textColor = rgb(1, 0.6, 0); // Orange for Elevated
|
|
708
|
+
}
|
|
697
709
|
}
|
|
710
|
+
} else if (hasCODeltaWarning) {
|
|
711
|
+
// No ambient CO value but delta warning detected
|
|
712
|
+
icon = iconRangeRed;
|
|
713
|
+
textColor = rgb(0.96, 0.26, 0.21); // Red
|
|
714
|
+
const deltaValue = coDelta !== null ? Math.round(coDelta) : "";
|
|
715
|
+
label = "CO Delta " + deltaValue + " ppm: Investigate heat exchanger" + suffix;
|
|
698
716
|
} else {
|
|
699
717
|
// No CO value, use pass/fail status
|
|
700
718
|
const isFail = !(meas === "Pass" || meas === "High" || meas === "Mid" || meas === "Caution");
|