Skip to content

Commit

Permalink
Add fractional time-shift
Browse files Browse the repository at this point in the history
Add the ability to time-shift with fractional input, e.g. 365,330.75 days. Input can now be floating point rather than integer. Input must be a non-fractional number of seconds.
  • Loading branch information
Tom Brauer committed Jul 1, 2024
1 parent 8dec8e5 commit 2632b29
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package mil.army.usace.hec.vortex.math;

public enum ShiftTimeUnit {
DAYS("Days", 86400),
HOURS("Hours", 3600),
MINUTES("Minutes", 60),
SECONDS("Seconds", 1);

private final String displayString;
private final int toSeconds;

ShiftTimeUnit(String displayString, int toSeconds) {
this.displayString = displayString;
this.toSeconds = toSeconds;
}

public int toSeconds() {
return toSeconds;
}

@Override
public String toString() {
return displayString;
}

public static ShiftTimeUnit fromString(String string) {
for (ShiftTimeUnit value : values()) {
String displayString = value.toString();
if (displayString.equalsIgnoreCase(string))
return value;
}
throw new IllegalArgumentException("Time unit string + \"" + string + "\" not recognized");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package mil.army.usace.hec.vortex.ui;

import mil.army.usace.hec.vortex.math.ShiftTimeUnit;

import javax.swing.*;
import java.util.Arrays;

class ShiftTimeUnitComboBox extends JComboBox<String> {

ShiftTimeUnitComboBox() {
String[] selections = Arrays.stream(ShiftTimeUnit.values())
.map(ShiftTimeUnit::toString)
.toArray(String[]::new);

setModel(new DefaultComboBoxModel<>(selections));

setSelectedIndex(1);
}

ShiftTimeUnit getSelected() {
String selected = String.valueOf(getSelectedItem());
return ShiftTimeUnit.fromString(selected);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package mil.army.usace.hec.vortex.ui;

import mil.army.usace.hec.vortex.math.ShiftTimeUnit;
import mil.army.usace.hec.vortex.math.TimeShiftMethod;
import mil.army.usace.hec.vortex.math.Shifter;
import mil.army.usace.hec.vortex.ui.util.FileSaveUtil;
Expand Down Expand Up @@ -28,7 +29,7 @@ public class ShifterWizard extends VortexWizard {
private JCheckBox startTimeCheckBox;
private JCheckBox endTimeCheckBox;
private JTextField intervalTextField;
private JComboBox<String> intervalComboBox;
private ShiftTimeUnitComboBox shiftTimeUnitComboBox;
private JList<String> chosenSourceGridsList;
private JProgressBar progressBar;

Expand Down Expand Up @@ -246,8 +247,6 @@ private JPanel stepTwoPanel() {
}

private boolean validateStepTwo() {
String intervalText = intervalTextField.getText();

/* Check that start time, end time, or both are selected */
if (!startTimeCheckBox.isSelected() && !endTimeCheckBox.isSelected()) {
String message = "Start time, end time, or both start time and end time must be selected.";
Expand All @@ -257,11 +256,30 @@ private boolean validateStepTwo() {
}

/* Check for at least one entry */
String intervalText = intervalTextField.getText();
if (intervalText.isEmpty()) {
JOptionPane.showMessageDialog(this, "Shift value required.",
"Error", JOptionPane.ERROR_MESSAGE);
return false;
}

double interval;
try {
interval = Double.parseDouble(intervalText);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Could not parse interval.",
"Error", JOptionPane.ERROR_MESSAGE);
return false;
}

ShiftTimeUnit timeUnit = shiftTimeUnitComboBox.getSelected();
if (!validateInterval(interval, timeUnit)) {
String message = "Specified interval is cannot be converted to an even number of seconds.";
JOptionPane.showMessageDialog(this, message,
"Error", JOptionPane.ERROR_MESSAGE);
return false;
}

return true;
}

Expand All @@ -288,18 +306,15 @@ private JPanel stepTwoIntervalPanel() {
/* Interval Panel */
JLabel shiftLabel = new JLabel(TextProperties.getInstance().getProperty("ShifterWiz_TimeShift_L"));
intervalTextField = new JTextField(25);
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
model.addAll(Arrays.asList("Days", "Hours", "Minutes", "Seconds"));
intervalComboBox = new JComboBox<>(model);
intervalComboBox.setEnabled(true);
intervalComboBox.setSelectedIndex(1);
shiftTimeUnitComboBox = new ShiftTimeUnitComboBox();
shiftTimeUnitComboBox.setEnabled(true);

JPanel setIntervalPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
setIntervalPanel.add(shiftLabel);
setIntervalPanel.add(Box.createRigidArea(new Dimension(2,0)));
setIntervalPanel.add(intervalTextField);
setIntervalPanel.add(Box.createRigidArea(new Dimension(2,0)));
setIntervalPanel.add(intervalComboBox);
setIntervalPanel.add(shiftTimeUnitComboBox);

/* Adding everything together */
JPanel intervalPanel = new JPanel();
Expand Down Expand Up @@ -355,26 +370,16 @@ private void timeShifterTask() {
if (startTimeCheckBox.isSelected()) methods.add(TimeShiftMethod.START);
if (endTimeCheckBox.isSelected()) methods.add(TimeShiftMethod.END);

Object selectedTimeUnit = intervalComboBox.getSelectedItem();
if(selectedTimeUnit == null) return;
String intervalType = selectedTimeUnit.toString();
String intervalAmount = intervalTextField.getText();

Duration interval;
switch (intervalType) {
case "Days":
interval = Duration.ofDays(Integer.parseInt(intervalAmount));
break;
case "Hours":
interval = Duration.ofHours(Integer.parseInt(intervalAmount));
break;
case "Seconds":
interval = Duration.ofSeconds(Integer.parseInt(intervalAmount));
break;
default:
interval = Duration.ofMinutes(Integer.parseInt(intervalAmount));
break;
}
String intervalText = intervalTextField.getText();
double value = Float.parseFloat(intervalText);

ShiftTimeUnit timeUnit = shiftTimeUnitComboBox.getSelected();
int toSeconds = timeUnit.toSeconds();

// Cast is validated on step 2 of the wizard
long seconds = (long) value * toSeconds;

Duration interval = Duration.ofSeconds(seconds);

String destination = destinationSelectionPanel.getDestinationTextField().getText();

Expand Down Expand Up @@ -482,6 +487,15 @@ private void closeAction() {
FileSaveUtil.showFileLocation(ShifterWizard.this, Path.of(savedFile));
}

private boolean validateInterval(double value, ShiftTimeUnit timeUnit) {
int toSeconds = timeUnit.toSeconds();
double doubleValue = value * toSeconds;
long longValue = (long) doubleValue;

// Check if there is any remainder after casting
return Double.compare(longValue, doubleValue) == 0;
}

/* Add main for quick UI Testing */
public static void main(String[] args) {
try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }
Expand Down

0 comments on commit 2632b29

Please sign in to comment.