From da3a5098602f8177f6d5dac4a322f70d6fdf9126 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Fri, 24 Dec 2021 16:03:26 -0500 Subject: Did some API design for user settings, and moved GUI to a new package --- .../sevenUnitsGUI/ExpressionConversionView.java | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/sevenUnitsGUI/ExpressionConversionView.java (limited to 'src/main/java/sevenUnitsGUI/ExpressionConversionView.java') diff --git a/src/main/java/sevenUnitsGUI/ExpressionConversionView.java b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java new file mode 100644 index 0000000..5a587d4 --- /dev/null +++ b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2021 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 . + */ +package sevenUnitsGUI; + +/** + * A View that can convert unit expressions + * + * @author Adrien Hopkins + * @since 2021-12-15 + */ +public interface ExpressionConversionView extends View { + /** + * @return unit expression to convert from + * @since 2021-12-15 + */ + String getFromExpression(); + + /** + * @return unit expression to convert to + * @since 2021-12-15 + */ + String getToExpression(); + + /** + * 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 + * @since 2021-12-15 + */ + void showExpressionConversionOutput(String fromExpression, + String toExpression, double value); +} -- cgit v1.2.3 From c421e474a7b0d0d453e4a527907f327f2ddef320 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 9 Apr 2022 11:32:43 -0500 Subject: View now sends and recieves Strings instead of data --- .../sevenUnitsGUI/ExpressionConversionView.java | 7 +- src/main/java/sevenUnitsGUI/Presenter.java | 153 +++++++++++------- src/main/java/sevenUnitsGUI/SearchBoxList.java | 10 ++ src/main/java/sevenUnitsGUI/TabbedView.java | 76 +++++---- .../java/sevenUnitsGUI/UnitConversionRecord.java | 180 +++++++++++++++++++++ .../java/sevenUnitsGUI/UnitConversionView.java | 47 +++--- src/main/java/sevenUnitsGUI/View.java | 2 +- src/main/java/sevenUnitsGUI/ViewBot.java | 141 +++++++--------- src/test/java/sevenUnitsGUI/PresenterTest.java | 85 +++++----- 9 files changed, 460 insertions(+), 241 deletions(-) create mode 100644 src/main/java/sevenUnitsGUI/UnitConversionRecord.java (limited to 'src/main/java/sevenUnitsGUI/ExpressionConversionView.java') 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; @@ -134,25 +132,6 @@ public final class Presenter { return Presenter.class.getResourceAsStream(filepath); } - /** - * Accepts a collection and returns a set with the unique elements in that - * collection - * - * @param type of element in collection - * @param collection collection to uniquify - * @return unique collection - * @since 2022-02-26 - */ - private static Set unique(Collection collection) { - final Set 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 @@ -259,13 +238,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,48 +316,81 @@ public final class Presenter { if (this.view instanceof UnitConversionView) { final UnitConversionView ucview = (UnitConversionView) this.view; - final Optional fromUnitOptional = ucview.getFromSelection(); - final Optional toUnitOptional = ucview.getToSelection(); - final OptionalDouble valueOptional = ucview.getInputValue(); + final Optional fromUnitOptional = ucview.getFromSelection(); + final Optional 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. * @@ -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 viewDimension = ucview - .getSelectedDimension().orElseThrow(); + final ObjectProduct viewDimension = this.database + .getDimension(((UnitConversionView) this.view) + .getSelectedDimensionName().orElseThrow()); - final Set units = this.database + final Set 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; @@ -165,6 +166,15 @@ final class SearchBoxList extends JPanel { this.customSearchFilter = o -> true; } + /** + * @return items available in search list, including items that are hidden by + * the search filter + * @since 2022-03-30 + */ + public Collection getItems() { + return Collections.unmodifiableCollection(this.itemsToFilter); + } + /** * @return this component's search box component * @since 2019-04-14 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> dimensionSelector; + private final JComboBox 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 fromSearch; + private final SearchBoxList fromSearch; /** The panel for "To" in the dimension-based converter */ - private final SearchBoxList toSearch; + private final SearchBoxList 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 unitNameList; + private final SearchBoxList unitNameList; /** The searchable list of prefix names in the prefix viewer */ - private final SearchBoxList prefixNameList; + private final SearchBoxList 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> getDimensions() { + public Set getDimensionNames() { return Collections .unmodifiableSet(new JComboBoxItemSet<>(this.dimensionSelector)); } @@ -539,27 +532,25 @@ final class TabbedView implements ExpressionConversionView, UnitConversionView { } @Override - public Optional getFromSelection() { + public Optional 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 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> getSelectedDimension() { - // this must work because this function can only return items that are in - // the selector, which are all of type ObjectProduct - @SuppressWarnings("unchecked") - final ObjectProduct selectedItem = (ObjectProduct) this.dimensionSelector + public Optional 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 getToSelection() { + public Optional getToSelection() { return this.toSearch.getSelectedValue(); } @Override - public void setDimensions( - Set> dimensions) { + public Set 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 dimensionNames) { this.dimensionSelector.removeAllItems(); - for (final NamedObjectProduct d : dimensions) { + for (final String d : dimensionNames) { this.dimensionSelector.addItem(d); } } @Override - public void setFromUnits(Set units) { + public void setFromUnitNames(Set units) { this.fromSearch.setItems(units); } @Override - public void setToUnits(Set units) { + public void setToUnitNames(Set 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 . + */ +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> getDimensions(); + Set getDimensionNames(); /** - * @return unit to convert from + * @return name of unit to convert from * @since 2021-12-15 */ - Optional getFromSelection(); + Optional getFromSelection(); + + /** + * @return list of names of units available to convert from + * @since 2022-03-30 + */ + Set 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> getSelectedDimension(); + Optional getSelectedDimensionName(); /** - * @return unit to convert to + * @return name of unit to convert to * @since 2021-12-15 */ - Optional getToSelection(); + Optional getToSelection(); + + /** + * @return list of names of units available to convert to + * @since 2022-03-30 + */ + Set 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> dimensions); + void setDimensionNames(Set 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 units); + void setFromUnitNames(Set 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 units); + void setToUnitNames(Set 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> dimensions; + private Set 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 fromSelection; + private Optional fromSelection; /** The unit selected in the To selection */ - private Optional toSelection; + private Optional toSelection; /** The currently selected dimension */ - private Optional> selectedDimension; + private Optional selectedDimensionName; /** The units available in the From selection */ - private Set fromUnits; + private Set fromUnits; /** The units available in the To selection */ - private Set toUnits; - /** Saved input values of all unit conversions */ - private final List unitConversionInputValues; - /** Saved output values of all unit conversions */ - private final List unitConversionOutputValues; + private Set toUnits; + + /** Saved outputs of all unit conversions */ + private final List unitConversions; /** Saved outputs of all unit expressions */ - private final List expressionConversionOutputs; + private final List 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 expressionConversionList() { + return this.expressionConversions; } /** @@ -86,12 +85,8 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { * @since 2022-01-29 */ @Override - public Set> getDimensions() { - return this.dimensions; - } - - public List getExpressionConversionOutputs() { - return this.expressionConversionOutputs; + public Set getDimensionNames() { + return this.dimensionNames; } @Override @@ -100,7 +95,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { } @Override - public Optional getFromSelection() { + public Optional 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 getFromUnits() { + @Override + public Set 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> getSelectedDimension() { - return this.selectedDimension.map(x -> x); + public Optional getSelectedDimensionName() { + return this.selectedDimensionName; } @Override @@ -136,7 +132,7 @@ final class ViewBot implements UnitConversionView, ExpressionConversionView { } @Override - public Optional getToSelection() { + public Optional 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 getToUnits() { + @Override + public Set getToUnitNames() { return Collections.unmodifiableSet(this.toUnits); } - /** - * @return the unitConversionInputValues - * @since 2022-02-26 - */ - public List getUnitConversionInputValues() { - return this.unitConversionInputValues; - } - - /** - * @return the unitConversionOutputValues - * @since 2022-02-10 - */ - public List getUnitConversionOutputValues() { - return this.unitConversionOutputValues; - } - @Override - public void setDimensions( - Set> dimensions) { - this.dimensions = Objects.requireNonNull(dimensions, + public void setDimensionNames(Set 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 fromSelection) { + public void setFromSelection(Optional 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 units) { + public void setFromUnitNames(Set 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 selectedDimension) { - this.setSelectedDimension(Optional.of(selectedDimension)); - } - /** * @param selectedDimension the selectedDimension to set * @since 2022-01-29 */ - public void setSelectedDimension( - Optional> selectedDimension) { - this.selectedDimension = selectedDimension; + public void setSelectedDimensionName( + Optional 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 toSelection) { + public void setToSelection(Optional 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 units) { + public void setToUnitNames(Set 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 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> testDimensions = Set .of(Metric.Dimensions.LENGTH, Metric.Dimensions.VELOCITY); - private static final List unitNames( - Collection units) { - return units.stream().map(Unit::getShortName) - .collect(Collectors.toList()); + private static final Set names(Set units) { + return units.stream().map(Nameable::getName).collect(Collectors.toSet()); } /** @@ -70,8 +66,10 @@ public final class PresenterTest { presenter.convertExpressions(); // test result - final List outputs = viewBot.getExpressionConversionOutputs(); - assertEquals("10000.0 m = 10.0 km", outputs.get(outputs.size() - 1)); + final List 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 inputs = viewBot.getUnitConversionInputValues(); - final List 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 fromUnits = viewBot.getFromUnits(); - final Set toUnits = viewBot.getToUnits(); + final Set fromUnits = viewBot.getFromUnitNames(); + final Set 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); } } -- cgit v1.2.3 From 39668f4b274f0e7996f65b4f432a48ae0d88daca Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Fri, 8 Jul 2022 12:46:45 -0500 Subject: Bumped version number to 0.4.0b1 & added @since --- CHANGELOG.org | 2 +- README.org | 2 +- docs/design.org | 2 +- docs/design.pdf | Bin 348080 -> 348051 bytes docs/design.tex | 68 ++++++++++----------- docs/manual.org | 6 +- docs/manual.pdf | Bin 173138 -> 173293 bytes docs/manual.tex | 36 +++++------ screenshots/main-interface-settings.png | Bin 25953 -> 25953 bytes src/main/java/sevenUnits/ProgramInfo.java | 4 +- src/main/java/sevenUnits/unit/BaseDimension.java | 5 +- src/main/java/sevenUnits/utils/NameSymbol.java | 1 + .../sevenUnits/utils/SemanticVersionNumber.java | 25 ++++++++ .../sevenUnitsGUI/ExpressionConversionView.java | 4 ++ src/main/java/sevenUnitsGUI/Main.java | 6 +- src/main/java/sevenUnitsGUI/PrefixSearchRule.java | 12 ++++ .../java/sevenUnitsGUI/StandardDisplayRules.java | 8 +++ .../java/sevenUnitsGUI/UnitConversionRecord.java | 8 +++ .../java/sevenUnitsGUI/UnitConversionView.java | 12 ++++ src/main/java/sevenUnitsGUI/View.java | 10 +++ src/main/java/sevenUnitsGUI/ViewBot.java | 1 + 21 files changed, 150 insertions(+), 62 deletions(-) (limited to 'src/main/java/sevenUnitsGUI/ExpressionConversionView.java') diff --git a/CHANGELOG.org b/CHANGELOG.org index 7000828..de873b3 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -1,6 +1,6 @@ * Changelog All notable changes in this project will be shown in this file. -** Unreleased +** v0.4.0 (Unreleased) *** Added - Added tests for the GUI - Added an object for the version numbers (SemanticVersionNumber) diff --git a/README.org b/README.org index f891bdc..171b4d9 100644 --- a/README.org +++ b/README.org @@ -1,4 +1,4 @@ -* 7Units v0.4.0a1 +* 7Units v0.4.0b1 (this project uses Semantic Versioning) ** What is it? This is a unit converter, which allows you to convert between different units, and includes a GUI which can read unit data from a file (using some unit math) and convert between units that you type in, and has a unit and prefix viewer to check the units that have been loaded in. diff --git a/docs/design.org b/docs/design.org index 467c018..0e4ca92 100644 --- a/docs/design.org +++ b/docs/design.org @@ -1,5 +1,5 @@ #+TITLE: 7Units Design Document -#+SUBTITLE: For version 0.4.0-alpha.1 +#+SUBTITLE: For version 0.4.0-beta.1 #+DATE: 2022 July 8 #+LaTeX_HEADER: \usepackage[a4paper, lmargin=25mm, rmargin=25mm, tmargin=25mm, bmargin=25mm]{geometry} #+LaTeX_HEADER: \usepackage{xurl} diff --git a/docs/design.pdf b/docs/design.pdf index 56d73a6..99fbb3b 100644 Binary files a/docs/design.pdf and b/docs/design.pdf differ diff --git a/docs/design.tex b/docs/design.tex index 5023fb3..9434cc1 100644 --- a/docs/design.tex +++ b/docs/design.tex @@ -1,4 +1,4 @@ -% Created 2022-07-08 Fri 10:05 +% Created 2022-07-08 Fri 12:43 % Intended LaTeX compiler: pdflatex \documentclass[11pt]{article} \usepackage[utf8]{inputenc} @@ -18,7 +18,7 @@ \usepackage{xurl} \date{2022 July 8} \title{7Units Design Document\\\medskip -\large For version 0.4.0-alpha.1} +\large For version 0.4.0-beta.1} \hypersetup{ pdfauthor={}, pdftitle={7Units Design Document}, @@ -34,35 +34,35 @@ \newpage \section{Introduction} -\label{sec:orgd3381a6} +\label{sec:orga266915} 7Units is a program that can convert between units. This document details the internal design of 7Units, intended to be used by current and future developers. \section{System Overview} -\label{sec:org9bd9474} +\label{sec:org6d969dd} \begin{figure}[htbp] \centering \includegraphics[height=144px]{./diagrams/overview-diagram.plantuml.png} \caption{A big-picture diagram of 7Units, containing all of the major classes.} \end{figure} \subsection{Packages of 7Units} -\label{sec:org5c8f3ee} +\label{sec:orged5584a} 7Units splits its code into three main packages: \begin{description} -\item[{\texttt{sevenUnits.unit}}] The \hyperref[sec:org1171d15]{unit system} +\item[{\texttt{sevenUnits.unit}}] The \hyperref[sec:orgf969629]{unit system} \item[{\texttt{sevenUnits.utils}}] Extra classes that aid the unit system. -\item[{\texttt{sevenUnitsGUI}}] The \hyperref[sec:orgb716c37]{front end} code +\item[{\texttt{sevenUnitsGUI}}] The \hyperref[sec:org431a987]{front end} code \end{description} \texttt{sevenUnits.unit} depends on \texttt{sevenUnits.utils}, while \texttt{sevenUnitsGUI} depends on both \texttt{sevenUnits} packages. There is only one class that isn't in any of these packages, \texttt{sevenUnits.VersionInfo}. \subsection{Major Classes of 7Units} -\label{sec:org22c5367} +\label{sec:org147769f} \begin{description} -\item[{\hyperref[sec:orge128590]{sevenUnits.unit.Unit}}] The class representing a unit -\item[{\hyperref[sec:orgc8dc0e4]{sevenUnits.unit.UnitDatabase}}] A class that stores collections of units, prefixes and dimensions. -\item[{\hyperref[sec:orgf3ee40e]{sevenUnitsGUI.View}}] The class that handles interaction between the user and the program. -\item[{\hyperref[sec:orgcf5cc70]{sevenUnitsGUI.Presenter}}] The class that handles communication between the \texttt{View} and the unit system. +\item[{\hyperref[sec:org93aab3e]{sevenUnits.unit.Unit}}] The class representing a unit +\item[{\hyperref[sec:org0a33326]{sevenUnits.unit.UnitDatabase}}] A class that stores collections of units, prefixes and dimensions. +\item[{\hyperref[sec:org5460ab6]{sevenUnitsGUI.View}}] The class that handles interaction between the user and the program. +\item[{\hyperref[sec:org4f735c1]{sevenUnitsGUI.Presenter}}] The class that handles communication between the \texttt{View} and the unit system. \end{description} \newpage \subsection{Process of Unit Conversion} -\label{sec:org73700d8} +\label{sec:org65b1400} \begin{figure}[htbp] \centering \includegraphics[width=.9\linewidth]{./diagrams/convert-units.plantuml.png} @@ -77,7 +77,7 @@ \end{enumerate} \newpage \subsection{Process of Expression Conversion} -\label{sec:org3e8ae17} +\label{sec:orgc9346ba} The process of expression conversion is similar to that of unit conversion. \begin{figure}[htbp] \centering @@ -93,7 +93,7 @@ The process of expression conversion is similar to that of unit conversion. \end{enumerate} \newpage \section{Unit System Design} -\label{sec:org1171d15} +\label{sec:orgf969629} Any code related to the backend unit system is stored in the \texttt{sevenUnits.unit} package. Here is a class diagram of the system. Unimportant methods, methods inherited from Object, getters and setters have been omitted. @@ -104,11 +104,11 @@ Here is a class diagram of the system. Unimportant methods, methods inherited f \end{figure} \newpage \subsection{Dimensions} -\label{sec:org14cd421} -Dimensions represent what a unit is measuring, such as length, time, or energy. Dimensions are represented as an \hyperref[sec:orgc3e831c]{ObjectProduct}, where \texttt{BaseDimension} is a very simple class (its only properties are a name and a symbol) which represents the dimension of a base unit; these base dimensions can be multiplied to create all other Dimensions. +\label{sec:orgda7eb73} +Dimensions represent what a unit is measuring, such as length, time, or energy. Dimensions are represented as an \hyperref[sec:org9c5f1fc]{ObjectProduct}, where \texttt{BaseDimension} is a very simple class (its only properties are a name and a symbol) which represents the dimension of a base unit; these base dimensions can be multiplied to create all other Dimensions. \subsection{Unit Classes} -\label{sec:orge128590} -Units are internally represented by the abstract class \texttt{Unit}. All units have an \hyperref[sec:orgc3e831c]{ObjectProduct} (referred to as the base) that they are based on, a dimension (ObjectProduct), one or more names and a symbol (these last two bits of data are contained in the \texttt{NameSymbol} class). The dimension is calculated from the base unit when needed; the variable is just a cache. It has two constructors: a package-private one used to make \texttt{BaseUnit} instances, and a protected one used to make general units (for other subclasses of \texttt{Unit}). All unit classes are immutable. +\label{sec:org93aab3e} +Units are internally represented by the abstract class \texttt{Unit}. All units have an \hyperref[sec:org9c5f1fc]{ObjectProduct} (referred to as the base) that they are based on, a dimension (ObjectProduct), one or more names and a symbol (these last two bits of data are contained in the \texttt{NameSymbol} class). The dimension is calculated from the base unit when needed; the variable is just a cache. It has two constructors: a package-private one used to make \texttt{BaseUnit} instances, and a protected one used to make general units (for other subclasses of \texttt{Unit}). All unit classes are immutable. Units also have two conversion functions - one which converts from a value expressed in this unit to its base unit, and another which converts from a value expressed in the base unit to this unit. In \texttt{Unit}, they are defined as two abstract methods. This allows you to convert from any unit to any other (as long as they have the same base, i.e. you aren't converting metres to pounds). To convert from A to B, first convert from A to its base, then convert from the base to B. @@ -133,20 +133,20 @@ There are a few more classes which play small roles in the unit system: \item[{USCustomary}] A static utility class with instances of common units in the US Customary system (not to be confused with the British Imperial system; it has the same unit names but the values of a few units are different). \end{description} \subsection{Prefixes} -\label{sec:org1bd7050} +\label{sec:org40fa3a0} A \texttt{UnitPrefix} is a simple object that can multiply a \texttt{LinearUnit} by a value. It can calculate a new name for the unit by combining its name and the unit's name (symbols are done similarly). It can do multiplication, division and exponentation with a number, as well as multiplication and division with another prefix; all of these work by changing the prefix's multiplier. \subsection{The Unit Database} -\label{sec:orgc8dc0e4} +\label{sec:org0a33326} The \texttt{UnitDatabase} class stores all of the unit, prefix and dimension data used by this program. It is not a representation of an actual database, just a class that stores lots of data. Units are stored using a custom \texttt{Map} implementation (\texttt{PrefixedUnitMap}) which maps unit names to units. It is backed by two maps: one for units (without prefixes) and one for prefixes. It is programmed to include prefixes (so if units includes "metre" and prefixes includes "kilo", this map will include "kilometre", mapping it to a unit representing a kilometre). It is immutable, but you can modify the underlying maps, which is reflected in the \texttt{PrefixedUnitMap}. Other than that, it is a normal map implementation. Prefixes and dimensions are stored in normal maps. \subsubsection{Parsing Expressions} -\label{sec:orgb7ee1da} -Each \texttt{UnitDatabase} instance has four \hyperref[sec:orgd351c2f]{ExpressionParser} instances associated with it, for four types of expressions: unit, unit value, prefix and dimension. They are mostly similar, with operators corresponding to each operation of the corresponding class (\texttt{LinearUnit}, \texttt{LinearUnitValue}, \texttt{UnitPrefix}, \texttt{ObjectProduct}). Unit and unit value expressions use linear units; nonlinear units can be used with a special syntax (like "degC(20)") and are immediately converted to a linear unit representing their base (Kelvin in this case) before operating. +\label{sec:orgb3362c7} +Each \texttt{UnitDatabase} instance has four \hyperref[sec:org7f49fac]{ExpressionParser} instances associated with it, for four types of expressions: unit, unit value, prefix and dimension. They are mostly similar, with operators corresponding to each operation of the corresponding class (\texttt{LinearUnit}, \texttt{LinearUnitValue}, \texttt{UnitPrefix}, \texttt{ObjectProduct}). Unit and unit value expressions use linear units; nonlinear units can be used with a special syntax (like "degC(20)") and are immediately converted to a linear unit representing their base (Kelvin in this case) before operating. \subsubsection{Parsing Files} -\label{sec:org072dc65} +\label{sec:org5f50970} There are two types of data files: unit and dimension. Unit files contain data about units and prefixes. Each line contains the name of a unit or prefix (prefixes end in a dash, units don't) followed by an expression which defines it, separated by one or more space characters (this behaviour is defined by the static regular expression \texttt{NAME\_EXPRESSION}). Unit files are parsed line by line, each line being run through the \texttt{addUnitOrPrefixFromLine} method, which splits a line into name and expression, determines whether it's a unit or a prefix, and parses the expression. Because all units are defined by others, base units need to be defined with a special expression "!"; \textbf{these units should be added to the database before parsing the file}. @@ -154,10 +154,10 @@ Unit files contain data about units and prefixes. Each line contains the name o Dimension files are similar, only for dimensions instead of units and prefixes. \newpage \section{Front-End Design} -\label{sec:orgb716c37} +\label{sec:org431a987} The front-end of 7Units is based on an MVP model. There are two major frontend classes, the \textbf{View} and the \textbf{Presenter}. \subsection{The View} -\label{sec:orgf3ee40e} +\label{sec:org5460ab6} The \texttt{View} is the part of the frontend code that directly interacts with the user. It handles input and output, but does not do any processing. Processing is handled by the presenter and the backend code. The \texttt{View} is an interface, not a single class, so that I can easily create multiple views without having to rewrite any processing code. This allows me to easily prototype changes to the GUI without messing with existing code. @@ -171,10 +171,10 @@ There are currently two implementations of the \texttt{View}: \end{description} Both of these \texttt{View} implementations implement \texttt{UnitConversionView} and \texttt{ExpressionConversionView}. \subsection{The Presenter} -\label{sec:orgcf5cc70} +\label{sec:org4f735c1} The \texttt{Presenter} is an intermediary between the \texttt{View} and the backend code. It accepts the user's input and passes it to the backend, then accepts the backend's output and passes it to the frontend for user viewing. Its main functions do not have arguments or return values; instead it takes input from and provides output to the \texttt{View} via its public methods. \subsubsection{Rules} -\label{sec:org9542834} +\label{sec:org29011d5} The \texttt{Presenter} has a set of function-object rules that determine some of its behaviours. Each corresponds to a setting in the \texttt{View}, but they can be set to other values via the \texttt{Presenter}'s setters (although nonstandard rules cannot be saved and loaded): \begin{description} \item[{numberDisplayRule}] A function that determines how numbers are displayed. This controls the rounding rules. @@ -184,7 +184,7 @@ The \texttt{Presenter} has a set of function-object rules that determine some of These rules have been made this way to enable an incredible level of customization of these behaviours. Because any function object with the correct arguments and return type is accepted, these rules (especially the number display rule) can do much more than the default behaviours. \subsection{Utility Classes} -\label{sec:orgc49ece0} +\label{sec:orga401626} The frontend has many miscellaneous utility classes. Many of them are package-private. Here is a list of them, with a brief description of what they do and where they are used: \begin{description} \item[{DefaultPrefixRepetitionRule}] An enum containing the available rules determining when you can repeat prefixes. Used by the \texttt{TabbedView} for selecting the rule and by the \texttt{Presenter} for loading it from a file. @@ -197,15 +197,15 @@ The frontend has many miscellaneous utility classes. Many of them are package-p \end{description} \newpage \section{Utility Classes} -\label{sec:orgc90957f} +\label{sec:org9889589} 7Units has a few general "utility" classes. They aren't directly related to units, but are used in the units system. \subsection{ObjectProduct} -\label{sec:orgc3e831c} +\label{sec:org9c5f1fc} An \texttt{ObjectProduct} represents a "product" of elements of some type. The units system uses them to represent coherent units as a product of base units, and dimensions as a product of base dimensions. Internally, it is represented using a map mapping objects to their exponents in the product. For example, the unit "kg m\textsuperscript{2} / s\textsuperscript{2}" (i.e. a Joule) would be represented with a map like \texttt{[kg: 1, m: 2, s: -2]}. \subsection{ExpressionParser} -\label{sec:orgd351c2f} +\label{sec:org7f49fac} The \texttt{ExpressionParser} class is used to parse the unit, prefix and dimension expressions that are used throughout 7Units. An expression is something like "(2 m + 30 J / N) * 8 s)". Each instance represents a type of expression, containing a way to obtain values (such as numbers or units) from the text and operations that can be done on these values (such as addition, subtraction or multiplication). Each operation also has a priority, which controls the order of operations (i.e. multiplication gets a higher priority than addition). \texttt{ExpressionParser} has a parameterized type \texttt{T}, which represents the type of the value used in the expression. The expression parser currently only supports one type of value per expression; in the expressions used by 7Units numbers are treated as a kind of unit or prefix. Operators are represented by internal types; the system distinguishes between unary operators (those that take a single value, like negation) and binary operators (those that take 2 values, like +, -, * or /). @@ -222,13 +222,13 @@ Expressions are parsed in 2 steps: After evaluating the last token, there should be one value left in the stack - the answer. If there isn't, the original expression was malformed. \end{enumerate} \subsection{Math Classes} -\label{sec:orgdadbc0d} +\label{sec:org48c9af9} There are two simple math classes in 7Units: \begin{description} \item[{\texttt{UncertainDouble}}] Like a \texttt{double}, but with an uncertainty (e.g. \(2.0 \pm 0.4\)). The operations are like those of the regular Double, only they also calculate the uncertainty of the final value. They also have "exact" versions to help interoperation between \texttt{double} and \texttt{UncertainDouble}. It is used by the converter's Scientific Precision setting. \item[{\texttt{DecimalComparison}}] A static utility class that contains a few alternate equals() methods for \texttt{double} and \texttt{UncertainDouble}. These methods allow a slight (configurable) difference between values to still be considered equal, to fight roundoff error. \end{description} \subsection{Collection Classes} -\label{sec:org7421746} +\label{sec:org9065607} The \texttt{ConditionalExistenceCollections} class contains wrapper implementations of \texttt{Collection}, \texttt{Iterator}, \texttt{Map} and \texttt{Set}. These implementations ignore elements that do not pass a certain condition - if an element fails the condition, \texttt{contains} will return false, the iterator will skip past it, it won't be counted in \texttt{size}, etc. even if it exists in the original collection. Effectively, any element of the original collection that fails the test does not exist. \end{document} diff --git a/docs/manual.org b/docs/manual.org index 6de3b93..bcaaf6b 100644 --- a/docs/manual.org +++ b/docs/manual.org @@ -1,5 +1,5 @@ #+TITLE: 7Units User Manual -#+SUBTITLE: For Version 0.4.0-alpha.1 +#+SUBTITLE: For Version 0.4.0-beta.1 #+DATE: 2022 July 8 #+LaTeX_HEADER: \usepackage[a4paper, lmargin=25mm, rmargin=25mm, tmargin=25mm, bmargin=25mm]{geometry} @@ -9,7 +9,7 @@ * System Requirements - Works on all major operating systems \\ *NOTE:* All screenshots in this document were taken on Windows 10. If you use a different operating system, the program will probably look different than what is shown. - - Java version 11-15 required + - Java version 11+ required # installation instructions go here - wait until git repository is fixed/set up #+LaTeX: \newpage * How to Use 7Units @@ -47,7 +47,7 @@ [[../screenshots/sample-conversion-results-expression-converter.png]] * 7Units Settings All settings can be accessed in the tab with the gear icon. - #+CAPTION: The settings menu, as of version 0.4.0-alpha.1 + #+CAPTION: The settings menu, as of version 0.4.0-beta.1 #+ATTR_LaTeX: :height 250px [[../screenshots/main-interface-settings.png]] ** Rounding Settings diff --git a/docs/manual.pdf b/docs/manual.pdf index 71cb886..430eb09 100644 Binary files a/docs/manual.pdf and b/docs/manual.pdf differ diff --git a/docs/manual.tex b/docs/manual.tex index 4b8e4ab..bc80a69 100644 --- a/docs/manual.tex +++ b/docs/manual.tex @@ -1,4 +1,4 @@ -% Created 2022-07-08 Fri 10:17 +% Created 2022-07-08 Fri 12:44 % Intended LaTeX compiler: pdflatex \documentclass[11pt]{article} \usepackage[utf8]{inputenc} @@ -17,7 +17,7 @@ \usepackage[a4paper, lmargin=25mm, rmargin=25mm, tmargin=25mm, bmargin=25mm]{geometry} \date{2022 July 8} \title{7Units User Manual\\\medskip -\large For Version 0.4.0-alpha.1} +\large For Version 0.4.0-beta.1} \hypersetup{ pdfauthor={}, pdftitle={7Units User Manual}, @@ -32,21 +32,21 @@ \newpage \section{Introduction and Purpose} -\label{sec:org26b964e} +\label{sec:org40df1fc} 7Units is a program that can be used to convert units. This document outlines how to use the program. \section{System Requirements} -\label{sec:orgfb95788} +\label{sec:org5bf24ac} \begin{itemize} \item Works on all major operating systems \\ \textbf{NOTE:} All screenshots in this document were taken on Windows 10. If you use a different operating system, the program will probably look different than what is shown. -\item Java version 11-15 required +\item Java version 11+ required \end{itemize} \newpage \section{How to Use 7Units} -\label{sec:orgc48d5d5} +\label{sec:org0303c2c} \subsection{Simple Unit Conversion} -\label{sec:orgd56d395} +\label{sec:orgfdea557} \begin{enumerate} \item Select the "Convert Units" tab if it is not already selected. You should see a screen like in figure \ref{main-interface-dimension}: \begin{figure}[htbp] @@ -71,7 +71,7 @@ \end{figure} \end{enumerate} \subsection{Complex Unit Conversion} -\label{sec:org79999e9} +\label{sec:orgaebd362} \begin{enumerate} \item Select the "Convert Unit Expressions" if it is not already selected. You should see a screen like in figure \ref{main-interface-expression}: \begin{figure}[htbp] @@ -79,7 +79,7 @@ \includegraphics[height=250px]{../screenshots/main-interface-expression-converter.png} \caption{\label{main-interface-expression}Taken in version 0.3.0} \end{figure} -\item Enter a \hyperref[sec:org28ae9bb]{unit expression} in the From box. This can be something like "\texttt{7 km}" or "\texttt{6 ft - 2 in}" or "\texttt{3 kg m + 9 lb ft + (35 mm)\textasciicircum{}2 * (85 oz) / (20 in)}". +\item Enter a \hyperref[sec:org1bb92a1]{unit expression} in the From box. This can be something like "\texttt{7 km}" or "\texttt{6 ft - 2 in}" or "\texttt{3 kg m + 9 lb ft + (35 mm)\textasciicircum{}2 * (85 oz) / (20 in)}". \item Enter a unit name (or another unit expression) in the To box. \item Press the Convert button. This will calculate the value of the first expression, and convert it to a multiple of the second unit (or expression). \begin{figure}[htbp] @@ -89,15 +89,15 @@ \end{figure} \end{enumerate} \section{7Units Settings} -\label{sec:org6032cec} +\label{sec:orgcab9094} All settings can be accessed in the tab with the gear icon. \begin{figure}[htbp] \centering \includegraphics[height=250px]{../screenshots/main-interface-settings.png} -\caption{The settings menu, as of version 0.4.0-alpha.1} +\caption{The settings menu, as of version 0.4.0-beta.1} \end{figure} \subsection{Rounding Settings} -\label{sec:orgbe67478} +\label{sec:orgbb50019} These settings control how the output of a unit conversion is rounded. \begin{description} \item[{Fixed Precision}] Round to a fixed number of \href{https://en.wikipedia.org/wiki/Significant\_figures}{significant digits}. The number of significant digits is controlled by the precision slider below. @@ -105,7 +105,7 @@ These settings control how the output of a unit conversion is rounded. \item[{Scientific Precision}] Intelligent rounding which uses the precision of the input value(s) to determine the output precision. Not affected by the precision slider. \end{description} \subsection{Prefix Repetition Settings} -\label{sec:org3207fad} +\label{sec:org48d4cc7} These settings control when you are allowed to repeat unit prefixes (e.g. kilokilometre) \begin{description} \item[{No Repetition}] Units may only have one prefix. @@ -120,7 +120,7 @@ These settings control when you are allowed to repeat unit prefixes (e.g. kiloki \end{itemize} \end{description} \subsection{Search Settings} -\label{sec:orge76e8f6} +\label{sec:orgce39699} These settings control which prefixes are shown in the "Convert Units" tab. Only coherent SI units (e.g. metre, second, newton, joule) will get prefixes. Some prefixed units are created in the unitfile, and will stay regardless of this setting (though they can be removed from the unitfile). \begin{description} \item[{Never Include Prefixed Units}] Prefixed units will only be shown if they are explicitly added to the unitfile. @@ -128,15 +128,15 @@ These settings control which prefixes are shown in the "Convert Units" tab. Onl \item[{Include All Single Prefixes}] Every coherent unit will have every prefixed version of it included in the list. \end{description} \subsection{Miscellaneous Settings} -\label{sec:org5613324} +\label{sec:org2332067} \begin{description} \item[{Convert One Way Only}] In the simple conversion tab, only imperial/customary units will be shown on the left, and only metric units\footnote{7Units's definition of "metric" is stricter than the SI, but all of the common units that are commonly considered metric but not included in 7Units's definition are included in the exceptions file.} will be shown on the right. Units listed in the exceptions file (\texttt{src/main/resources/metric\_exceptions.txt}) will be shown on both sides. This is a way to reduce the number of options you must search through if you only convert one way. The expressions tab is unaffected. \item[{Show Duplicates in "Convert Units"}] If unchecked, any unit that has multiple names will only have one included in the Convert Units lists. The selected name will be the longest; if there are multiple longest names one is selected arbitrarily. You will still be able to use these alternate names in the expressions tab. \end{description} \section{Appendices} -\label{sec:org03406a3} +\label{sec:orgd294b53} \subsection{Unit Expressions} -\label{sec:org28ae9bb} +\label{sec:org1bb92a1} A unit expression is simply a math expression where the values being operated on are units or numbers. The operations that can be used are (in order of precedence): \begin{itemize} \item Exponentiation (\^{}); the exponent must be an integer. Both units and numbers can be raised to an exponent @@ -146,6 +146,6 @@ A unit expression is simply a math expression where the values being operated on Brackets can be used to manipulate the order of operations, and nonlinear units like Celsius and Fahrenheit cannot be used in expressions. You can use a value in a nonlinear unit by putting brackets after it - for example, degC(12) represents the value 12 \textdegree{} C \subsection{Other Expressions} -\label{sec:orgb03cf2c} +\label{sec:org2f36819} There are also a simplified version of expressions for prefixes and dimensions. Only multiplication, division and exponentation are supported. Currently, exponentation is not supported for dimensions, but that may be fixed in the future. \end{document} diff --git a/screenshots/main-interface-settings.png b/screenshots/main-interface-settings.png index c29f65c..39b95f4 100644 Binary files a/screenshots/main-interface-settings.png and b/screenshots/main-interface-settings.png differ diff --git a/src/main/java/sevenUnits/ProgramInfo.java b/src/main/java/sevenUnits/ProgramInfo.java index f32d2c7..6ebe66c 100644 --- a/src/main/java/sevenUnits/ProgramInfo.java +++ b/src/main/java/sevenUnits/ProgramInfo.java @@ -26,9 +26,9 @@ import sevenUnits.utils.SemanticVersionNumber; */ public final class ProgramInfo { - /** The version number (0.4.0-alpha+dev) */ + /** The version number (0.4.0-beta.1) */ public static final SemanticVersionNumber VERSION = SemanticVersionNumber - .preRelease(0, 4, 0, "alpha", 1); + .preRelease(0, 4, 0, "beta", 1); private ProgramInfo() { // this class is only for static variables, you shouldn't be able to diff --git a/src/main/java/sevenUnits/unit/BaseDimension.java b/src/main/java/sevenUnits/unit/BaseDimension.java index bcd57d9..820d48c 100644 --- a/src/main/java/sevenUnits/unit/BaseDimension.java +++ b/src/main/java/sevenUnits/unit/BaseDimension.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2019 Adrien Hopkins + * Copyright (C) 2019, 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 @@ -63,6 +63,9 @@ public final class BaseDimension implements Nameable { this.symbol = Objects.requireNonNull(symbol, "symbol must not be null."); } + /** + * @since v0.4.0 + */ @Override public NameSymbol getNameSymbol() { return NameSymbol.of(this.name, this.symbol); diff --git a/src/main/java/sevenUnits/utils/NameSymbol.java b/src/main/java/sevenUnits/utils/NameSymbol.java index 7ef2967..9388f63 100644 --- a/src/main/java/sevenUnits/utils/NameSymbol.java +++ b/src/main/java/sevenUnits/utils/NameSymbol.java @@ -294,6 +294,7 @@ public final class NameSymbol { * extra name. If this {@code NameSymbol} has a primary name, the provided * name will become an other name, otherwise it will become the primary name. * + * @since v0.4.0 * @since 2022-04-19 */ public final NameSymbol withExtraName(String name) { diff --git a/src/main/java/sevenUnits/utils/SemanticVersionNumber.java b/src/main/java/sevenUnits/utils/SemanticVersionNumber.java index a663a11..e80e16e 100644 --- a/src/main/java/sevenUnits/utils/SemanticVersionNumber.java +++ b/src/main/java/sevenUnits/utils/SemanticVersionNumber.java @@ -39,6 +39,7 @@ import java.util.regex.Pattern; * are made * * + * @since v0.4.0 * @since 2022-02-19 */ public final class SemanticVersionNumber @@ -51,6 +52,7 @@ public final class SemanticVersionNumber * throw NullPointerExceptions, everything else throws * IllegalArgumentException. * + * @since v0.4.0 * @since 2022-02-19 */ public static final class Builder { @@ -67,6 +69,7 @@ public final class SemanticVersionNumber * @param major major version number of final version * @param minor minor version number of final version * @param patch patch version number of final version + * @since v0.4.0 * @since 2022-02-19 */ private Builder(int major, int minor, int patch) { @@ -79,6 +82,7 @@ public final class SemanticVersionNumber /** * @return version number created by this builder + * @since v0.4.0 * @since 2022-02-19 */ public SemanticVersionNumber build() { @@ -91,6 +95,7 @@ public final class SemanticVersionNumber * * @param identifiers build metadata * @return this builder + * @since v0.4.0 * @since 2022-02-19 */ public Builder buildMetadata(List identifiers) { @@ -110,6 +115,7 @@ public final class SemanticVersionNumber * * @param identifiers build metadata * @return this builder + * @since v0.4.0 * @since 2022-02-19 */ public Builder buildMetadata(String... identifiers) { @@ -148,6 +154,7 @@ public final class SemanticVersionNumber * * @param identifiers pre-release identifier(s) to add * @return this builder + * @since v0.4.0 * @since 2022-02-19 */ public Builder preRelease(int... identifiers) { @@ -166,6 +173,7 @@ public final class SemanticVersionNumber * * @param identifiers pre-release identifier(s) to add * @return this builder + * @since v0.4.0 * @since 2022-02-19 */ public Builder preRelease(List identifiers) { @@ -185,6 +193,7 @@ public final class SemanticVersionNumber * * @param identifiers pre-release identifier(s) to add * @return this builder + * @since v0.4.0 * @since 2022-02-19 */ public Builder preRelease(String... identifiers) { @@ -205,6 +214,7 @@ public final class SemanticVersionNumber * @param identifier1 first identifier * @param identifier2 second identifier * @return this builder + * @since v0.4.0 * @since 2022-02-19 */ public Builder preRelease(String identifier1, int identifier2) { @@ -270,6 +280,7 @@ public final class SemanticVersionNumber * @param patch patch version number of final version * @return version number builder * @throws IllegalArgumentException if any argument is negative + * @since v0.4.0 * @since 2022-02-19 */ public static final SemanticVersionNumber.Builder builder(int major, @@ -293,6 +304,7 @@ public final class SemanticVersionNumber * @param b second list * @return result of comparison as in a comparator * @see Comparator + * @since v0.4.0 * @since 2022-02-20 */ private static final int compareIdentifiers(List a, List b) { @@ -353,6 +365,7 @@ public final class SemanticVersionNumber * * @param versionString string to parse * @return {@code SemanticVersionNumber} instance + * @since v0.4.0 * @since 2022-02-19 * @see {@link #toString} */ @@ -396,6 +409,7 @@ public final class SemanticVersionNumber * * @param versionString string to test * @return true iff string is valid + * @since v0.4.0 * @since 2022-02-19 */ public static final boolean isValidVersionString(String versionString) { @@ -415,6 +429,7 @@ public final class SemanticVersionNumber * @throws IllegalArgumentException if any argument is negative or if the * preReleaseType is null, empty or not * alphanumeric (0-9, A-Z, a-z, - only) + * @since v0.4.0 * @since 2022-02-19 */ public static final SemanticVersionNumber preRelease(int major, int minor, @@ -452,6 +467,7 @@ public final class SemanticVersionNumber * @param patch patch version number * @return {@code SemanticVersionNumber} instance * @throws IllegalArgumentException if any argument is negative + * @since v0.4.0 * @since 2022-02-19 */ public static final SemanticVersionNumber stableVersion(int major, int minor, @@ -484,6 +500,7 @@ public final class SemanticVersionNumber * @param patch patch version number * @param preReleaseIdentifiers pre-release version data * @param buildMetadata build metadata + * @since v0.4.0 * @since 2022-02-19 */ private SemanticVersionNumber(int major, int minor, int patch, @@ -497,6 +514,7 @@ public final class SemanticVersionNumber /** * @return build metadata (empty if there is none) + * @since v0.4.0 * @since 2022-02-19 */ public List buildMetadata() { @@ -567,6 +585,7 @@ public final class SemanticVersionNumber * @param other version to compare with * @return true if you can definitely upgrade to {@code other} without * changing code + * @since v0.4.0 * @since 2022-02-20 */ public boolean compatibleWith(SemanticVersionNumber other) { @@ -620,6 +639,7 @@ public final class SemanticVersionNumber /** * @return true iff this version is stable (major version > 0 and not a * pre-release) + * @since v0.4.0 * @since 2022-02-19 */ public boolean isStable() { @@ -629,6 +649,7 @@ public final class SemanticVersionNumber /** * @return the MAJOR version number, incremented when you make backwards * incompatible API changes + * @since v0.4.0 * @since 2022-02-19 */ public int majorVersion() { @@ -638,6 +659,7 @@ public final class SemanticVersionNumber /** * @return the MINOR version number, incremented when you add backwards * compatible functionality + * @since v0.4.0 * @since 2022-02-19 */ public int minorVersion() { @@ -647,6 +669,7 @@ public final class SemanticVersionNumber /** * @return the PATCH version number, incremented when you make backwards * compatible bug fixes + * @since v0.4.0 * @since 2022-02-19 */ public int patchVersion() { @@ -656,6 +679,7 @@ public final class SemanticVersionNumber /** * @return identifiers describing this pre-release (empty if not a * pre-release) + * @since v0.4.0 * @since 2022-02-19 */ public List preReleaseIdentifiers() { @@ -674,6 +698,7 @@ public final class SemanticVersionNumber * 1, pre-release identifiers "alpha" and "1" and build metadata "2022-02-19" * has a string representation "3.2.1-alpha.1+2022-02-19". * + * @since v0.4.0 * @see The official SemVer specification */ @Override diff --git a/src/main/java/sevenUnitsGUI/ExpressionConversionView.java b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java index 872ca10..5c39788 100644 --- a/src/main/java/sevenUnitsGUI/ExpressionConversionView.java +++ b/src/main/java/sevenUnitsGUI/ExpressionConversionView.java @@ -20,17 +20,20 @@ package sevenUnitsGUI; * A View that can convert unit expressions * * @author Adrien Hopkins + * @since v0.4.0 * @since 2021-12-15 */ public interface ExpressionConversionView extends View { /** * @return unit expression to convert from + * @since v0.4.0 * @since 2021-12-15 */ String getFromExpression(); /** * @return unit expression to convert to + * @since v0.4.0 * @since 2021-12-15 */ String getToExpression(); @@ -39,6 +42,7 @@ public interface ExpressionConversionView extends View { * Shows the output of an expression conversion to the user. * * @param uc unit conversion to show + * @since v0.4.0 * @since 2021-12-15 */ void showExpressionConversionOutput(UnitConversionRecord uc); diff --git a/src/main/java/sevenUnitsGUI/Main.java b/src/main/java/sevenUnitsGUI/Main.java index b5a896f..998b373 100644 --- a/src/main/java/sevenUnitsGUI/Main.java +++ b/src/main/java/sevenUnitsGUI/Main.java @@ -19,12 +19,16 @@ package sevenUnitsGUI; /** * The main code for the 7Units GUI * + * @since v0.4.0 * @since 2022-04-19 */ public final class Main { /** - * @param args + * The main method that starts 7Units + * + * @param args commandline arguments + * @since v0.4.0 * @since 2022-04-19 */ public static void main(String[] args) { diff --git a/src/main/java/sevenUnitsGUI/PrefixSearchRule.java b/src/main/java/sevenUnitsGUI/PrefixSearchRule.java index 2928082..87f14a8 100644 --- a/src/main/java/sevenUnitsGUI/PrefixSearchRule.java +++ b/src/main/java/sevenUnitsGUI/PrefixSearchRule.java @@ -33,24 +33,31 @@ import sevenUnits.unit.UnitPrefix; * A search rule that applies a certain set of prefixes to a unit. It always * includes the original unit in the output map. * + * @since v0.4.0 * @since 2022-07-06 */ public final class PrefixSearchRule implements Function, Map> { /** * A rule that does not add any prefixed versions of units. + * + * @since v0.4.0 */ public static final PrefixSearchRule NO_PREFIXES = getUniversalRule( Set.of()); /** * A rule that gives every unit a common set of prefixes. + * + * @since v0.4.0 */ public static final PrefixSearchRule COMMON_PREFIXES = getCoherentOnlyRule( Set.of(Metric.MILLI, Metric.KILO)); /** * A rule that gives every unit all metric prefixes. + * + * @since v0.4.0 */ public static final PrefixSearchRule ALL_METRIC_PREFIXES = getCoherentOnlyRule( Metric.ALL_PREFIXES); @@ -62,6 +69,7 @@ public final class PrefixSearchRule implements * * @param prefixes prefixes to apply * @return prefix rule + * @since v0.4.0 * @since 2022-07-06 */ public static final PrefixSearchRule getCoherentOnlyRule( @@ -75,6 +83,7 @@ public final class PrefixSearchRule implements * * @param prefixes prefixes to apply * @return prefix rule + * @since v0.4.0 * @since 2022-07-06 */ public static final PrefixSearchRule getUniversalRule( @@ -95,6 +104,7 @@ public final class PrefixSearchRule implements /** * @param prefixes * @param metricOnly + * @since v0.4.0 * @since 2022-07-06 */ public PrefixSearchRule(Set prefixes, @@ -140,6 +150,7 @@ public final class PrefixSearchRule implements /** * @return the allowUnit + * @since v0.4.0 * @since 2022-07-06 */ public Predicate getAllowUnit() { @@ -148,6 +159,7 @@ public final class PrefixSearchRule implements /** * @return the prefixes that are applied by this rule + * @since v0.4.0 * @since 2022-07-06 */ public Set getPrefixes() { diff --git a/src/main/java/sevenUnitsGUI/StandardDisplayRules.java b/src/main/java/sevenUnitsGUI/StandardDisplayRules.java index 0c0ba8e..cc69d31 100644 --- a/src/main/java/sevenUnitsGUI/StandardDisplayRules.java +++ b/src/main/java/sevenUnitsGUI/StandardDisplayRules.java @@ -28,12 +28,14 @@ import sevenUnits.utils.UncertainDouble; * A static utility class that can be used to make display rules for the * presenter. * + * @since v0.4.0 * @since 2022-04-18 */ public final class StandardDisplayRules { /** * A rule that rounds to a fixed number of decimal places. * + * @since v0.4.0 * @since 2022-04-18 */ public static final class FixedDecimals @@ -94,6 +96,7 @@ public final class StandardDisplayRules { /** * A rule that rounds to a fixed number of significant digits. * + * @since v0.4.0 * @since 2022-04-18 */ public static final class FixedPrecision @@ -162,6 +165,7 @@ public final class StandardDisplayRules { * This means the output will have around as many significant figures as the * input. * + * @since v0.4.0 * @since 2022-04-18 */ public static final class UncertaintyBased @@ -188,6 +192,7 @@ public final class StandardDisplayRules { /** * @param decimalPlaces decimal places to round to * @return a rounding rule that rounds to fixed number of decimal places + * @since v0.4.0 * @since 2022-04-18 */ public static final FixedDecimals fixedDecimals(int decimalPlaces) { @@ -198,6 +203,7 @@ public final class StandardDisplayRules { * @param significantFigures significant figures to round to * @return a rounding rule that rounds to a fixed number of significant * figures + * @since v0.4.0 * @since 2022-04-18 */ public static final FixedPrecision fixedPrecision(int significantFigures) { @@ -211,6 +217,7 @@ public final class StandardDisplayRules { * @return display rule * @throws IllegalArgumentException if the provided string is not that of a * standard rule. + * @since v0.4.0 * @since 2021-12-24 */ public static final Function getStandardRule( @@ -236,6 +243,7 @@ public final class StandardDisplayRules { /** * @return an UncertainDouble-based rounding rule + * @since v0.4.0 * @since 2022-04-18 */ public static final UncertaintyBased uncertaintyBased() { diff --git a/src/main/java/sevenUnitsGUI/UnitConversionRecord.java b/src/main/java/sevenUnitsGUI/UnitConversionRecord.java index f951f44..fa64ee9 100644 --- a/src/main/java/sevenUnitsGUI/UnitConversionRecord.java +++ b/src/main/java/sevenUnitsGUI/UnitConversionRecord.java @@ -24,6 +24,7 @@ import sevenUnits.unit.UnitValue; /** * A record of a conversion between units or expressions * + * @since v0.4.0 * @since 2022-04-09 */ public final class UnitConversionRecord { @@ -33,6 +34,7 @@ public final class UnitConversionRecord { * @param input input unit & value * @param output output unit & value * @return unit conversion record + * @since v0.4.0 * @since 2022-04-09 */ public static UnitConversionRecord fromLinearValues(LinearUnitValue input, @@ -49,6 +51,7 @@ public final class UnitConversionRecord { * @param input input unit & value * @param output output unit & value * @return unit conversion record + * @since v0.4.0 * @since 2022-04-09 */ public static UnitConversionRecord fromValues(UnitValue input, @@ -67,6 +70,7 @@ public final class UnitConversionRecord { * @param inputValueString string representing input value * @param outputValueString string representing output value * @return unit conversion record + * @since v0.4.0 * @since 2022-04-09 */ public static UnitConversionRecord valueOf(String fromName, String toName, @@ -143,6 +147,7 @@ public final class UnitConversionRecord { /** * @return name of unit or expression that was converted from + * @since v0.4.0 * @since 2022-04-09 */ public String fromName() { @@ -166,6 +171,7 @@ public final class UnitConversionRecord { /** * @return string representing input value + * @since v0.4.0 * @since 2022-04-09 */ public String inputValueString() { @@ -174,6 +180,7 @@ public final class UnitConversionRecord { /** * @return string representing output value + * @since v0.4.0 * @since 2022-04-09 */ public String outputValueString() { @@ -182,6 +189,7 @@ public final class UnitConversionRecord { /** * @return name of unit or expression that was converted to + * @since v0.4.0 * @since 2022-04-09 */ public String toName() { diff --git a/src/main/java/sevenUnitsGUI/UnitConversionView.java b/src/main/java/sevenUnitsGUI/UnitConversionView.java index 6a95aa5..0d07823 100644 --- a/src/main/java/sevenUnitsGUI/UnitConversionView.java +++ b/src/main/java/sevenUnitsGUI/UnitConversionView.java @@ -23,23 +23,27 @@ import java.util.Set; * A View that supports single unit-based conversion * * @author Adrien Hopkins + * @since v0.4.0 * @since 2021-12-15 */ public interface UnitConversionView extends View { /** * @return dimensions available for filtering + * @since v0.4.0 * @since 2022-01-29 */ Set getDimensionNames(); /** * @return name of unit to convert from + * @since v0.4.0 * @since 2021-12-15 */ Optional getFromSelection(); /** * @return list of names of units available to convert from + * @since v0.4.0 * @since 2022-03-30 */ Set getFromUnitNames(); @@ -47,24 +51,28 @@ public interface UnitConversionView extends View { /** * @return value to convert between the units (specifically, the numeric * string provided by the user) + * @since v0.4.0 * @since 2021-12-15 */ String getInputValue(); /** * @return selected dimension + * @since v0.4.0 * @since 2021-12-15 */ Optional getSelectedDimensionName(); /** * @return name of unit to convert to + * @since v0.4.0 * @since 2021-12-15 */ Optional getToSelection(); /** * @return list of names of units available to convert to + * @since v0.4.0 * @since 2022-03-30 */ Set getToUnitNames(); @@ -73,6 +81,7 @@ public interface UnitConversionView extends View { * Sets the available dimensions for filtering. * * @param dimensionNames names of dimensions to use + * @since v0.4.0 * @since 2021-12-15 */ void setDimensionNames(Set dimensionNames); @@ -83,6 +92,7 @@ public interface UnitConversionView extends View { * that allow the user to select units from a list. * * @param unitNames names of units to convert from + * @since v0.4.0 * @since 2021-12-15 */ void setFromUnitNames(Set unitNames); @@ -93,6 +103,7 @@ public interface UnitConversionView extends View { * that allow the user to select units from a list. * * @param unitNames names of units to convert to + * @since v0.4.0 * @since 2021-12-15 */ void setToUnitNames(Set unitNames); @@ -102,6 +113,7 @@ public interface UnitConversionView extends View { * * @param input input unit & value (obtained from this view) * @param output output unit & value + * @since v0.4.0 * @since 2021-12-24 */ void showUnitConversionOutput(UnitConversionRecord uc); diff --git a/src/main/java/sevenUnitsGUI/View.java b/src/main/java/sevenUnitsGUI/View.java index b2d2b94..bb810ec 100644 --- a/src/main/java/sevenUnitsGUI/View.java +++ b/src/main/java/sevenUnitsGUI/View.java @@ -26,11 +26,13 @@ import sevenUnits.utils.NameSymbol; * An object that controls user interaction with 7Units * * @author Adrien Hopkins + * @since v0.4.0 * @since 2021-12-15 */ public interface View { /** * @return a new tabbed view + * @since v0.4.0 * @since 2022-04-19 */ static View createTabbedView() { @@ -39,18 +41,21 @@ public interface View { /** * @return the presenter associated with this view + * @since v0.4.0 * @since 2022-04-19 */ Presenter getPresenter(); /** * @return name of prefix currently being viewed + * @since v0.4.0 * @since 2022-04-10 */ Optional getViewedPrefixName(); /** * @return name of unit currently being viewed + * @since v0.4.0 * @since 2022-04-10 */ Optional getViewedUnitName(); @@ -60,6 +65,7 @@ public interface View { * viewer * * @param prefixNames prefix names to view + * @since v0.4.0 * @since 2022-04-10 */ void setViewablePrefixNames(Set prefixNames); @@ -68,6 +74,7 @@ public interface View { * Sets the list of units that are available to be viewed in a unit viewer * * @param unitNames unit names to view + * @since v0.4.0 * @since 2022-04-10 */ void setViewableUnitNames(Set unitNames); @@ -78,6 +85,7 @@ public interface View { * @param title title of error message; on any view that uses an error * dialog, this should be the title of the error dialog. * @param message error message + * @since v0.4.0 * @since 2021-12-15 */ void showErrorMessage(String title, String message); @@ -87,6 +95,7 @@ public interface View { * * @param name name(s) and symbol of prefix * @param multiplierString string representation of prefix multiplier + * @since v0.4.0 * @since 2022-04-10 */ void showPrefix(NameSymbol name, String multiplierString); @@ -98,6 +107,7 @@ public interface View { * @param definition unit's definition string * @param dimensionName name of unit's dimension * @param type type of unit (metric/semi-metric/non-metric) + * @since v0.4.0 * @since 2022-04-10 */ void showUnit(NameSymbol name, String definition, String dimensionName, diff --git a/src/main/java/sevenUnitsGUI/ViewBot.java b/src/main/java/sevenUnitsGUI/ViewBot.java index a3ba7a2..e7304c4 100644 --- a/src/main/java/sevenUnitsGUI/ViewBot.java +++ b/src/main/java/sevenUnitsGUI/ViewBot.java @@ -32,6 +32,7 @@ import sevenUnits.utils.Nameable; * for testing. Getters and setters work as expected. * * @author Adrien Hopkins + * @since v0.4.0 * @since 2022-01-29 */ public final class ViewBot -- cgit v1.2.3