Skip to content

Commit 96fd1ae

Browse files
committed
Refactor and improve unit conversion engine
1 parent ded5d18 commit 96fd1ae

File tree

66 files changed

+39985
-6067
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+39985
-6067
lines changed

src/main/java/uk/co/ryanharrison/mathengine/gui/Converter.java

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package uk.co.ryanharrison.mathengine.gui;
22

33
import uk.co.ryanharrison.mathengine.unitconversion.ConversionEngine;
4-
import uk.co.ryanharrison.mathengine.unitconversion.units.Conversion;
5-
import uk.co.ryanharrison.mathengine.utils.MathUtils;
4+
import uk.co.ryanharrison.mathengine.unitconversion.ConversionResult;
65
import uk.co.ryanharrison.mathengine.utils.Utils;
76

87
import javax.swing.*;
98
import java.awt.*;
109
import java.awt.datatransfer.StringSelection;
10+
import java.awt.event.ActionListener;
1111

1212
/**
1313
* Interactive GUI for converting values between different units of measurement.
@@ -81,13 +81,14 @@ public static void createAndShow() {
8181
public Converter() {
8282
super(new GridBagLayout());
8383

84-
this.engine = new ConversionEngine();
84+
this.engine = ConversionEngine.loadDefaults();
85+
this.engine.updateTimeZones();
8586

8687
// Initialize components
8788
String[] unitGroups = getTitleCasedUnitGroups();
8889
this.unitGroupBox = createUnitGroupBox(unitGroups);
8990

90-
String[] defaultUnits = engine.getUnitsFor(unitGroupBox.getItemAt(0));
91+
String[] defaultUnits = engine.getUnitsForGroup(unitGroupBox.getItemAt(0)).toArray(new String[0]);
9192
this.fromUnitBox = createFromUnitBox(defaultUnits);
9293
this.toUnitBox = createToUnitBox(defaultUnits);
9394

@@ -106,12 +107,9 @@ public Converter() {
106107
* Gets unit groups from the engine and converts them to title case.
107108
*/
108109
private String[] getTitleCasedUnitGroups() {
109-
String[] groups = engine.getUnitGroups();
110-
String[] titleCased = new String[groups.length];
111-
for (int i = 0; i < groups.length; i++) {
112-
titleCased[i] = Utils.toTitleCase(groups[i]);
113-
}
114-
return titleCased;
110+
return engine.getUnitGroupNames().stream()
111+
.map(Utils::toTitleCase)
112+
.toArray(String[]::new);
115113
}
116114

117115
/**
@@ -252,13 +250,37 @@ private void buildLayout() {
252250
*/
253251
private void onUnitGroupChanged() {
254252
String selectedGroup = unitGroupBox.getItemAt(unitGroupBox.getSelectedIndex());
255-
String[] newUnits = engine.getUnitsFor(selectedGroup);
253+
String[] newUnits = engine.getUnitsForGroup(selectedGroup).toArray(new String[0]);
254+
255+
// Remove listeners to prevent conversion attempts while updating
256+
ActionListener[] fromListeners = fromUnitBox.getActionListeners();
257+
ActionListener[] toListeners = toUnitBox.getActionListeners();
258+
259+
for (ActionListener listener : fromListeners) {
260+
fromUnitBox.removeActionListener(listener);
261+
}
262+
for (ActionListener listener : toListeners) {
263+
toUnitBox.removeActionListener(listener);
264+
}
256265

266+
// Update items
257267
replaceComboBoxItems(fromUnitBox, newUnits);
258268
replaceComboBoxItems(toUnitBox, newUnits);
259269

260-
fromUnitBox.setSelectedIndex(2);
261-
toUnitBox.setSelectedIndex(3);
270+
// Set default selections
271+
if (newUnits.length > 2) fromUnitBox.setSelectedIndex(2);
272+
if (newUnits.length > 3) toUnitBox.setSelectedIndex(3);
273+
274+
// Re-add listeners
275+
for (ActionListener listener : fromListeners) {
276+
fromUnitBox.addActionListener(listener);
277+
}
278+
for (ActionListener listener : toListeners) {
279+
toUnitBox.addActionListener(listener);
280+
}
281+
282+
// Clear any previous results
283+
resultValueField.setText("");
262284
}
263285

264286
/**
@@ -286,11 +308,13 @@ private void performConversion() {
286308

287309
try {
288310
double value = Double.parseDouble(fromValueField.getText());
289-
double result = engine.convertAsDouble(value, fromUnit, toUnit);
290-
double rounded = MathUtils.round(result, DECIMAL_PLACES);
291-
resultValueField.setText(Double.toString(rounded));
311+
double result = engine.convertToDouble(value, fromUnit, toUnit, DECIMAL_PLACES);
312+
resultValueField.setText(Double.toString(result));
292313
} catch (NumberFormatException ex) {
293314
showErrorDialog("Numerical input expected");
315+
} catch (IllegalArgumentException ex) {
316+
showErrorDialog(ex.getMessage());
317+
resultValueField.setText("");
294318
}
295319
}
296320

@@ -305,17 +329,17 @@ private void convertFromString(String text) {
305329
}
306330

307331
try {
308-
Conversion result = engine.convert(text);
332+
ConversionResult result = engine.convertFromString(text);
309333

310334
// Update UI to reflect the conversion
311-
String unitGroup = Utils.toTitleCase(engine.getUnitGroupOfSubUnit(result.getFrom()));
335+
String unitGroup = Utils.toTitleCase(result.groupName());
312336
unitGroupBox.setSelectedItem(unitGroup);
313337

314-
fromUnitBox.setSelectedItem(result.getFrom().toString());
315-
toUnitBox.setSelectedItem(result.getTo().toString());
338+
fromUnitBox.setSelectedItem(result.fromUnit().getPlural());
339+
toUnitBox.setSelectedItem(result.toUnit().getPlural());
316340

317-
resultValueField.setText(Double.toString(result.getResult().doubleValue()));
318-
fromValueField.setText(Double.toString(result.getValue().doubleValue()));
341+
resultValueField.setText(Double.toString(result.result().doubleValue()));
342+
fromValueField.setText(Double.toString(result.inputValue().doubleValue()));
319343

320344
} catch (IllegalArgumentException ex) {
321345
showErrorDialog(ex.getLocalizedMessage());

src/main/java/uk/co/ryanharrison/mathengine/parser/nodes/NodeUnit.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
package uk.co.ryanharrison.mathengine.parser.nodes;
22

3-
import uk.co.ryanharrison.mathengine.unitconversion.units.SubUnit;
3+
import uk.co.ryanharrison.mathengine.unitconversion.units.Unit;
44

55
import java.util.Objects;
66

77
public class NodeUnit extends NodeDouble {
88

9-
private Node value;
10-
private SubUnit unit;
11-
private boolean hasValue;
9+
private final Node value;
10+
private final Unit unit;
11+
private final boolean hasValue;
1212

13-
public NodeUnit(SubUnit unit, Node val) {
13+
public NodeUnit(Unit unit, Node val) {
1414
this(unit, val, true);
1515
}
1616

17-
private NodeUnit(SubUnit unit, Node val, boolean hasValue) {
17+
private NodeUnit(Unit unit, Node val, boolean hasValue) {
1818
super(1.0);
1919
this.unit = unit;
2020
this.value = val;
2121
this.hasValue = hasValue;
2222
}
2323

24-
public SubUnit getUnit() {
24+
public Unit getUnit() {
2525
return unit;
2626
}
2727

src/main/java/uk/co/ryanharrison/mathengine/parser/operators/binary/Convert.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
import uk.co.ryanharrison.mathengine.parser.nodes.NodeUnit;
77
import uk.co.ryanharrison.mathengine.parser.operators.BinaryOperator;
88
import uk.co.ryanharrison.mathengine.unitconversion.ConversionEngine;
9-
import uk.co.ryanharrison.mathengine.unitconversion.units.Conversion;
9+
import uk.co.ryanharrison.mathengine.unitconversion.ConversionResult;
1010

1111
public class Convert extends BinaryOperator {
12+
private static final ConversionEngine ENGINE = ConversionEngine.loadDefaults();
13+
1214
@Override
1315
public String[] getAliases() {
1416
return new String[]{"in", "to", "as", "convert"};
@@ -26,17 +28,15 @@ public String toLongString() {
2628

2729
@Override
2830
public NodeConstant toResult(NodeConstant arg1, NodeConstant arg2) {
29-
if (arg1 instanceof NodeUnit && arg2 instanceof NodeUnit) {
30-
NodeUnit unit1 = (NodeUnit) arg1;
31-
NodeUnit unit2 = (NodeUnit) arg2;
32-
33-
Conversion result = ConversionEngine.getInstance().convert(unit1.doubleValue(), unit1.getUnit()
34-
.getSingular(), unit2.getUnit().getSingular());
35-
36-
NodeNumber value = NodeFactory.createNodeNumberFrom(result.getResult().doubleValue());
37-
38-
NodeUnit unit = new NodeUnit(result.getTo(), value);
39-
return unit;
31+
if (arg1 instanceof NodeUnit unit1 && arg2 instanceof NodeUnit unit2) {
32+
ConversionResult result = ENGINE.convert(
33+
unit1.doubleValue(),
34+
unit1.getUnit().getSingular(),
35+
unit2.getUnit().getSingular()
36+
);
37+
38+
NodeNumber value = NodeFactory.createNodeNumberFrom(result.result().doubleValue());
39+
return new NodeUnit(result.toUnit(), value);
4040
}
4141

4242
throw new IllegalArgumentException("Incorrect conversion parameters");

0 commit comments

Comments
 (0)