f7
f7 is a spreadsheet formula execution library
git clone https://git.vogt.world/f7.git
Log | Files | README.md | LICENSE.md
← All files
name: src/main/js/utils/Compare.ts
-rw-r--r--
4785
  1import { ComparisonResult, comparisonResultFromNumber } from "../models/common/ComparisonResults";
  2import { Converters } from "./Converters";
  3import { isNull } from "../common/utils/Types";
  4
  5export class Compare {
  6  /**
  7   * Compare two objects using their type precedence first, and then defaulting to their default class compare methods
  8   * if they are of the same type. If one is null, use a default depending on type.
  9   *
 10   * @param first  - object to compare. Should be Double, Boolean, String, or null.
 11   * @param second - second object to compare.  Should be Double, Boolean, String, or null.
 12   * @return ComparisonResult indicating less-than, greater-than, equal-to.
 13   */
 14  static compare(first: any, second: any): ComparisonResult {
 15    const firstPrecedence = Compare.getTypePrecedence(first);
 16    const secondPrecedence = Compare.getTypePrecedence(second);
 17    if (firstPrecedence === secondPrecedence) {
 18      if (isNull(first)) {
 19        return ComparisonResult.EQUAL;
 20      }
 21      if (typeof first === "number") {
 22        const firstNumber = Converters.toNumber(first);
 23        const secondNumber = Converters.toNumber(second);
 24        return comparisonResultFromNumber(Compare.numberComparison(firstNumber, secondNumber));
 25      }
 26      if (typeof first === "boolean") {
 27        const firstBoolean = Converters.toBoolean(first);
 28        const secondBoolean = Converters.toBoolean(second);
 29        return comparisonResultFromNumber(Compare.booleanComparison(firstBoolean, secondBoolean));
 30      }
 31      if (typeof first === "string") {
 32        const firstString = Converters.toText(first).toLowerCase();
 33        const secondString = Converters.toText(second).toLowerCase();
 34        return comparisonResultFromNumber(Compare.stringComparison(firstString, secondString));
 35      }
 36    }
 37    // If the first is null, the second must be a number. First falls back to default.
 38    if (isNull(first)) {
 39      if (typeof second === "number") {
 40        const firstNumber = 0;
 41        const secondNumber = Converters.toNumber(second);
 42        return comparisonResultFromNumber(Compare.numberComparison(firstNumber, secondNumber));
 43      }
 44      if (typeof second === "boolean") {
 45        const firstBoolean = false;
 46        const secondBoolean = Converters.toBoolean(second);
 47        return comparisonResultFromNumber(Compare.booleanComparison(firstBoolean, secondBoolean));
 48      }
 49      if (typeof second === "string") {
 50        const firstString = "";
 51        const secondString = Converters.toText(second).toLowerCase();
 52        return comparisonResultFromNumber(Compare.stringComparison(firstString, secondString));
 53      }
 54    }
 55    // If the second is null, the first must be a number. Second falls back to default.
 56    if (isNull(second)) {
 57      if (typeof first === "number") {
 58        const firstNumber = Converters.toNumber(first);
 59        const secondNumber = 0;
 60        return comparisonResultFromNumber(Compare.numberComparison(firstNumber, secondNumber));
 61      }
 62      if (typeof first === "boolean") {
 63        const firstBoolean = Converters.toBoolean(first);
 64        const secondBoolean = false;
 65        return comparisonResultFromNumber(Compare.booleanComparison(firstBoolean, secondBoolean));
 66      }
 67      if (typeof first === "string") {
 68        const firstString = Converters.toText(first).toLowerCase();
 69        const secondString = "";
 70        return comparisonResultFromNumber(Compare.stringComparison(firstString, secondString));
 71      }
 72    }
 73    return comparisonResultFromNumber(Compare.numberComparison(firstPrecedence, secondPrecedence));
 74  }
 75
 76  /**
 77   * Strings, Numbers, and Booleans have type precedence that is used when comparing across types.
 78   *
 79   * @param value to get precedence of.
 80   * @return {@code 1} if Number,{@code 2} if String, {@code 3} if Boolean.
 81   */
 82  static getTypePrecedence(value: any): number {
 83    if (isNull(value)) {
 84      return 0;
 85    }
 86    if (typeof value === "number") {
 87      return 1;
 88    }
 89    if (typeof value === "string") {
 90      return 2;
 91    }
 92    return 3;
 93  }
 94
 95  /**
 96   * Compare numbers by subtracting one from the other.
 97   * @param first number
 98   * @param second number
 99   */
100  static numberComparison(first: number, second: number): number {
101    return first - second;
102  }
103
104  /**
105   * Compare boolean values, returning 0, 1, -1
106   * @param first boolean.
107   * @param second boolean.
108   */
109  static booleanComparison(first: boolean, second: boolean): number {
110    return (first ? 1 : 0) - (second ? 1 : 0);
111  }
112
113  /**
114   * Compare strings, returning 0, 1, -1;
115   * @param first
116   * @param second
117   */
118  static stringComparison(first: string, second: string): number {
119    if (first === second) {
120      return 0;
121    }
122    if (first > second) {
123      return 1;
124    }
125    return -1;
126  }
127}