128 lines
5.5 KiB
Java
128 lines
5.5 KiB
Java
import java.io.*;
|
|
import java.util.Scanner;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
public class ReadDataUtil {
|
|
|
|
private static final Pattern LINE_FORMAT = Pattern.compile("^\\d+(\\.\\d+)?, *[A-Za-z \\d:.-]+(, *[-+]?\\d+(\\.\\d+)?([eE][+-]?\\d+)?){6}, *$");
|
|
private static final Pattern DATE_COLUMN_FORMAT = Pattern.compile("^A\\.D\\. (?<year>\\d{4})-(?<month>[A-Z][a-z]{2})-(?<day>[0-3]\\d) \\d{2}:\\d{2}:\\d{2}(\\.\\d+)?$");
|
|
private static final Pattern DATE_FORMAT_YYYY_MMM_DD = Pattern.compile("^(?<year>\\d{4})-(?<month>[A-Z][a-z]{2})-(?<day>[0-3]\\d)$");
|
|
|
|
/**
|
|
* Reads the position and velocity vector on the specified 'day' from the file with the
|
|
* specified 'path', and sets position and current velocity of 'b' accordingly. If
|
|
* successful the method returns 'true'. If the specified 'day' was not found in the file,
|
|
* 'b' is unchanged and the method returns 'false'.
|
|
* The file format is validated before reading the state.
|
|
* Lines before the line "$$SOE" and after the line "$$EOE" the are ignored. Each line of the
|
|
* file between the line "$$SOE" and the line "$$EOE" is required to have the following format:
|
|
* JDTDB, TIME, X, Y, Z, VX, VY, VZ
|
|
* where JDTDB is interpretable as a 'double' value, TIME is a string and X, Y, Z, VX, VY and
|
|
* VZ are interpretable as 'double' values. JDTDB can be ignored. The character ',' must only
|
|
* be used as field separator. If the file is not found, an exception of the class
|
|
* 'StateFileNotFoundException' is thrown. If it does not comply with the format described
|
|
* above, the method throws an exception of the class 'StateFileFormatException'. Both
|
|
* exceptions are subtypes of 'IOException'.
|
|
* Precondition: b != null, path != null, day != null and has the format YYYY-MM-DD.
|
|
*/
|
|
public static boolean readConfiguration(NamedBody b, String path, String day) throws IOException {
|
|
State state = State.Pre;
|
|
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(path))) {
|
|
Scanner lines = new Scanner(in);
|
|
long lineNum = 0;
|
|
while (lines.hasNextLine() && state != State.Post) {
|
|
lineNum++;
|
|
String line = lines.nextLine();
|
|
State nextState = state.next(line);
|
|
|
|
if (state == State.In && nextState == State.In) {
|
|
Matcher m = LINE_FORMAT.matcher(line);
|
|
if (!m.matches()) {
|
|
throw new StateFileFormatException(path, lineNum);
|
|
}
|
|
|
|
String[] rows = line.split(", *");
|
|
String date;
|
|
try {
|
|
date = convertDateColumn(rows[1]);
|
|
} catch (IllegalArgumentException e) {
|
|
throw new StateFileFormatException(path, lineNum);
|
|
}
|
|
if (date.equals(day)) {
|
|
try {
|
|
double x = Double.parseDouble(rows[2]); // [km]
|
|
double y = Double.parseDouble(rows[3]); // [km]
|
|
double z = Double.parseDouble(rows[4]); // [km]
|
|
double vx = Double.parseDouble(rows[5]); // [km/s]
|
|
double vy = Double.parseDouble(rows[6]); // [km/s]
|
|
double vz = Double.parseDouble(rows[7]); // [km/s]
|
|
b.setState(new Vector3(x * 1000, y * 1000, z * 1000), new Vector3(vx * 1000, vy * 1000, vz * 1000));
|
|
} catch (NumberFormatException e) {
|
|
throw new StateFileFormatException(path, lineNum);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
state = nextState;
|
|
}
|
|
} catch (IOException e) {
|
|
if (e instanceof FileNotFoundException) {
|
|
throw new StateFileNotFoundException(path);
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static String convertDateColumn(String column) {
|
|
Matcher m = DATE_COLUMN_FORMAT.matcher(column);
|
|
if (!m.matches()) {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
|
|
return m.group("year") + "-" + convertMonth(m.group("month")) + "-" + m.group("day");
|
|
}
|
|
|
|
public static String convertDate(String date) {
|
|
Matcher m = DATE_FORMAT_YYYY_MMM_DD.matcher(date);
|
|
if (!m.matches()) {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
return m.group("year") + "-" + convertMonth(m.group("month")) + "-" + m.group("day");
|
|
}
|
|
|
|
private static String convertMonth(String month) {
|
|
return switch (month) {
|
|
case "Jan" -> "01";
|
|
case "Feb" -> "02";
|
|
case "Mar" -> "03";
|
|
case "Apr" -> "04";
|
|
case "May" -> "05";
|
|
case "Jun" -> "06";
|
|
case "Jul" -> "07";
|
|
case "Aug" -> "08";
|
|
case "Sep" -> "09";
|
|
case "Oct" -> "10";
|
|
case "Nov" -> "11";
|
|
case "Dec" -> "12";
|
|
default -> throw new IllegalArgumentException();
|
|
};
|
|
}
|
|
|
|
private enum State {
|
|
Pre, In, Post;
|
|
|
|
public State next(String line) {
|
|
switch (this) {
|
|
case Pre: if (line.equals("$$SOE")) return In; break;
|
|
case In: if (line.equals("$$EOE")) return Post; break;
|
|
case Post: break;
|
|
}
|
|
return this;
|
|
}
|
|
}
|
|
}
|