diff options
author | Adrien Hopkins <ahopk127@my.yorku.ca> | 2022-04-09 11:32:43 -0500 |
---|---|---|
committer | Adrien Hopkins <ahopk127@my.yorku.ca> | 2022-04-09 11:32:43 -0500 |
commit | c421e474a7b0d0d453e4a527907f327f2ddef320 (patch) | |
tree | 1edf5930488ad18f318a05dcfa3aa4824f5e22ca /src | |
parent | 91f87da88f98de996e167f0ff6809356f6d57e11 (diff) |
View now sends and recieves Strings instead of data
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/sevenUnitsGUI/ExpressionConversionView.java | 7 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/Presenter.java | 153 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/SearchBoxList.java | 10 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/TabbedView.java | 76 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/UnitConversionRecord.java | 180 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/UnitConversionView.java | 47 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/View.java | 2 | ||||
-rw-r--r-- | src/main/java/sevenUnitsGUI/ViewBot.java | 141 | ||||
-rw-r--r-- | src/test/java/sevenUnitsGUI/PresenterTest.java | 85 |
9 files changed, 460 insertions, 241 deletions
diff --git a/src/main/java/sevenUnitsGUI/ExpressionConversionView.java b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java index 5a587d4..872ca10 100644 --- a/src/main/java/sevenUnitsGUI/ExpressionConversionView.java +++ b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java @@ -38,11 +38,8 @@ public interface ExpressionConversionView extends View { /** * Shows the output of an expression conversion to the user. * - * @param fromExpression expression converted from - * @param toExpression expression converted to - * @param value conversion factor between two expressions + * @param uc unit conversion to show * @since 2021-12-15 */ - void showExpressionConversionOutput(String fromExpression, - String toExpression, double value); + void showExpressionConversionOutput(UnitConversionRecord uc); } diff --git a/src/main/java/sevenUnitsGUI/Presenter.java b/src/main/java/sevenUnitsGUI/Presenter.java index 57d353d..9f8fe69 100644 --- a/src/main/java/sevenUnitsGUI/Presenter.java +++ b/src/main/java/sevenUnitsGUI/Presenter.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2021 Adrien Hopkins + * Copyright (C) 2021-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 @@ -19,13 +19,11 @@ 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.NoSuchElementException; import java.util.Optional; -import java.util.OptionalDouble; import java.util.Scanner; import java.util.Set; import java.util.function.Function; @@ -135,25 +133,6 @@ 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 */ @@ -206,7 +185,7 @@ public final class Presenter { * removed from the From unit list and imperial/USC units removed from the To * unit list. */ - private boolean oneWayConversion; + private boolean oneWayConversionEnabled; /** * If this is false, duplicate units will be removed from the unit view in @@ -260,13 +239,6 @@ public final class Presenter { } /** - * Gets settings from the view and applies them to both view and presenter. - * - * @since 2021-12-15 - */ - public void applySettings() {} - - /** * Converts from the view's input expression to its output expression. * Displays an error message if any of the required fields are invalid. * @@ -316,8 +288,9 @@ public final class Presenter { // convert and show output if (from.getUnit().canConvertTo(to)) { final double value = from.asUnitValue().convertTo(to).getValue(); - xcview.showExpressionConversionOutput(fromExpression, toExpression, - value); + final UnitConversionRecord uc = UnitConversionRecord.valueOf( + fromExpression, toExpression, "", String.valueOf(value)); + xcview.showExpressionConversionOutput(uc); } else { this.view.showErrorMessage("Conversion Error", "Cannot convert between \"" + fromExpression + "\" and \"" @@ -343,49 +316,82 @@ public final class Presenter { 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(); + final Optional<String> fromUnitOptional = ucview.getFromSelection(); + final Optional<String> toUnitOptional = ucview.getToSelection(); + final String valueString = ucview.getInputValue(); - // ensure everything is obtained - final Unit fromUnit, toUnit; - final double value; + // extract values from optionals + final String fromUnitString, toUnitString; if (fromUnitOptional.isPresent()) { - fromUnit = fromUnitOptional.orElseThrow(); + fromUnitString = fromUnitOptional.orElseThrow(); } else { - this.view.showErrorMessage("Unit Conversion Error", + this.view.showErrorMessage("Unit Selection Error", "Please specify a From unit"); return; } if (toUnitOptional.isPresent()) { - toUnit = toUnitOptional.orElseThrow(); + toUnitString = toUnitOptional.orElseThrow(); } else { - this.view.showErrorMessage("Unit Conversion Error", + this.view.showErrorMessage("Unit Selection 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"); + + // convert strings to data, checking if anything is invalid + final Unit fromUnit, toUnit; + final double value; + + if (this.database.containsUnitName(fromUnitString)) { + fromUnit = this.database.getUnit(fromUnitString); + } else + throw this.viewError("Nonexistent From unit: %s", fromUnitString); + if (this.database.containsUnitName(toUnitString)) { + toUnit = this.database.getUnit(toUnitString); + } else + throw this.viewError("Nonexistent To unit: %s", toUnitString); + try { + value = Double.parseDouble(valueString); + } catch (final NumberFormatException e) { + this.view.showErrorMessage("Value Error", + "Invalid value " + valueString); return; } if (!fromUnit.canConvertTo(toUnit)) - throw new AssertionError( - "From and To units incompatible (should be impossible)"); + throw this.viewError("Could not convert between %s and %s", + fromUnit, toUnit); // convert! final UnitValue initialValue = UnitValue.of(fromUnit, value); final UnitValue converted = initialValue.convertTo(toUnit); - ucview.showUnitConversionOutput(initialValue, converted); + + ucview.showUnitConversionOutput( + UnitConversionRecord.fromValues(initialValue, converted)); } else throw new UnsupportedOperationException( "This function can only be called when the view is a UnitConversionView."); } /** + * @return true iff duplicate units are shown in unit lists + * @since 2022-03-30 + */ + public boolean duplicateUnitsShown() { + return this.showDuplicateUnits; + } + + /** + * @return true iff the One-Way Conversion feature is available (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) + * + * @since 2022-03-30 + */ + public boolean isOneWayConversionEnabled() { + return this.oneWayConversionEnabled; + } + + /** * Loads settings from the user's settings file and applies them to the view. * * @since 2021-12-15 @@ -403,7 +409,7 @@ public final class Presenter { // unit conversion specific stuff if (this.view instanceof UnitConversionView) { final UnitConversionView ucview = (UnitConversionView) this.view; - ucview.setDimensions(unique(this.database.dimensionMap().values())); + ucview.setDimensionNames(this.database.dimensionMap().keySet()); } } @@ -417,6 +423,26 @@ public final class Presenter { */ public void saveSettings() {} + /** + * @param oneWayConversionEnabled whether not one-way conversion should be + * enabled + * @since 2022-03-30 + * @see {@link #isOneWayConversionEnabled} + */ + public void setOneWayConversionEnabled(boolean oneWayConversionEnabled) { + this.oneWayConversionEnabled = oneWayConversionEnabled; + this.updateView(); + } + + /** + * @param showDuplicateUnits whether or not duplicate units should be shown + * @since 2022-03-30 + */ + public void setShowDuplicateUnits(boolean showDuplicateUnits) { + this.showDuplicateUnits = showDuplicateUnits; + this.updateView(); + } + void unitNameSelected() {} /** @@ -427,17 +453,30 @@ public final class Presenter { public void updateView() { if (this.view instanceof UnitConversionView) { final UnitConversionView ucview = (UnitConversionView) this.view; - final ObjectProduct<BaseDimension> viewDimension = ucview - .getSelectedDimension().orElseThrow(); + final ObjectProduct<BaseDimension> viewDimension = this.database + .getDimension(((UnitConversionView) this.view) + .getSelectedDimensionName().orElseThrow()); - final Set<Unit> units = this.database + final Set<String> units = this.database .unitMapPrefixless(this.showDuplicateUnits).entrySet().stream() .map(Map.Entry::getValue) .filter(u -> viewDimension.equals(u.getDimension())) - .collect(Collectors.toSet()); + .map(Unit::getName).collect(Collectors.toSet()); - ucview.setFromUnits(units); - ucview.setToUnits(units); + ucview.setFromUnitNames(units); + ucview.setToUnitNames(units); } } + + /** + * @param message message to add + * @param args string formatting arguments for message + * @return AssertionError stating that an error has happened in the view's + * code + * @since 2022-04-09 + */ + private AssertionError viewError(String message, Object... args) { + return new AssertionError("View Programming Error (from " + this.view + + "): " + String.format(message, args)); + } } diff --git a/src/main/java/sevenUnitsGUI/SearchBoxList.java b/src/main/java/sevenUnitsGUI/SearchBoxList.java index 2b935d0..9b41601 100644 --- a/src/main/java/sevenUnitsGUI/SearchBoxList.java +++ b/src/main/java/sevenUnitsGUI/SearchBoxList.java @@ -22,6 +22,7 @@ import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Optional; @@ -166,6 +167,15 @@ final class SearchBoxList<E> extends JPanel { } /** + * @return items available in search list, including items that are hidden by + * the search filter + * @since 2022-03-30 + */ + public Collection<E> getItems() { + return Collections.unmodifiableCollection(this.itemsToFilter); + } + + /** * @return this component's search box component * @since 2019-04-14 * @since v0.2.0 diff --git a/src/main/java/sevenUnitsGUI/TabbedView.java b/src/main/java/sevenUnitsGUI/TabbedView.java index 0461cb6..ed45011 100644 --- a/src/main/java/sevenUnitsGUI/TabbedView.java +++ b/src/main/java/sevenUnitsGUI/TabbedView.java @@ -23,13 +23,12 @@ import java.awt.GridLayout; import java.awt.event.KeyEvent; import java.text.DecimalFormat; import java.text.NumberFormat; -import java.text.ParseException; import java.util.AbstractSet; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Optional; -import java.util.OptionalDouble; import java.util.Set; import javax.swing.BorderFactory; @@ -57,12 +56,6 @@ import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import sevenUnits.ProgramInfo; -import sevenUnits.unit.BaseDimension; -import sevenUnits.unit.Unit; -import sevenUnits.unit.UnitPrefix; -import sevenUnits.unit.UnitValue; -import sevenUnits.utils.NamedObjectProduct; -import sevenUnits.utils.ObjectProduct; /** * A View that separates its functions into multiple tabs @@ -140,13 +133,13 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { // DIMENSION-BASED CONVERTER /** The combo box that selects dimensions */ - private final JComboBox<NamedObjectProduct<BaseDimension>> dimensionSelector; + private final JComboBox<String> dimensionSelector; /** The panel for inputting values in the dimension-based converter */ private final JFormattedTextField valueInput; /** The panel for "From" in the dimension-based converter */ - private final SearchBoxList<Unit> fromSearch; + private final SearchBoxList<String> fromSearch; /** The panel for "To" in the dimension-based converter */ - private final SearchBoxList<Unit> toSearch; + private final SearchBoxList<String> toSearch; /** The output area in the dimension-based converter */ private final JTextArea unitOutput; @@ -160,9 +153,9 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { // UNIT AND PREFIX VIEWERS /** The searchable list of unit names in the unit viewer */ - private final SearchBoxList<Unit> unitNameList; + private final SearchBoxList<String> unitNameList; /** The searchable list of prefix names in the prefix viewer */ - private final SearchBoxList<UnitPrefix> prefixNameList; + private final SearchBoxList<String> prefixNameList; /** The text box for unit data in the unit viewer */ private final JTextArea unitTextBox; /** The text box for prefix data in the prefix viewer */ @@ -528,7 +521,7 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { } @Override - public Set<NamedObjectProduct<BaseDimension>> getDimensions() { + public Set<String> getDimensionNames() { return Collections .unmodifiableSet(new JComboBoxItemSet<>(this.dimensionSelector)); } @@ -539,27 +532,25 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { } @Override - public Optional<Unit> getFromSelection() { + public Optional<String> getFromSelection() { return this.fromSearch.getSelectedValue(); } @Override - public OptionalDouble getInputValue() { - try { - this.valueInput.commitEdit(); - } catch (final ParseException e) { - return OptionalDouble.empty(); - } - return OptionalDouble - .of(((Number) this.valueInput.getValue()).doubleValue()); + public Set<String> getFromUnitNames() { + // this should work because the only way I can mutate the item list is + // with setFromUnits which only accepts a Set + return new HashSet<>(this.fromSearch.getItems()); + } + + @Override + public String getInputValue() { + return this.valueInput.getText(); } @Override - public Optional<? extends ObjectProduct<BaseDimension>> getSelectedDimension() { - // this must work because this function can only return items that are in - // the selector, which are all of type ObjectProduct<BaseDimension> - @SuppressWarnings("unchecked") - final ObjectProduct<BaseDimension> selectedItem = (ObjectProduct<BaseDimension>) this.dimensionSelector + public Optional<String> getSelectedDimensionName() { + final String selectedItem = (String) this.dimensionSelector .getSelectedItem(); return Optional.ofNullable(selectedItem); } @@ -570,26 +561,32 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { } @Override - public Optional<Unit> getToSelection() { + public Optional<String> getToSelection() { return this.toSearch.getSelectedValue(); } @Override - public void setDimensions( - Set<NamedObjectProduct<BaseDimension>> dimensions) { + public Set<String> getToUnitNames() { + // this should work because the only way I can mutate the item list is + // with setToUnits which only accepts a Set + return new HashSet<>(this.toSearch.getItems()); + } + + @Override + public void setDimensionNames(Set<String> dimensionNames) { this.dimensionSelector.removeAllItems(); - for (final NamedObjectProduct<BaseDimension> d : dimensions) { + for (final String d : dimensionNames) { this.dimensionSelector.addItem(d); } } @Override - public void setFromUnits(Set<? extends Unit> units) { + public void setFromUnitNames(Set<String> units) { this.fromSearch.setItems(units); } @Override - public void setToUnits(Set<? extends Unit> units) { + public void setToUnitNames(Set<String> units) { this.toSearch.setItems(units); } @@ -600,15 +597,14 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { } @Override - public void showExpressionConversionOutput(String fromExpression, - String toExpression, double value) { - this.expressionOutput.setText( - String.format("%s = %s %s", fromExpression, value, toExpression)); + public void showExpressionConversionOutput(UnitConversionRecord uc) { + this.expressionOutput.setText(String.format("%s = %s %s", uc.fromName(), + uc.outputValueString(), uc.toName())); } @Override - public void showUnitConversionOutput(UnitValue input, UnitValue output) { - this.unitOutput.setText(input + " = " + output); + public void showUnitConversionOutput(UnitConversionRecord uc) { + this.unitOutput.setText(uc.toString()); } } diff --git a/src/main/java/sevenUnitsGUI/UnitConversionRecord.java b/src/main/java/sevenUnitsGUI/UnitConversionRecord.java new file mode 100644 index 0000000..60675e2 --- /dev/null +++ b/src/main/java/sevenUnitsGUI/UnitConversionRecord.java @@ -0,0 +1,180 @@ +/** + * 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 sevenUnits.unit.UnitValue; + +/** + * A record of a conversion between units or expressions + * + * @since 2022-04-09 + */ +public final class UnitConversionRecord { + /** + * Gets a {@code UnitConversionRecord} from two unit values + * + * @param input input unit & value + * @param output output unit & value + * @return unit conversion record + * @since 2022-04-09 + */ + public static UnitConversionRecord fromValues(UnitValue input, + UnitValue output) { + return UnitConversionRecord.valueOf(input.getUnit().getName(), + output.getUnit().getName(), String.valueOf(input.getValue()), + String.valueOf(output.getValue())); + } + + /** + * Gets a {@code UnitConversionRecord} + * + * @param fromName name of unit or expression that was converted + * from + * @param toName name of unit or expression that was converted to + * @param inputValueString string representing input value + * @param outputValueString string representing output value + * @return unit conversion record + * @since 2022-04-09 + */ + public static UnitConversionRecord valueOf(String fromName, String toName, + String inputValueString, String outputValueString) { + return new UnitConversionRecord(fromName, toName, inputValueString, + outputValueString); + } + + /** + * The name of the unit or expression that was converted from + */ + private final String fromName; + /** + * The name of the unit or expression that was converted to + */ + private final String toName; + + /** + * A string representing the input value. It doesn't need to be the same as + * the input value's string representation; it could be rounded, for example. + */ + private final String inputValueString; + /** + * A string representing the input value. It doesn't need to be the same as + * the input value's string representation; it could be rounded, for example. + */ + private final String outputValueString; + + /** + * @param fromName name of unit or expression that was converted + * from + * @param toName name of unit or expression that was converted to + * @param inputValueString string representing input value + * @param outputValueString string representing output value + * @since 2022-04-09 + */ + private UnitConversionRecord(String fromName, String toName, + String inputValueString, String outputValueString) { + this.fromName = fromName; + this.toName = toName; + this.inputValueString = inputValueString; + this.outputValueString = outputValueString; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof UnitConversionRecord)) + return false; + final UnitConversionRecord other = (UnitConversionRecord) obj; + if (this.fromName == null) { + if (other.fromName != null) + return false; + } else if (!this.fromName.equals(other.fromName)) + return false; + if (this.inputValueString == null) { + if (other.inputValueString != null) + return false; + } else if (!this.inputValueString.equals(other.inputValueString)) + return false; + if (this.outputValueString == null) { + if (other.outputValueString != null) + return false; + } else if (!this.outputValueString.equals(other.outputValueString)) + return false; + if (this.toName == null) { + if (other.toName != null) + return false; + } else if (!this.toName.equals(other.toName)) + return false; + return true; + } + + /** + * @return name of unit or expression that was converted from + * @since 2022-04-09 + */ + public String fromName() { + return this.fromName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + (this.fromName == null ? 0 : this.fromName.hashCode()); + result = prime * result + (this.inputValueString == null ? 0 + : this.inputValueString.hashCode()); + result = prime * result + (this.outputValueString == null ? 0 + : this.outputValueString.hashCode()); + result = prime * result + + (this.toName == null ? 0 : this.toName.hashCode()); + return result; + } + + /** + * @return string representing input value + * @since 2022-04-09 + */ + public String inputValueString() { + return this.inputValueString; + } + + /** + * @return string representing output value + * @since 2022-04-09 + */ + public String outputValueString() { + return this.outputValueString; + } + + /** + * @return name of unit or expression that was converted to + * @since 2022-04-09 + */ + public String toName() { + return this.toName; + } + + @Override + public String toString() { + final String inputString = this.inputValueString.isBlank() ? this.fromName + : this.inputValueString + " " + this.fromName; + final String outputString = this.outputValueString.isBlank() ? this.toName + : this.outputValueString + " " + this.toName; + return inputString + " = " + outputString; + } +} diff --git a/src/main/java/sevenUnitsGUI/UnitConversionView.java b/src/main/java/sevenUnitsGUI/UnitConversionView.java index 67d3ddc..9d3a67b 100644 --- a/src/main/java/sevenUnitsGUI/UnitConversionView.java +++ b/src/main/java/sevenUnitsGUI/UnitConversionView.java @@ -17,15 +17,8 @@ package sevenUnitsGUI; import java.util.Optional; -import java.util.OptionalDouble; import java.util.Set; -import sevenUnits.unit.BaseDimension; -import sevenUnits.unit.Unit; -import sevenUnits.unit.UnitValue; -import sevenUnits.utils.NamedObjectProduct; -import sevenUnits.utils.ObjectProduct; - /** * A View that supports single unit-based conversion * @@ -37,60 +30,72 @@ public interface UnitConversionView extends View { * @return dimensions available for filtering * @since 2022-01-29 */ - Set<NamedObjectProduct<BaseDimension>> getDimensions(); + Set<String> getDimensionNames(); /** - * @return unit to convert <em>from</em> + * @return name of unit to convert <em>from</em> * @since 2021-12-15 */ - Optional<Unit> getFromSelection(); + Optional<String> getFromSelection(); + + /** + * @return list of names of units available to convert from + * @since 2022-03-30 + */ + Set<String> getFromUnitNames(); /** * @return value to convert between the units (specifically, the numeric * string provided by the user) * @since 2021-12-15 */ - OptionalDouble getInputValue(); + String getInputValue(); /** * @return selected dimension * @since 2021-12-15 */ - Optional<? extends ObjectProduct<BaseDimension>> getSelectedDimension(); + Optional<String> getSelectedDimensionName(); /** - * @return unit to convert <em>to</em> + * @return name of unit to convert <em>to</em> * @since 2021-12-15 */ - Optional<Unit> getToSelection(); + Optional<String> getToSelection(); + + /** + * @return list of names of units available to convert to + * @since 2022-03-30 + */ + Set<String> getToUnitNames(); /** * Sets the available dimensions for filtering. * - * @param dimensions dimensions to use + * @param dimensionNames names of dimensions to use * @since 2021-12-15 */ - void setDimensions(Set<NamedObjectProduct<BaseDimension>> dimensions); + void setDimensionNames(Set<String> dimensionNames); /** * Sets the available units to convert from. {@link #getFromSelection} is not * required to use one of these units; this method is to be used for views * that allow the user to select units from a list. * - * @param units units to convert from + * @param unitNames names of units to convert from * @since 2021-12-15 */ - void setFromUnits(Set<? extends Unit> units); + void setFromUnitNames(Set<String> unitNames); /** * Sets the available units to convert to. {@link #getToSelection} is not * required to use one of these units; this method is to be used for views * that allow the user to select units from a list. * - * @param units units to convert to + * @param unitNames names of units to convert to * @since 2021-12-15 */ - void setToUnits(Set<? extends Unit> units); + void setToUnitNames(Set<String> unitNames); /** * Shows the output of a unit conversion. @@ -99,5 +104,5 @@ public interface UnitConversionView extends View { * @param output output unit & value * @since 2021-12-24 */ - void showUnitConversionOutput(UnitValue input, UnitValue output); + void showUnitConversionOutput(UnitConversionRecord uc); } diff --git a/src/main/java/sevenUnitsGUI/View.java b/src/main/java/sevenUnitsGUI/View.java index a93c76a..e78c9cc 100644 --- a/src/main/java/sevenUnitsGUI/View.java +++ b/src/main/java/sevenUnitsGUI/View.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2021 Adrien Hopkins + * Copyright (C) 2021-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 diff --git a/src/main/java/sevenUnitsGUI/ViewBot.java b/src/main/java/sevenUnitsGUI/ViewBot.java index 43d73bb..0195dd6 100644 --- a/src/main/java/sevenUnitsGUI/ViewBot.java +++ b/src/main/java/sevenUnitsGUI/ViewBot.java @@ -21,15 +21,8 @@ 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; -import sevenUnits.unit.Unit; -import sevenUnits.unit.UnitValue; -import sevenUnits.utils.NamedObjectProduct; -import sevenUnits.utils.ObjectProduct; - /** * A class that simulates a View (supports both unit and expression conversion) * for testing. Getters and setters work as expected. @@ -42,7 +35,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { private final Presenter presenter; /** The dimensions available to select from */ - private Set<NamedObjectProduct<BaseDimension>> dimensions; + private Set<String> dimensionNames; /** The expression in the From field */ private String fromExpression; /** The expression in the To field */ @@ -50,23 +43,22 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { /** * The user-provided string representing the value in {@code fromSelection} */ - private OptionalDouble inputValue; + private String inputValue; /** The unit selected in the From selection */ - private Optional<Unit> fromSelection; + private Optional<String> fromSelection; /** The unit selected in the To selection */ - private Optional<Unit> toSelection; + private Optional<String> toSelection; /** The currently selected dimension */ - private Optional<? extends ObjectProduct<BaseDimension>> selectedDimension; + private Optional<String> selectedDimensionName; /** The units available in the From selection */ - private Set<? extends Unit> fromUnits; + private Set<String> fromUnits; /** The units available in the To selection */ - private Set<? extends Unit> toUnits; - /** Saved input values of all unit conversions */ - private final List<UnitValue> unitConversionInputValues; - /** Saved output values of all unit conversions */ - private final List<UnitValue> unitConversionOutputValues; + private Set<String> toUnits; + + /** Saved outputs of all unit conversions */ + private final List<UnitConversionRecord> unitConversions; /** Saved outputs of all unit expressions */ - private final List<String> expressionConversionOutputs; + private final List<UnitConversionRecord> expressionConversions; /** * Creates a new {@code ViewBot} with a new presenter. @@ -76,9 +68,16 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { public ViewBot() { this.presenter = new Presenter(this); - this.unitConversionInputValues = new ArrayList<>(); - this.unitConversionOutputValues = new ArrayList<>(); - this.expressionConversionOutputs = new ArrayList<>(); + this.unitConversions = new ArrayList<>(); + this.expressionConversions = new ArrayList<>(); + } + + /** + * @return list of records of expression conversions done by this bot + * @since 2022-04-09 + */ + public List<UnitConversionRecord> expressionConversionList() { + return this.expressionConversions; } /** @@ -86,12 +85,8 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @since 2022-01-29 */ @Override - public Set<NamedObjectProduct<BaseDimension>> getDimensions() { - return this.dimensions; - } - - public List<String> getExpressionConversionOutputs() { - return this.expressionConversionOutputs; + public Set<String> getDimensionNames() { + return this.dimensionNames; } @Override @@ -100,7 +95,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { } @Override - public Optional<Unit> getFromSelection() { + public Optional<String> getFromSelection() { return this.fromSelection; } @@ -108,12 +103,13 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @return the units available for selection in From * @since 2022-01-29 */ - public Set<Unit> getFromUnits() { + @Override + public Set<String> getFromUnitNames() { return Collections.unmodifiableSet(this.fromUnits); } @Override - public OptionalDouble getInputValue() { + public String getInputValue() { return this.inputValue; } @@ -126,8 +122,8 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { } @Override - public Optional<ObjectProduct<BaseDimension>> getSelectedDimension() { - return this.selectedDimension.map(x -> x); + public Optional<String> getSelectedDimensionName() { + return this.selectedDimensionName; } @Override @@ -136,7 +132,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { } @Override - public Optional<Unit> getToSelection() { + public Optional<String> getToSelection() { return this.toSelection; } @@ -144,30 +140,14 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @return the units available for selection in To * @since 2022-01-29 */ - public Set<Unit> getToUnits() { + @Override + public Set<String> getToUnitNames() { return Collections.unmodifiableSet(this.toUnits); } - /** - * @return the unitConversionInputValues - * @since 2022-02-26 - */ - public List<UnitValue> getUnitConversionInputValues() { - return this.unitConversionInputValues; - } - - /** - * @return the unitConversionOutputValues - * @since 2022-02-10 - */ - public List<UnitValue> getUnitConversionOutputValues() { - return this.unitConversionOutputValues; - } - @Override - public void setDimensions( - Set<NamedObjectProduct<BaseDimension>> dimensions) { - this.dimensions = Objects.requireNonNull(dimensions, + public void setDimensionNames(Set<String> dimensionNames) { + this.dimensionNames = Objects.requireNonNull(dimensionNames, "dimensions may not be null"); } @@ -187,7 +167,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @param fromSelection the fromSelection to set * @since 2022-01-29 */ - public void setFromSelection(Optional<Unit> fromSelection) { + public void setFromSelection(Optional<String> fromSelection) { this.fromSelection = Objects.requireNonNull(fromSelection, "fromSelection cannot be null"); } @@ -196,12 +176,12 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @param fromSelection the fromSelection to set * @since 2022-02-10 */ - public void setFromSelection(Unit fromSelection) { + public void setFromSelection(String fromSelection) { this.setFromSelection(Optional.of(fromSelection)); } @Override - public void setFromUnits(Set<? extends Unit> units) { + public void setFromUnitNames(Set<String> units) { this.fromUnits = Objects.requireNonNull(units, "units may not be null"); } @@ -209,22 +189,21 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @param inputValue the inputValue to set * @since 2022-01-29 */ - public void setInputValue(OptionalDouble inputValue) { + public void setInputValue(String inputValue) { this.inputValue = inputValue; } - public void setSelectedDimension( - ObjectProduct<BaseDimension> selectedDimension) { - this.setSelectedDimension(Optional.of(selectedDimension)); - } - /** * @param selectedDimension the selectedDimension to set * @since 2022-01-29 */ - public void setSelectedDimension( - Optional<? extends ObjectProduct<BaseDimension>> selectedDimension) { - this.selectedDimension = selectedDimension; + public void setSelectedDimensionName( + Optional<String> selectedDimensionName) { + this.selectedDimensionName = selectedDimensionName; + } + + public void setSelectedDimensionName(String selectedDimensionName) { + this.setSelectedDimensionName(Optional.of(selectedDimensionName)); } /** @@ -243,17 +222,17 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @param toSelection the toSelection to set * @since 2022-01-29 */ - public void setToSelection(Optional<Unit> toSelection) { + public void setToSelection(Optional<String> toSelection) { this.toSelection = Objects.requireNonNull(toSelection, "toSelection cannot be null."); } - public void setToSelection(Unit toSelection) { + public void setToSelection(String toSelection) { this.setToSelection(Optional.of(toSelection)); } @Override - public void setToUnits(Set<? extends Unit> units) { + public void setToUnitNames(Set<String> units) { this.toUnits = Objects.requireNonNull(units, "units may not be null"); } @@ -263,19 +242,15 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { } @Override - public void showExpressionConversionOutput(String fromExpression, - String toExpression, double value) { - final String output = String.format("%s = %s %s", fromExpression, value, - toExpression); - this.expressionConversionOutputs.add(output); - System.out.println("Expression Conversion: " + output); + public void showExpressionConversionOutput(UnitConversionRecord uc) { + this.expressionConversions.add(uc); + System.out.println("Expression Conversion: " + uc); } @Override - public void showUnitConversionOutput(UnitValue input, UnitValue output) { - this.unitConversionInputValues.add(input); - this.unitConversionOutputValues.add(output); - System.out.println("Unit conversion: " + input + " = " + output); + public void showUnitConversionOutput(UnitConversionRecord uc) { + this.unitConversions.add(uc); + System.out.println("Unit Conversion: " + uc); } @Override @@ -283,4 +258,12 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { return super.toString() + String.format("[presenter=%s]", this.presenter); } + /** + * @return list of records of every unit conversion made by this bot + * @since 2022-04-09 + */ + public List<UnitConversionRecord> unitConversionList() { + return Collections.unmodifiableList(this.unitConversions); + } + } diff --git a/src/test/java/sevenUnitsGUI/PresenterTest.java b/src/test/java/sevenUnitsGUI/PresenterTest.java index 82842d8..dc2fb57 100644 --- a/src/test/java/sevenUnitsGUI/PresenterTest.java +++ b/src/test/java/sevenUnitsGUI/PresenterTest.java @@ -17,12 +17,9 @@ package sevenUnitsGUI; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; -import java.util.Collection; import java.util.List; -import java.util.Optional; -import java.util.OptionalDouble; import java.util.Set; import java.util.stream.Collectors; @@ -32,6 +29,7 @@ import sevenUnits.unit.BaseDimension; import sevenUnits.unit.Metric; import sevenUnits.unit.Unit; import sevenUnits.unit.UnitValue; +import sevenUnits.utils.Nameable; import sevenUnits.utils.NamedObjectProduct; /** @@ -46,10 +44,8 @@ public final class PresenterTest { static final Set<NamedObjectProduct<BaseDimension>> testDimensions = Set .of(Metric.Dimensions.LENGTH, Metric.Dimensions.VELOCITY); - private static final List<String> unitNames( - Collection<? extends Unit> units) { - return units.stream().map(Unit::getShortName) - .collect(Collectors.toList()); + private static final Set<String> names(Set<? extends Nameable> units) { + return units.stream().map(Nameable::getName).collect(Collectors.toSet()); } /** @@ -70,8 +66,10 @@ public final class PresenterTest { presenter.convertExpressions(); // test result - final List<String> outputs = viewBot.getExpressionConversionOutputs(); - assertEquals("10000.0 m = 10.0 km", outputs.get(outputs.size() - 1)); + final List<UnitConversionRecord> outputs = viewBot + .expressionConversionList(); + assertEquals("10000.0 m = 10.0 km", + outputs.get(outputs.size() - 1).toString()); } /** @@ -85,11 +83,11 @@ public final class PresenterTest { final ViewBot viewBot = new ViewBot(); final Presenter presenter = new Presenter(viewBot); - viewBot.setFromUnits(testUnits); - viewBot.setToUnits(testUnits); - viewBot.setFromSelection(Optional.of(Metric.METRE)); - viewBot.setToSelection(Optional.of(Metric.KILOMETRE)); - viewBot.setInputValue(OptionalDouble.of(10000.0)); + viewBot.setFromUnitNames(names(testUnits)); + viewBot.setToUnitNames(names(testUnits)); + viewBot.setFromSelection("metre"); + viewBot.setToSelection("kilometre"); + viewBot.setInputValue("10000.0"); // convert units presenter.convertUnits(); @@ -102,11 +100,29 @@ public final class PresenterTest { final UnitValue expectedInput = UnitValue.of(Metric.METRE, 10000.0); final UnitValue expectedOutput = expectedInput .convertTo(Metric.KILOMETRE); + final UnitConversionRecord expectedUC = UnitConversionRecord + .fromValues(expectedInput, expectedOutput); - final List<UnitValue> inputs = viewBot.getUnitConversionInputValues(); - final List<UnitValue> outputs = viewBot.getUnitConversionOutputValues(); - assertEquals(expectedInput, inputs.get(inputs.size() - 1)); - assertEquals(expectedOutput, outputs.get(outputs.size() - 1)); + assertEquals(List.of(expectedUC), viewBot.unitConversionList()); + } + + @Test + void testDuplicateUnits() { + assumeTrue(false, "Not yet implemented"); + /* + * enable and disable duplicate units and check for those in From and To, + * include duplicate units in the input set + */ + } + + @Test + void testOneWayConversion() { + assumeTrue(false, "Not yet implemented"); + /* + * enable and disable one-way conversion, testing the units in From and To + * on each setting to ensure they match the rule. Include at least one + * metric exception. + */ } /** @@ -125,31 +141,24 @@ public final class PresenterTest { for (final Unit unit : testUnits) { presenter.database.addUnit(unit.getPrimaryName().orElseThrow(), unit); } + for (final var dimension : testDimensions) { + presenter.database.addDimension( + dimension.getPrimaryName().orElseThrow(), dimension); + } // set from and to units - viewBot.setFromUnits(testUnits); - viewBot.setToUnits(testUnits); - viewBot.setDimensions(testDimensions); - viewBot.setSelectedDimension(Optional.of(Metric.Dimensions.LENGTH)); + viewBot.setFromUnitNames(names(testUnits)); + viewBot.setToUnitNames(names(testUnits)); + viewBot.setDimensionNames(names(testDimensions)); + viewBot.setSelectedDimensionName(Metric.Dimensions.LENGTH.getName()); // filter to length units only, then get the filtered sets of units presenter.updateView(); - final Set<Unit> fromUnits = viewBot.getFromUnits(); - final Set<Unit> toUnits = viewBot.getToUnits(); + final Set<String> fromUnits = viewBot.getFromUnitNames(); + final Set<String> toUnits = viewBot.getToUnitNames(); // test that fromUnits/toUnits is [METRE, KILOMETRE] - // HOWEVER I don't care about the order so I'm testing it this way - assertEquals(2, fromUnits.size(), - "Invalid fromUnits (length != 2): " + unitNames(fromUnits)); - assertEquals(2, toUnits.size(), - "Invalid toUnits (length != 2): " + unitNames(toUnits)); - assertTrue(fromUnits.contains(Metric.METRE), - "Invaild fromUnits (METRE missing): " + unitNames(fromUnits)); - assertTrue(toUnits.contains(Metric.METRE), - "Invaild toUnits (METRE missing): " + unitNames(toUnits)); - assertTrue(fromUnits.contains(Metric.KILOMETRE), - "Invaild fromUnits (KILOMETRE missing): " + unitNames(fromUnits)); - assertTrue(toUnits.contains(Metric.KILOMETRE), - "Invaild toUnits (KILOMETRE missing): " + unitNames(toUnits)); + assertEquals(Set.of("metre", "kilometre"), fromUnits); + assertEquals(Set.of("metre", "kilometre"), toUnits); } } |