summaryrefslogtreecommitdiff
path: root/src/main/java/sevenUnitsGUI/Presenter.java
diff options
context:
space:
mode:
authorAdrien Hopkins <ahopk127@my.yorku.ca>2022-04-19 16:10:44 -0500
committerAdrien Hopkins <ahopk127@my.yorku.ca>2022-04-19 16:10:44 -0500
commit0aacba9fc8a9140fdf331172ad66afe280d09b5e (patch)
tree3699f6cf4ce40db818233287853474a4cf99ba5c /src/main/java/sevenUnitsGUI/Presenter.java
parent40f7b6e806140fc2fc741c63c71f5ce97b4bd1d2 (diff)
Implemented prefix settings, saving & loading of settings
Also fixed some bugs: - Presenter now has default values for its settings in case they don't load properly - UnitDatabase ensures its units, prefixes and dimensions have all of the names you give it
Diffstat (limited to 'src/main/java/sevenUnitsGUI/Presenter.java')
-rw-r--r--src/main/java/sevenUnitsGUI/Presenter.java175
1 files changed, 149 insertions, 26 deletions
diff --git a/src/main/java/sevenUnitsGUI/Presenter.java b/src/main/java/sevenUnitsGUI/Presenter.java
index f4f3e3a..fd050b7 100644
--- a/src/main/java/sevenUnitsGUI/Presenter.java
+++ b/src/main/java/sevenUnitsGUI/Presenter.java
@@ -16,8 +16,10 @@
*/
package sevenUnitsGUI;
+import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
@@ -30,7 +32,6 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
import sevenUnits.ProgramInfo;
import sevenUnits.unit.BaseDimension;
@@ -140,12 +141,24 @@ public final class Presenter {
}
/**
+ * @return true iff a and b have any elements in common
+ * @since 2022-04-19
+ */
+ private static final boolean sharesAnyElements(Set<?> a, Set<?> b) {
+ for (final Object e : a) {
+ if (b.contains(e))
+ return true;
+ }
+ return false;
+ }
+
+ /**
* @return {@code line} with any comments removed.
* @since 2021-03-13
*/
private static final String withoutComments(String line) {
final int index = line.indexOf('#');
- return index == -1 ? line : line.substring(index);
+ return index == -1 ? line : line.substring(0, index);
}
// ====== SETTINGS ======
@@ -171,14 +184,15 @@ public final class Presenter {
* of unit conversions will be put into this function, and the resulting
* string will be used in the output.
*/
- private Function<UncertainDouble, String> numberDisplayRule;
+ private Function<UncertainDouble, String> numberDisplayRule = StandardDisplayRules
+ .uncertaintyBased();
/**
* A predicate that determines whether or not a certain combination of
* prefixes is allowed. If it returns false, a combination of prefixes will
* not be allowed. Prefixes are put in the list from right to left.
*/
- private Predicate<List<UnitPrefix>> prefixRepetitionRule;
+ private Predicate<List<UnitPrefix>> prefixRepetitionRule = DefaultPrefixRepetitionRule.NO_RESTRICTION;
/**
* The set of units that is considered neither metric nor nonmetric for the
@@ -192,13 +206,13 @@ public final class Presenter {
* removed from the From unit list and imperial/USC units removed from the To
* unit list.
*/
- private boolean oneWayConversionEnabled;
+ private boolean oneWayConversionEnabled = false;
/**
* If this is false, duplicate units and prefixes will be removed from the
* unit view in views that show units as a list to choose from.
*/
- private boolean showDuplicates;
+ private boolean showDuplicates = false;
/**
* Creates a Presenter
@@ -245,7 +259,19 @@ public final class Presenter {
}
// set default settings temporarily
- this.numberDisplayRule = StandardDisplayRules.uncertaintyBased();
+ this.loadSettings(DEFAULT_SETTINGS_FILEPATH);
+
+ // a Predicate that returns true iff the argument is a full base unit
+ final Predicate<Unit> isFullBase = unit -> unit instanceof LinearUnit
+ && ((LinearUnit) unit).isBase();
+
+ // print out unit counts
+ System.out.printf(
+ "Successfully loaded %d units with %d unit names (%d base units).%n",
+ this.database.unitMapPrefixless(false).size(),
+ this.database.unitMapPrefixless(true).size(),
+ this.database.unitMapPrefixless(false).values().stream()
+ .filter(isFullBase).count());
}
/**
@@ -456,18 +482,35 @@ public final class Presenter {
}
/**
+ * @return the rule that determines whether a set of prefixes is valid
+ * @since 2022-04-19
+ */
+ public Predicate<List<UnitPrefix>> getPrefixRepetitionRule() {
+ return this.prefixRepetitionRule;
+ }
+
+ /**
+ * @return the view associated with this presenter
+ * @since 2022-04-19
+ */
+ public View getView() {
+ return this.view;
+ }
+
+ /**
* @return whether or not the provided unit is semi-metric (i.e. an
* exception)
* @since 2022-04-16
*/
- private final boolean isSemiMetric(Unit u) {
+ final boolean isSemiMetric(Unit u) {
// determine if u is an exception
final var primaryName = u.getPrimaryName();
final var symbol = u.getSymbol();
return primaryName.isPresent()
&& this.metricExceptions.contains(primaryName.orElseThrow())
|| symbol.isPresent()
- && this.metricExceptions.contains(symbol.orElseThrow());
+ && this.metricExceptions.contains(symbol.orElseThrow())
+ || sharesAnyElements(this.metricExceptions, u.getOtherNames());
}
/**
@@ -477,7 +520,48 @@ public final class Presenter {
* @param settingsFile file settings should be loaded from
* @since 2021-12-15
*/
- void loadSettings(Path settingsFile) {}
+ void loadSettings(Path settingsFile) {
+ try {
+ // read file line by line
+ final int lineNum = 0;
+ for (final String line : Files.readAllLines(settingsFile)) {
+ final int equalsIndex = line.indexOf('=');
+ if (equalsIndex == -1)
+ throw new IllegalStateException(
+ "Settings file is malformed at line " + lineNum);
+
+ final String param = line.substring(0, equalsIndex);
+ final String value = line.substring(equalsIndex + 1);
+
+ switch (param) {
+ // set manually to avoid the unnecessary saving of the non-manual
+ // methods
+ case "number_display_rule":
+ this.numberDisplayRule = StandardDisplayRules
+ .getStandardRule(value);
+ break;
+ case "prefix_rule":
+ this.prefixRepetitionRule = DefaultPrefixRepetitionRule
+ .valueOf(value);
+ this.database.setPrefixRepetitionRule(this.prefixRepetitionRule);
+ break;
+ case "one_way":
+ this.oneWayConversionEnabled = Boolean.valueOf(value);
+ break;
+ case "include_duplicates":
+ this.showDuplicates = Boolean.valueOf(value);
+ break;
+ default:
+ System.err.printf("Warning: unrecognized setting \"%s\".%n",
+ param);
+ break;
+ }
+ }
+ if (this.view.getPresenter() != null) {
+ this.updateView();
+ }
+ } catch (final IOException e) {}
+ }
/**
* @return true iff the One-Way Conversion feature is available (views that
@@ -520,12 +604,37 @@ public final class Presenter {
}
/**
+ * Saves the presenter's current settings to its default filepath.
+ *
+ * @since 2022-04-19
+ */
+ public void saveSettings() {
+ this.saveSettings(DEFAULT_SETTINGS_FILEPATH);
+ }
+
+ /**
* Saves the presenter's settings to the user settings file.
*
* @param settingsFile file settings should be saved to
* @since 2021-12-15
*/
- void saveSettings(Path settingsFile) {}
+ void saveSettings(Path settingsFile) {
+ try (BufferedWriter writer = Files.newBufferedWriter(settingsFile)) {
+ writer.write(String.format("number_display_rule=%s\n",
+ this.numberDisplayRule));
+ writer.write(
+ String.format("prefix_rule=%s\n", this.prefixRepetitionRule));
+ writer.write(
+ String.format("one_way=%s\n", this.oneWayConversionEnabled));
+ writer.write(
+ String.format("include_duplicates=%s\n", this.showDuplicates));
+ } catch (final IOException e) {
+ e.printStackTrace();
+ this.view.showErrorMessage("I/O Error",
+ "Error occurred while saving settings: "
+ + e.getLocalizedMessage());
+ }
+ }
/**
* @param numberDisplayRule the new rule that will be used by this presenter
@@ -560,6 +669,17 @@ public final class Presenter {
}
/**
+ * @param prefixRepetitionRule the rule that determines whether a set of
+ * prefixes is valid
+ * @since 2022-04-19
+ */
+ public void setPrefixRepetitionRule(
+ Predicate<List<UnitPrefix>> prefixRepetitionRule) {
+ this.prefixRepetitionRule = prefixRepetitionRule;
+ this.database.setPrefixRepetitionRule(prefixRepetitionRule);
+ }
+
+ /**
* @param showDuplicateUnits whether or not duplicate units should be shown
* @since 2022-03-30
*/
@@ -608,9 +728,7 @@ public final class Presenter {
public void updateView() {
if (this.view instanceof UnitConversionView) {
final UnitConversionView ucview = (UnitConversionView) this.view;
- final ObjectProduct<BaseDimension> viewDimension = this.database
- .getDimension(((UnitConversionView) this.view)
- .getSelectedDimensionName().orElseThrow());
+ final var selectedDimensionName = ucview.getSelectedDimensionName();
// load units & prefixes into viewers
this.view.setViewableUnitNames(
@@ -619,29 +737,34 @@ public final class Presenter {
this.database.prefixMap(this.showDuplicates).keySet());
// get From and To units
- Stream<Unit> fromUnits = this.database
- .unitMapPrefixless(this.showDuplicates).entrySet().stream()
- .map(Map.Entry::getValue)
- .filter(u -> viewDimension.equals(u.getDimension()));
+ var fromUnits = this.database.unitMapPrefixless(this.showDuplicates)
+ .entrySet().stream();
+ var toUnits = this.database.unitMapPrefixless(this.showDuplicates)
+ .entrySet().stream();
- Stream<Unit> toUnits = this.database
- .unitMapPrefixless(this.showDuplicates).entrySet().stream()
- .map(Map.Entry::getValue)
- .filter(u -> viewDimension.equals(u.getDimension()));
+ // filter by dimension, if one is selected
+ if (selectedDimensionName.isPresent()) {
+ final var viewDimension = this.database
+ .getDimension(selectedDimensionName.orElseThrow());
+ fromUnits = fromUnits.filter(
+ u -> viewDimension.equals(u.getValue().getDimension()));
+ toUnits = toUnits.filter(
+ u -> viewDimension.equals(u.getValue().getDimension()));
+ }
// filter by unit type, if desired
if (this.oneWayConversionEnabled) {
- fromUnits = fromUnits.filter(u -> UnitType.getType(u,
+ fromUnits = fromUnits.filter(u -> UnitType.getType(u.getValue(),
this::isSemiMetric) != UnitType.METRIC);
- toUnits = toUnits.filter(u -> UnitType.getType(u,
+ toUnits = toUnits.filter(u -> UnitType.getType(u.getValue(),
this::isSemiMetric) != UnitType.NON_METRIC);
}
// set unit names
ucview.setFromUnitNames(
- fromUnits.map(Unit::getName).collect(Collectors.toSet()));
+ fromUnits.map(Map.Entry::getKey).collect(Collectors.toSet()));
ucview.setToUnitNames(
- toUnits.map(Unit::getName).collect(Collectors.toSet()));
+ toUnits.map(Map.Entry::getKey).collect(Collectors.toSet()));
}
}