create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / file / CSVExport.java
1 package net.sf.openrocket.file;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.io.PrintWriter;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.List;
9
10 import net.sf.openrocket.aerodynamics.Warning;
11 import net.sf.openrocket.aerodynamics.WarningSet;
12 import net.sf.openrocket.document.Simulation;
13 import net.sf.openrocket.simulation.FlightData;
14 import net.sf.openrocket.simulation.FlightDataBranch;
15 import net.sf.openrocket.simulation.FlightDataType;
16 import net.sf.openrocket.simulation.FlightEvent;
17 import net.sf.openrocket.unit.Unit;
18 import net.sf.openrocket.util.TextUtil;
19
20 public class CSVExport {
21         
22         /**
23          * Exports the specified flight data branch into a CSV file.
24          * 
25          * @param stream                                the stream to write to.
26          * @param simulation                    the simulation being exported.
27          * @param branch                                the branch to export.
28          * @param fields                                the fields to export (in appropriate order).
29          * @param units                                 the units of the fields.
30          * @param fieldSeparator                the field separator string.
31          * @param commentStarter                the comment starting character(s).
32          * @param simulationComments    whether to output general simulation comments.
33          * @param fieldComments                 whether to output field comments.
34          * @param eventComments                 whether to output comments for the flight events.
35          * @throws IOException                  if an I/O exception occurs.
36          */
37         public static void exportCSV(OutputStream stream, Simulation simulation,
38                         FlightDataBranch branch, FlightDataType[] fields, Unit[] units,
39                         String fieldSeparator, String commentStarter, boolean simulationComments,
40                         boolean fieldComments, boolean eventComments) throws IOException {
41                 
42                 if (fields.length != units.length) {
43                         throw new IllegalArgumentException("fields and units lengths must be equal " +
44                                         "(" + fields.length + " vs " + units.length + ")");
45                 }
46                 
47
48                 PrintWriter writer = null;
49                 try {
50                         
51                         writer = new PrintWriter(stream);
52                         
53                         // Write the initial comments
54                         if (simulationComments) {
55                                 writeSimulationComments(writer, simulation, branch, fields, commentStarter);
56                         }
57                         
58                         if (simulationComments && fieldComments) {
59                                 writer.println(commentStarter);
60                         }
61                         
62                         if (fieldComments) {
63                                 writer.print(commentStarter + " ");
64                                 for (int i = 0; i < fields.length; i++) {
65                                         writer.print(fields[i].getName() + " (" + units[i].getUnit() + ")");
66                                         if (i < fields.length - 1) {
67                                                 writer.print(fieldSeparator);
68                                         }
69                                 }
70                                 writer.println();
71                         }
72                         
73                         writeData(writer, branch, fields, units, fieldSeparator,
74                                         eventComments, commentStarter);
75                         
76
77                 } finally {
78                         if (writer != null) {
79                                 try {
80                                         writer.close();
81                                 } catch (Exception e) {
82                                         e.printStackTrace();
83                                 }
84                         }
85                 }
86         }
87         
88         private static void writeData(PrintWriter writer, FlightDataBranch branch,
89                         FlightDataType[] fields, Unit[] units, String fieldSeparator, boolean eventComments,
90                         String commentStarter) {
91                 
92                 // Number of data points
93                 int n = branch.getLength();
94                 
95                 // Flight events in occurrance order
96                 List<FlightEvent> events = branch.getEvents();
97                 Collections.sort(events);
98                 int eventPosition = 0;
99                 
100                 // List of field values
101                 List<List<Double>> fieldValues = new ArrayList<List<Double>>();
102                 for (FlightDataType t : fields) {
103                         fieldValues.add(branch.get(t));
104                 }
105                 
106                 // Time variable
107                 List<Double> time = branch.get(FlightDataType.TYPE_TIME);
108                 if (eventComments && time == null) {
109                         // If time information is not available, print events at beginning of file
110                         for (FlightEvent e : events) {
111                                 printEvent(writer, e, commentStarter);
112                         }
113                         eventPosition = events.size();
114                 }
115                 
116
117                 // Loop over all data points
118                 for (int pos = 0; pos < n; pos++) {
119                         
120                         // Check for events to store
121                         if (eventComments && time != null) {
122                                 double t = time.get(pos);
123                                 
124                                 while ((eventPosition < events.size()) &&
125                                                 (events.get(eventPosition).getTime() <= t)) {
126                                         printEvent(writer, events.get(eventPosition), commentStarter);
127                                         eventPosition++;
128                                 }
129                         }
130                         
131                         // Store CSV line
132                         for (int i = 0; i < fields.length; i++) {
133                                 double value = fieldValues.get(i).get(pos);
134                                 writer.print(TextUtil.doubleToString(units[i].toUnit(value)));
135                                 if (i < fields.length - 1) {
136                                         writer.print(fieldSeparator);
137                                 }
138                         }
139                         writer.println();
140                         
141                 }
142                 
143                 // Store any remaining events
144                 if (eventComments && time != null) {
145                         while (eventPosition < events.size()) {
146                                 printEvent(writer, events.get(eventPosition), commentStarter);
147                                 eventPosition++;
148                         }
149                 }
150                 
151         }
152         
153         
154         private static void printEvent(PrintWriter writer, FlightEvent e,
155                         String commentStarter) {
156                 writer.println(commentStarter + " Event " + e.getType().name() +
157                                 " occurred at t=" + TextUtil.doubleToString(e.getTime()) + " seconds");
158         }
159         
160         private static void writeSimulationComments(PrintWriter writer,
161                         Simulation simulation, FlightDataBranch branch, FlightDataType[] fields,
162                         String commentStarter) {
163                 
164                 String line;
165                 
166                 line = simulation.getName();
167                 
168                 FlightData data = simulation.getSimulatedData();
169                 
170                 switch (simulation.getStatus()) {
171                 case UPTODATE:
172                         line += " (Up to date)";
173                         break;
174                 
175                 case LOADED:
176                         line += " (Data loaded from a file)";
177                         break;
178                 
179                 case OUTDATED:
180                         line += " (Data is out of date)";
181                         break;
182                 
183                 case EXTERNAL:
184                         line += " (Imported data)";
185                         break;
186                 
187                 case NOT_SIMULATED:
188                         line += " (Not simulated yet)";
189                         break;
190                 }
191                 
192                 writer.println(commentStarter + " " + line);
193                 
194
195                 writer.println(commentStarter + " " + branch.getLength() + " data points written for "
196                                 + fields.length + " variables.");
197                 
198
199                 if (data == null) {
200                         writer.println(commentStarter + " No simulation data available.");
201                         return;
202                 }
203                 WarningSet warnings = data.getWarningSet();
204                 
205                 if (!warnings.isEmpty()) {
206                         writer.println(commentStarter + " Simulation warnings:");
207                         for (Warning w : warnings) {
208                                 writer.println(commentStarter + "   " + w.toString());
209                         }
210                 }
211         }
212         
213 }