/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2013 Ausenco Engineering Canada Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaamsim.input;
import java.util.ArrayList;
import com.jaamsim.Samples.TimeSeriesData;
import com.jaamsim.basicsim.Simulation;
import com.jaamsim.datatypes.DoubleVector;
import com.jaamsim.units.DimensionlessUnit;
import com.jaamsim.units.TimeUnit;
import com.jaamsim.units.Unit;
import com.jaamsim.units.UserSpecifiedUnit;
public class TimeSeriesDataInput extends Input<TimeSeriesData> {
private Class<? extends Unit> unitType;
private double tickLength; // simulation clock tick length used to convert times into ticks
private double maxValue = Double.POSITIVE_INFINITY;
private double minValue = Double.NEGATIVE_INFINITY;
public TimeSeriesDataInput(String key, String cat, TimeSeriesData def) {
super(key, cat, def);
unitType = DimensionlessUnit.class;
}
@Override
public void parse(KeywordIndex kw) throws InputErrorException {
boolean braceOpened = false;
// Set the clock tick length
tickLength = Simulation.getTickLength();
if (unitType == UserSpecifiedUnit.class)
throw new InputErrorException(INP_ERR_UNITUNSPECIFIED);
long startingYearOffset = -1;
long lastTime = -1;
DoubleVector times = new DoubleVector(kw.numArgs()/4);
DoubleVector values = new DoubleVector(kw.numArgs()/4);
// Determine records in the time series
// Records have form: (e.g.) yyyy-MM-dd HH:mm value units
// where units are optional
ArrayList<String> each = new ArrayList<>();
for (int i=0; i < kw.numArgs(); i++) {
//skip over opening brace if present
if (kw.getArg(i).equals("{") ) {
braceOpened = true;
continue;
}
each.clear();
// Load one record into 'each' containing an individual timeseries record
for (int j = i; j < kw.numArgs(); j++, i++){
if (kw.getArg(j).equals("}")) {
braceOpened = false;
break;
}
if (!braceOpened)
throw new InputErrorException("Expected an opening brace ( { ). Received: %s", kw.getArg(j));
each.add(kw.getArg(j));
}
// Time input in RFC8601 date/time format
long recordus;
if (Input.isRFC8601DateTime(each.get(0))) {
Input.assertCountRange(each, 2, 3);
recordus = Input.parseRFC8601DateTime(each.get(0));
each.remove(0);
}
// Time input in number/unit format
else {
// Parse the unit portion of the time input
Input.assertCountRange(each, 3, 4);
TimeUnit unit = Input.tryParseUnit(each.get(1), TimeUnit.class);
if (unit == null)
throw new InputErrorException(INP_ERR_NOUNITFOUND, each.get(1), "TimeUnit");
// Parse the numeric portion of the time input
double factor = unit.getConversionFactorToSI();
recordus = (long) (Input.parseDouble(each.get(0), 0.0, Double.POSITIVE_INFINITY, factor)*1e6);
each.remove(0);
each.remove(0);
}
// Make sure the times are in increasing order
if (recordus <= lastTime)
throw new InputErrorException( "The times must be given in increasing order on " + each.get(0));
lastTime = recordus;
// set the offset to the number of whole years from the first record
if (startingYearOffset == -1) {
startingYearOffset = recordus / Input.usPerYr;
startingYearOffset *= Input.usPerYr;
}
long usOffset = recordus - startingYearOffset;
// Value portion of the record
DoubleVector v = Input.parseDoubles(each, minValue, maxValue, unitType);
// Store the time and value for this record
times.add( usOffset/(1.0e6*tickLength) );
values.add(v.get(0));
}
if (braceOpened)
throw new InputErrorException("Final closing brace ( } ) is missing.");
// Set the value to a new time series data object
value = new TimeSeriesData( times, values );
}
public void setUnitType(Class<? extends Unit> u) {
if (u != unitType)
this.reset();
unitType = u;
}
public double getTickLength() {
return tickLength;
}
}