summaryrefslogtreecommitdiff
path: root/src/main/java/sevenUnitsGUI/StandardDisplayRules.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/sevenUnitsGUI/StandardDisplayRules.java')
-rw-r--r--src/main/java/sevenUnitsGUI/StandardDisplayRules.java246
1 files changed, 246 insertions, 0 deletions
diff --git a/src/main/java/sevenUnitsGUI/StandardDisplayRules.java b/src/main/java/sevenUnitsGUI/StandardDisplayRules.java
new file mode 100644
index 0000000..0c0ba8e
--- /dev/null
+++ b/src/main/java/sevenUnitsGUI/StandardDisplayRules.java
@@ -0,0 +1,246 @@
+/**
+ * Copyright (C) 2022 Adrien Hopkins
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package sevenUnitsGUI;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.util.function.Function;
+import java.util.regex.Pattern;
+
+import sevenUnits.utils.UncertainDouble;
+
+/**
+ * A static utility class that can be used to make display rules for the
+ * presenter.
+ *
+ * @since 2022-04-18
+ */
+public final class StandardDisplayRules {
+ /**
+ * A rule that rounds to a fixed number of decimal places.
+ *
+ * @since 2022-04-18
+ */
+ public static final class FixedDecimals
+ implements Function<UncertainDouble, String> {
+ public static final Pattern TO_STRING_PATTERN = Pattern
+ .compile("Round to (\\d+) decimal places");
+ /**
+ * The number of places to round to.
+ */
+ private final int decimalPlaces;
+
+ /**
+ * @param decimalPlaces
+ * @since 2022-04-18
+ */
+ private FixedDecimals(int decimalPlaces) {
+ this.decimalPlaces = decimalPlaces;
+ }
+
+ @Override
+ public String apply(UncertainDouble t) {
+ final var toRound = new BigDecimal(t.value());
+ return toRound.setScale(this.decimalPlaces, RoundingMode.HALF_EVEN)
+ .toPlainString();
+ }
+
+ /**
+ * @return the number of decimal places this rule rounds to
+ * @since 2022-04-18
+ */
+ public int decimalPlaces() {
+ return this.decimalPlaces;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof FixedDecimals))
+ return false;
+ final FixedDecimals other = (FixedDecimals) obj;
+ if (this.decimalPlaces != other.decimalPlaces)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 + this.decimalPlaces;
+ }
+
+ @Override
+ public String toString() {
+ return "Round to " + this.decimalPlaces + " decimal places";
+ }
+ }
+
+ /**
+ * A rule that rounds to a fixed number of significant digits.
+ *
+ * @since 2022-04-18
+ */
+ public static final class FixedPrecision
+ implements Function<UncertainDouble, String> {
+ public static final Pattern TO_STRING_PATTERN = Pattern
+ .compile("Round to (\\d+) significant figures");
+
+ /**
+ * The number of significant figures to round to.
+ */
+ private final MathContext mathContext;
+
+ /**
+ * @param significantFigures
+ * @since 2022-04-18
+ */
+ private FixedPrecision(int significantFigures) {
+ this.mathContext = new MathContext(significantFigures,
+ RoundingMode.HALF_EVEN);
+ }
+
+ @Override
+ public String apply(UncertainDouble t) {
+ final var toRound = new BigDecimal(t.value());
+ return toRound.round(this.mathContext).toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof FixedPrecision))
+ return false;
+ final FixedPrecision other = (FixedPrecision) obj;
+ if (this.mathContext == null) {
+ if (other.mathContext != null)
+ return false;
+ } else if (!this.mathContext.equals(other.mathContext))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 127
+ + (this.mathContext == null ? 0 : this.mathContext.hashCode());
+ }
+
+ /**
+ * @return the number of significant figures this rule rounds to
+ * @since 2022-04-18
+ */
+ public int significantFigures() {
+ return this.mathContext.getPrecision();
+ }
+
+ @Override
+ public String toString() {
+ return "Round to " + this.mathContext.getPrecision()
+ + " significant figures";
+ }
+ }
+
+ /**
+ * A rounding rule that rounds based on UncertainDouble's toString method.
+ * This means the output will have around as many significant figures as the
+ * input.
+ *
+ * @since 2022-04-18
+ */
+ public static final class UncertaintyBased
+ implements Function<UncertainDouble, String> {
+ private UncertaintyBased() {}
+
+ @Override
+ public String apply(UncertainDouble t) {
+ return t.toString(false, RoundingMode.HALF_EVEN);
+ }
+
+ @Override
+ public String toString() {
+ return "Uncertainty-Based Rounding";
+ }
+ }
+
+ /**
+ * For now, I want this to be a singleton. I might want to add a parameter
+ * later, so I won't make it an enum.
+ */
+ private static final UncertaintyBased UNCERTAINTY_BASED_ROUNDING_RULE = new UncertaintyBased();
+
+ /**
+ * @param decimalPlaces decimal places to round to
+ * @return a rounding rule that rounds to fixed number of decimal places
+ * @since 2022-04-18
+ */
+ public static final FixedDecimals fixedDecimals(int decimalPlaces) {
+ return new FixedDecimals(decimalPlaces);
+ }
+
+ /**
+ * @param significantFigures significant figures to round to
+ * @return a rounding rule that rounds to a fixed number of significant
+ * figures
+ * @since 2022-04-18
+ */
+ public static final FixedPrecision fixedPrecision(int significantFigures) {
+ return new FixedPrecision(significantFigures);
+ }
+
+ /**
+ * Gets one of the standard rules from its string representation.
+ *
+ * @param ruleToString string representation of the display rule
+ * @return display rule
+ * @throws IllegalArgumentException if the provided string is not that of a
+ * standard rule.
+ * @since 2021-12-24
+ */
+ public static final Function<UncertainDouble, String> getStandardRule(
+ String ruleToString) {
+ if (UNCERTAINTY_BASED_ROUNDING_RULE.toString().equals(ruleToString))
+ return UNCERTAINTY_BASED_ROUNDING_RULE;
+
+ // test if it is a fixed-places rule
+ final var placesMatch = FixedDecimals.TO_STRING_PATTERN
+ .matcher(ruleToString);
+ if (placesMatch.matches())
+ return new FixedDecimals(Integer.valueOf(placesMatch.group(1)));
+
+ // test if it is a fixed-sig-fig rule
+ final var sigFigMatch = FixedPrecision.TO_STRING_PATTERN
+ .matcher(ruleToString);
+ if (sigFigMatch.matches())
+ return new FixedPrecision(Integer.valueOf(sigFigMatch.group(1)));
+
+ throw new IllegalArgumentException(
+ "Provided string does not match any given rules.");
+ }
+
+ /**
+ * @return an UncertainDouble-based rounding rule
+ * @since 2022-04-18
+ */
+ public static final UncertaintyBased uncertaintyBased() {
+ return UNCERTAINTY_BASED_ROUNDING_RULE;
+ }
+
+ private StandardDisplayRules() {}
+}