package nl.wldelft.timeseriesparsers;
import nl.wldelft.util.FastDateFormat;
import nl.wldelft.util.io.LineReader;
import nl.wldelft.util.io.TextParser;
import nl.wldelft.util.timeseries.DefaultTimeSeriesHeader;
import nl.wldelft.util.timeseries.TimeSeriesContentHandler;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
public class OttawaRiverRegulationPlanningBoardSHTTimeSeriesParser implements TextParser<TimeSeriesContentHandler> {
public static final TimeZone EST = TimeZone.getTimeZone("EST");
private static final FastDateFormat DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd", EST, Locale.CANADA, null);
@Override
public void parse(LineReader reader, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {
String[] buffer = reader.readLine(' ');
String forecastDateStart = buffer[buffer.length - 1];
// This is the date when forecasting starts.
Date date = DATE_FORMAT.parse(forecastDateStart);
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(EST);
calendar.setTime(date);
DefaultTimeSeriesHeader forecastHeader = new DefaultTimeSeriesHeader();
DefaultTimeSeriesHeader observationHeader = new DefaultTimeSeriesHeader();
forecastHeader.setForecastTime(EST, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), 0);
reader.skipLines(24);
// Collecting days from the next row
String[] days = reader.readLine(' ');
reader.skipLines(3);
// Finding out if there is a column with stars, separating the prior days
int starIndex = -1;
for (int i = 0; i < days.length; i++) {
if (days[i].equals("*")) {
// +2 is added because starting from the table rows, parameter and location columns are added too.
starIndex = i + 2;
}
}
// location and parameter are added since reading the next line
buffer = new String[days.length + 2];
reader.readLine(' ', buffer);
// Until we reach the end of the table, in which case the length of the buffer would get 3.
while (buffer.length > 3) {
forecastHeader.setLocationId(buffer[0]);
forecastHeader.setParameterId(buffer[1]);
observationHeader.setLocationId(buffer[0]);
observationHeader.setParameterId(buffer[1]);
for (int i = 2; i < buffer.length; i++) {
// Storing measurements
if (i < starIndex) {
// The qualifier "Obs" is used for observation values
forecastHeader.setQualifierIds("Obs");
if (i == 2) {
calendar.add(Calendar.DAY_OF_YEAR, -(starIndex - 2));
} else {
calendar.add(Calendar.DAY_OF_YEAR, 1);
}
contentHandler.setTime(EST, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), 0);
contentHandler.setValue(Float.parseFloat(buffer[i]));
contentHandler.setTimeSeriesHeader(observationHeader);
} else if (i > starIndex) {
// Storing forecast values
forecastHeader.setQualifierIds("Sim");
calendar.add(Calendar.DAY_OF_YEAR, 1);
contentHandler.setTime(EST, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), 0);
contentHandler.setValue(Float.parseFloat(buffer[i]));
contentHandler.setTimeSeriesHeader(forecastHeader);
} else {
continue; // Do nothing when reaching the star column
}
contentHandler.applyCurrentFields();
}
calendar.setTime(date); // reset the date back to the forecasting date
buffer = reader.readLine(' ');
}
}
}