package net.sf.openrocket.file;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.simulation.FlightData;
import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightDataType;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.util.TextUtil;
public class CSVExport {
/**
* Exports the specified flight data branch into a CSV file.
*
* @param stream the stream to write to.
* @param simulation the simulation being exported.
* @param branch the branch to export.
* @param fields the fields to export (in appropriate order).
* @param units the units of the fields.
* @param fieldSeparator the field separator string.
* @param commentStarter the comment starting character(s).
* @param simulationComments whether to output general simulation comments.
* @param fieldComments whether to output field comments.
* @param eventComments whether to output comments for the flight events.
* @throws IOException if an I/O exception occurs.
*/
public static void exportCSV(OutputStream stream, Simulation simulation,
FlightDataBranch branch, FlightDataType[] fields, Unit[] units,
String fieldSeparator, String commentStarter, boolean simulationComments,
boolean fieldComments, boolean eventComments) throws IOException {
if (fields.length != units.length) {
throw new IllegalArgumentException("fields and units lengths must be equal " +
"(" + fields.length + " vs " + units.length + ")");
}
PrintWriter writer = null;
try {
writer = new PrintWriter(stream);
// Write the initial comments
if (simulationComments) {
writeSimulationComments(writer, simulation, branch, fields, commentStarter);
}
if (simulationComments && fieldComments) {
writer.println(commentStarter);
}
if (fieldComments) {
writer.print(commentStarter + " ");
for (int i = 0; i < fields.length; i++) {
writer.print(fields[i].getName() + " (" + units[i].getUnit() + ")");
if (i < fields.length - 1) {
writer.print(fieldSeparator);
}
}
writer.println();
}
writeData(writer, branch, fields, units, fieldSeparator,
eventComments, commentStarter);
} finally {
if (writer != null) {
try {
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private static void writeData(PrintWriter writer, FlightDataBranch branch,
FlightDataType[] fields, Unit[] units, String fieldSeparator, boolean eventComments,
String commentStarter) {
// Number of data points
int n = branch.getLength();
// Flight events in occurrance order
List<FlightEvent> events = branch.getEvents();
Collections.sort(events);
int eventPosition = 0;
// List of field values
List<List<Double>> fieldValues = new ArrayList<List<Double>>();
for (FlightDataType t : fields) {
fieldValues.add(branch.get(t));
}
// Time variable
List<Double> time = branch.get(FlightDataType.TYPE_TIME);
if (eventComments && time == null) {
// If time information is not available, print events at beginning of file
for (FlightEvent e : events) {
printEvent(writer, e, commentStarter);
}
eventPosition = events.size();
}
// Loop over all data points
for (int pos = 0; pos < n; pos++) {
// Check for events to store
if (eventComments && time != null) {
double t = time.get(pos);
while ((eventPosition < events.size()) &&
(events.get(eventPosition).getTime() <= t)) {
printEvent(writer, events.get(eventPosition), commentStarter);
eventPosition++;
}
}
// Store CSV line
for (int i = 0; i < fields.length; i++) {
double value = fieldValues.get(i).get(pos);
writer.print(TextUtil.doubleToString(units[i].toUnit(value)));
if (i < fields.length - 1) {
writer.print(fieldSeparator);
}
}
writer.println();
}
// Store any remaining events
if (eventComments && time != null) {
while (eventPosition < events.size()) {
printEvent(writer, events.get(eventPosition), commentStarter);
eventPosition++;
}
}
}
private static void printEvent(PrintWriter writer, FlightEvent e,
String commentStarter) {
writer.println(commentStarter + " Event " + e.getType().name() +
" occurred at t=" + TextUtil.doubleToString(e.getTime()) + " seconds");
}
private static void writeSimulationComments(PrintWriter writer,
Simulation simulation, FlightDataBranch branch, FlightDataType[] fields,
String commentStarter) {
String line;
line = simulation.getName();
FlightData data = simulation.getSimulatedData();
switch (simulation.getStatus()) {
case UPTODATE:
line += " (Up to date)";
break;
case LOADED:
line += " (Data loaded from a file)";
break;
case OUTDATED:
line += " (Data is out of date)";
break;
case EXTERNAL:
line += " (Imported data)";
break;
case NOT_SIMULATED:
line += " (Not simulated yet)";
break;
}
writer.println(commentStarter + " " + line);
writer.println(commentStarter + " " + branch.getLength() + " data points written for "
+ fields.length + " variables.");
if (data == null) {
writer.println(commentStarter + " No simulation data available.");
return;
}
WarningSet warnings = data.getWarningSet();
if (!warnings.isEmpty()) {
writer.println(commentStarter + " Simulation warnings:");
for (Warning w : warnings) {
writer.println(commentStarter + " " + w.toString());
}
}
}
}