summaryrefslogtreecommitdiff
path: root/src/main/java/sevenUnitsGUI
diff options
context:
space:
mode:
authorAdrien Hopkins <ahopk127@my.yorku.ca>2022-02-26 09:53:24 -0500
committerAdrien Hopkins <ahopk127@my.yorku.ca>2022-02-26 09:53:24 -0500
commit07c86e02be29aa3d3d878adce62c5c0a9a458e47 (patch)
treef7b13c71beed93f3af0919a2c835414252bf30c7 /src/main/java/sevenUnitsGUI
parentb7eee33a5b162b4057d04d28f45738e3048bf01d (diff)
Implemented unit conversion, with a few problems
TabbedView now displays its units, but with their toString method which shows their definition in addition to their name
Diffstat (limited to 'src/main/java/sevenUnitsGUI')
-rw-r--r--src/main/java/sevenUnitsGUI/Presenter.java202
-rw-r--r--src/main/java/sevenUnitsGUI/TabbedView.java14
-rw-r--r--src/main/java/sevenUnitsGUI/UnitConversionView.java3
-rw-r--r--src/main/java/sevenUnitsGUI/ViewBot.java7
4 files changed, 206 insertions, 20 deletions
diff --git a/src/main/java/sevenUnitsGUI/Presenter.java b/src/main/java/sevenUnitsGUI/Presenter.java
index 23a631d..be02364 100644
--- a/src/main/java/sevenUnitsGUI/Presenter.java
+++ b/src/main/java/sevenUnitsGUI/Presenter.java
@@ -19,17 +19,26 @@ package sevenUnitsGUI;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalDouble;
import java.util.Scanner;
+import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import sevenUnits.ProgramInfo;
import sevenUnits.unit.BaseDimension;
+import sevenUnits.unit.BritishImperial;
+import sevenUnits.unit.Metric;
import sevenUnits.unit.Unit;
import sevenUnits.unit.UnitDatabase;
import sevenUnits.unit.UnitPrefix;
+import sevenUnits.unit.UnitValue;
import sevenUnits.utils.ObjectProduct;
import sevenUnits.utils.UncertainDouble;
@@ -40,6 +49,44 @@ import sevenUnits.utils.UncertainDouble;
* @since 2021-12-15
*/
public final class Presenter {
+ /** The default place where settings are stored. */
+ private static final String DEFAULT_SETTINGS_FILEPATH = "settings.txt";
+ /** The default place where units are stored. */
+ private static final String DEFAULT_UNITS_FILEPATH = "/unitsfile.txt";
+ /** The default place where dimensions are stored. */
+ private static final String DEFAULT_DIMENSIONS_FILEPATH = "/dimensionfile.txt";
+ /** The default place where exceptions are stored. */
+ private static final String DEFAULT_EXCEPTIONS_FILEPATH = "/metric_exceptions.txt";
+
+ /**
+ * Adds default units and dimensions to a database.
+ *
+ * @param database database to add to
+ * @since 2019-04-14
+ * @since v0.2.0
+ */
+ private static void addDefaults(final UnitDatabase database) {
+ database.addUnit("metre", Metric.METRE);
+ database.addUnit("kilogram", Metric.KILOGRAM);
+ database.addUnit("gram", Metric.KILOGRAM.dividedBy(1000));
+ database.addUnit("second", Metric.SECOND);
+ database.addUnit("ampere", Metric.AMPERE);
+ database.addUnit("kelvin", Metric.KELVIN);
+ database.addUnit("mole", Metric.MOLE);
+ database.addUnit("candela", Metric.CANDELA);
+ database.addUnit("bit", Metric.BIT);
+ database.addUnit("unit", Metric.ONE);
+ // nonlinear units - must be loaded manually
+ database.addUnit("tempCelsius", Metric.CELSIUS);
+ database.addUnit("tempFahrenheit", BritishImperial.FAHRENHEIT);
+
+ // load initial dimensions
+ database.addDimension("LENGTH", Metric.Dimensions.LENGTH);
+ database.addDimension("MASS", Metric.Dimensions.MASS);
+ database.addDimension("TIME", Metric.Dimensions.TIME);
+ database.addDimension("TEMPERATURE", Metric.Dimensions.TEMPERATURE);
+ }
+
/**
* @return text in About file
* @since 2022-02-19
@@ -86,6 +133,25 @@ public final class Presenter {
}
/**
+ * Accepts a collection and returns a set with the unique elements in that
+ * collection
+ *
+ * @param <E> type of element in collection
+ * @param collection collection to uniquify
+ * @return unique collection
+ * @since 2022-02-26
+ */
+ private static <E> Set<E> unique(Collection<E> collection) {
+ final Set<E> uniqueSet = new HashSet<>();
+ for (final E e : collection) {
+ if (!uniqueSet.contains(e)) {
+ uniqueSet.add(e);
+ }
+ }
+ return uniqueSet;
+ }
+
+ /**
* @return {@code line} with any comments removed.
* @since 2021-03-13
*/
@@ -127,6 +193,13 @@ public final class Presenter {
private Predicate<List<UnitPrefix>> prefixRepetitionRule;
/**
+ * The set of units that is considered neither metric nor nonmetric for the
+ * purposes of the metric-imperial one-way conversion. These units are
+ * included in both From and To, even if One Way Conversion is enabled.
+ */
+ private final Set<String> metricExceptions;
+
+ /**
* If this is true, views that show units as a list will have metric units
* removed from the From unit list and imperial/USC units removed from the To
* unit list.
@@ -148,20 +221,43 @@ public final class Presenter {
public Presenter(View view) {
this.view = view;
this.database = new UnitDatabase();
+ addDefaults(this.database);
+
+ // load units and prefixes
+ try (final InputStream units = inputStream(DEFAULT_UNITS_FILEPATH)) {
+ this.database.loadUnitsFromStream(units);
+ } catch (final IOException e) {
+ throw new AssertionError("Loading of unitsfile.txt failed.", e);
+ }
+
+ // load dimensions
+ try (final InputStream dimensions = inputStream(
+ DEFAULT_DIMENSIONS_FILEPATH)) {
+ this.database.loadDimensionsFromStream(dimensions);
+ } catch (final IOException e) {
+ throw new AssertionError("Loading of dimensionfile.txt failed.", e);
+ }
+
+ // load metric exceptions
+ try {
+ this.metricExceptions = new HashSet<>();
+ try (InputStream exceptions = inputStream(DEFAULT_EXCEPTIONS_FILEPATH);
+ Scanner scanner = new Scanner(exceptions)) {
+ while (scanner.hasNextLine()) {
+ final String line = Presenter
+ .withoutComments(scanner.nextLine());
+ if (!line.isBlank()) {
+ this.metricExceptions.add(line);
+ }
+ }
+ }
+ } catch (final IOException e) {
+ throw new AssertionError("Loading of metric_exceptions.txt failed.",
+ e);
+ }
}
/**
- * Sets the dimension of the view's From and To units.
- *
- * @throws UnsupportedOperationException if the view does not support
- * unit-based conversion (does not
- * implement
- * {@link UnitConversionView})
- * @since 2021-12-15
- */
- public void applyDimensionFilter() {}
-
- /**
* Gets settings from the view and applies them to both view and presenter.
*
* @since 2021-12-15
@@ -190,7 +286,52 @@ public final class Presenter {
* {@link UnitConversionView})
* @since 2021-12-15
*/
- public void convertUnits() {}
+ public void convertUnits() {
+ if (this.view instanceof UnitConversionView) {
+ final UnitConversionView ucview = (UnitConversionView) this.view;
+
+ final Optional<Unit> fromUnitOptional = ucview.getFromSelection();
+ final Optional<Unit> toUnitOptional = ucview.getToSelection();
+ final OptionalDouble valueOptional = ucview.getInputValue();
+
+ // ensure everything is obtained
+ final Unit fromUnit, toUnit;
+ final double value;
+ if (fromUnitOptional.isPresent()) {
+ fromUnit = fromUnitOptional.orElseThrow();
+ } else {
+ this.view.showErrorMessage("Unit Conversion Error",
+ "Please specify a From unit");
+ return;
+ }
+ if (toUnitOptional.isPresent()) {
+ toUnit = toUnitOptional.orElseThrow();
+ } else {
+ this.view.showErrorMessage("Unit Conversion Error",
+ "Please specify a To unit");
+ return;
+ }
+ if (valueOptional.isPresent()) {
+ value = valueOptional.orElseThrow();
+ } else {
+ this.view.showErrorMessage("Unit Conversion Error",
+ "Please specify a valid value");
+ return;
+ }
+
+ if (!fromUnit.canConvertTo(toUnit))
+ throw new AssertionError(
+ "From and To units incompatible (should be impossible)");
+
+ // convert!
+ final UnitValue initialValue = UnitValue.of(fromUnit, value);
+ final UnitValue converted = initialValue.convertTo(toUnit);
+ ucview.showUnitConversionOutput(
+ String.format("%s = %s", initialValue, converted));
+ } else
+ throw new UnsupportedOperationException(
+ "This function can only be called when the view is a UnitConversionView.");
+ }
/**
* Loads settings from the user's settings file and applies them to the view.
@@ -199,6 +340,21 @@ public final class Presenter {
*/
public void loadSettings() {}
+ /**
+ * Completes creation of the presenter. This part of the initialization
+ * depends on the view's functions, so it cannot be run if the components
+ * they depend on are not created yet.
+ *
+ * @since 2022-02-26
+ */
+ public void postViewInitialize() {
+ // unit conversion specific stuff
+ if (this.view instanceof UnitConversionView) {
+ final UnitConversionView ucview = (UnitConversionView) this.view;
+ ucview.setDimensions(unique(this.database.dimensionMap().values()));
+ }
+ }
+
void prefixSelected() {}
/**
@@ -227,4 +383,26 @@ public final class Presenter {
}
void unitNameSelected() {}
+
+ /**
+ * Updates the view's From and To units, if it has some
+ *
+ * @since 2021-12-15
+ */
+ public void updateView() {
+ if (this.view instanceof UnitConversionView) {
+ final UnitConversionView ucview = (UnitConversionView) this.view;
+ final ObjectProduct<BaseDimension> viewDimension = ucview
+ .getSelectedDimension().orElseThrow();
+
+ final Set<Unit> units = this.database
+ .unitMapPrefixless(this.showDuplicateUnits).entrySet().stream()
+ .map(Map.Entry::getValue)
+ .filter(u -> viewDimension.equals(u.getDimension()))
+ .collect(Collectors.toSet());
+
+ ucview.setFromUnits(units);
+ ucview.setToUnits(units);
+ }
+ }
}
diff --git a/src/main/java/sevenUnitsGUI/TabbedView.java b/src/main/java/sevenUnitsGUI/TabbedView.java
index e92b661..c3a05e2 100644
--- a/src/main/java/sevenUnitsGUI/TabbedView.java
+++ b/src/main/java/sevenUnitsGUI/TabbedView.java
@@ -28,6 +28,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Optional;
+import java.util.OptionalDouble;
import java.util.Set;
import javax.swing.BorderFactory;
@@ -212,7 +213,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
this.dimensionSelector = new JComboBox<>();
inBetweenPanel.add(this.dimensionSelector, BorderLayout.PAGE_START);
this.dimensionSelector
- .addItemListener(e -> this.presenter.applyDimensionFilter());
+ .addItemListener(e -> this.presenter.updateView());
final JLabel arrowLabel = new JLabel("-->");
inBetweenPanel.add(arrowLabel, BorderLayout.CENTER);
@@ -326,9 +327,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
this.masterPane.setMnemonicAt(5, KeyEvent.VK_S);
// ============ FINALIZE CREATION OF VIEW ============
+ this.presenter.postViewInitialize();
this.frame.pack();
this.frame.setVisible(true);
-
}
/**
@@ -541,8 +542,13 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView {
}
@Override
- public String getInputValue() {
- return this.valueInput.getText();
+ public OptionalDouble getInputValue() {
+ final String text = this.valueInput.getText();
+ try {
+ return OptionalDouble.of(Double.parseDouble(text));
+ } catch (final NumberFormatException e) {
+ return OptionalDouble.empty();
+ }
}
@Override
diff --git a/src/main/java/sevenUnitsGUI/UnitConversionView.java b/src/main/java/sevenUnitsGUI/UnitConversionView.java
index 5fd5a82..e411a44 100644
--- a/src/main/java/sevenUnitsGUI/UnitConversionView.java
+++ b/src/main/java/sevenUnitsGUI/UnitConversionView.java
@@ -17,6 +17,7 @@
package sevenUnitsGUI;
import java.util.Optional;
+import java.util.OptionalDouble;
import java.util.Set;
import sevenUnits.unit.BaseDimension;
@@ -48,7 +49,7 @@ public interface UnitConversionView extends View {
* string provided by the user)
* @since 2021-12-15
*/
- String getInputValue();
+ OptionalDouble getInputValue();
/**
* @return selected dimension
diff --git a/src/main/java/sevenUnitsGUI/ViewBot.java b/src/main/java/sevenUnitsGUI/ViewBot.java
index 0c0d189..bc5302b 100644
--- a/src/main/java/sevenUnitsGUI/ViewBot.java
+++ b/src/main/java/sevenUnitsGUI/ViewBot.java
@@ -20,6 +20,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
+import java.util.OptionalDouble;
import java.util.Set;
import sevenUnits.unit.BaseDimension;
@@ -47,7 +48,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView {
/**
* The user-provided string representing the value in {@code fromSelection}
*/
- private String inputValue;
+ private OptionalDouble inputValue;
/** The unit selected in the From selection */
private Optional<Unit> fromSelection;
/** The unit selected in the To selection */
@@ -102,7 +103,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView {
}
@Override
- public String getInputValue() {
+ public OptionalDouble getInputValue() {
return this.inputValue;
}
@@ -190,7 +191,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView {
* @param inputValue the inputValue to set
* @since 2022-01-29
*/
- public void setInputValue(String inputValue) {
+ public void setInputValue(OptionalDouble inputValue) {
this.inputValue = inputValue;
}