feat: warn if charging profile schedule periods are not sorted
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 25 Jul 2023 19:27:18 +0000 (21:27 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 25 Jul 2023 19:27:18 +0000 (21:27 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/ChargingStationUtils.ts
src/utils/Utils.ts
src/utils/index.ts
test/utils/Utils.test.ts

index ca4ec0b200130e00b6a80ee8dbbdc15df4358d1f..1af1266110bd62d2e49f42e5ec801cc34fac8546 100644 (file)
@@ -49,6 +49,7 @@ import {
   cloneObject,
   convertToDate,
   convertToInt,
+  isArraySorted,
   isEmptyObject,
   isEmptyString,
   isNotEmptyArray,
@@ -739,7 +740,21 @@ const getLimitFromChargingProfiles = (
       })
     ) {
       if (isNotEmptyArray(chargingSchedule.chargingSchedulePeriod)) {
-        chargingSchedule.chargingSchedulePeriod.sort((a, b) => a.startPeriod - b.startPeriod);
+        const chargingSchedulePeriodCompareFn = (
+          a: ChargingSchedulePeriod,
+          b: ChargingSchedulePeriod,
+        ) => a.startPeriod - b.startPeriod;
+        if (
+          isArraySorted<ChargingSchedulePeriod>(
+            chargingSchedule.chargingSchedulePeriod,
+            chargingSchedulePeriodCompareFn,
+          ) === false
+        ) {
+          logger.warn(
+            `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} schedule periods are not sorted by start period`,
+          );
+          chargingSchedule.chargingSchedulePeriod.sort(chargingSchedulePeriodCompareFn);
+        }
         // Check if the first schedule period start period is equal to 0
         if (chargingSchedule.chargingSchedulePeriod[0].startPeriod !== 0) {
           logger.error(
index ff41faf8a674540a8b512ac8664cb61e98bfc6ec..14869b0d35cee8bb2b9a429de17499196ac38437 100644 (file)
@@ -354,3 +354,12 @@ export const getWebSocketCloseEventStatusString = (code: number): string => {
   }
   return '(Unknown)';
 };
+
+export const isArraySorted = <T>(elements: T[], compareFn: (a: T, b: T) => number): boolean => {
+  for (let i = 0; i < elements.length - 1; ++i) {
+    if (compareFn(elements[i], elements[i + 1]) > 0) {
+      return false;
+    }
+  }
+  return true;
+};
index cdc98711a6b14afdff5c2a1048bdc7d936794185..86649874a30e1434c751056257972535fb760be4 100644 (file)
@@ -39,6 +39,7 @@ export {
   getRandomFloatRounded,
   getRandomInteger,
   getWebSocketCloseEventStatusString,
+  isArraySorted,
   isEmptyArray,
   isEmptyObject,
   isEmptyString,
index 4677fcdaa337c9a736d5b0e9df326eaf09b8cf11..233ee75d8baa886fcdd5e8920d7c58d544095a75 100644 (file)
@@ -11,6 +11,7 @@ import {
   getRandomFloat,
   getRandomInteger,
   hasOwnProp,
+  isArraySorted,
   isEmptyArray,
   isEmptyObject,
   isEmptyString,
@@ -365,4 +366,19 @@ describe('Utils test suite', () => {
     expect(isEmptyObject(new WeakMap())).toBe(false);
     expect(isEmptyObject(new WeakSet())).toBe(false);
   });
+
+  it('Verify isArraySorted()', () => {
+    expect(
+      isArraySorted([], (a, b) => {
+        return a - b;
+      }),
+    ).toBe(true);
+    expect(
+      isArraySorted([1], (a, b) => {
+        return a - b;
+      }),
+    ).toBe(true);
+    expect(isArraySorted<number>([1, 2, 3, 4, 5], (a, b) => a - b)).toBe(true);
+    expect(isArraySorted<number>([1, 2, 3, 5, 4], (a, b) => a - b)).toBe(false);
+  });
 });