1 package net.sf.tourviewer.lib.ciclo;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.text.ParseException;
8 import java.text.SimpleDateFormat;
9 import java.util.Calendar;
10 import java.util.Date;
11 import net.sf.tourviewer.lib.Tour;
12 import net.sf.tourviewer.lib.TourRecord;
13 import net.sf.tourviewer.lib.TourSet;
14 import net.sf.tourviewer.lib.Tour.Type;
15
16 public class CicloTurReader
17 {
18
19 private static final String FILE_SIGNATURE = "HACtronic";
20 private int currentLine;
21 BufferedReader in;
22
23 public boolean accept(InputStream in) throws IOException {
24 byte[] buffer = new byte[FILE_SIGNATURE.length()];
25 in.mark(buffer.length);
26 in.read(buffer);
27
28 try {
29 return FILE_SIGNATURE.equalsIgnoreCase(new String(buffer));
30 }
31 finally {
32 in.reset();
33 }
34 }
35
36 public TourSet read(InputStream inStream) throws IOException {
37 in = new BufferedReader(new InputStreamReader(inStream));
38
39 TourSet tourSet = new TourSet();
40 Tour tour = new Tour();
41 tour.setAutoStatistics(false);
42 try {
43 String signature = readLine();
44 int version1 = Integer.parseInt(readLine());
45 int version2 = Integer.parseInt(readLine());
46 int version3 = Integer.parseInt(readLine());
47 tour.setTitle(readLine());
48 tour.setStartLocation(readLine());
49 tour.setEndLocation(readLine());
50 String date = readLine();
51 String time = readLine();
52 tour.setStartTime(parseTime(date, time));
53 StringBuffer sb = new StringBuffer();
54 int noteCount = Integer.parseInt(readLine());
55 for (int i = 0; i < noteCount; i++) {
56 sb.append(readLine());
57 }
58 tour.setNote(sb.toString());
59 tour.setDistance(Integer.parseInt(readLine()));
60
61 int tourDurance = Integer.parseInt(readLine());
62 readLine();
63 tour.setMaxAltitude(Integer.parseInt(readLine()));
64 int diffAltitude = Integer.parseInt(readLine());
65 tour.setAvgAltitudeInc(Double.parseDouble(readLine()));
66 tour.setAvgSlope(Double.parseDouble(readLine()));
67 tour.setAvgSpeed(Double.parseDouble(readLine()));
68 tour.setAvgTemperature(Double.parseDouble(readLine()));
69 tour.setAvgPulse(Double.parseDouble(readLine()));
70 readLine();
71 tour.setType(parseType(Integer.parseInt(readLine()), version2));
72 readLine();
73 readLine();
74 readLine();
75 readLine();
76 readLine();
77 readLine();
78 readLine();
79 readLine();
80 tourSet.setPersonName(parseName(readLine(), readLine()));
81 tourSet.setDateOfBirth(parseDate(readLine().trim()));
82 String team = readLine();
83 tourSet.setPersonWeight(Integer.parseInt(readLine()));
84 int pulseLow = Integer.parseInt(readLine());
85 int pulseHigh = Integer.parseInt(readLine());
86 String material = readLine();
87 int materialWeight = Integer.parseInt(readLine());
88 tourSet.setTotalDistance(Integer.parseInt(readLine()));
89 tourSet.setTotalTravelTime(Integer.parseInt(readLine()));
90 tourSet.setTotalAltitudeUp(Integer.parseInt(readLine()));
91 tourSet.setTotalAltitudeDown(Integer.parseInt(readLine()));
92 readLine();
93 readLine();
94 readLine();
95 readLine();
96 readLine();
97 readLine();
98 readLine();
99 readLine();
100 readLine();
101 readLine();
102 int recordCount = Integer.parseInt(readLine());
103 TourRecord lastRecord = readRecords(tour, recordCount);
104 if (recordCount > 0) {
105 readLine();
106 tour.setEndTime(lastRecord.getTime());
107 tour.setDistance(lastRecord.getDistance());
108 }
109 int markerCount = Integer.parseInt(readLine()); currentLine++;
110 readMarkers(tour, markerCount);
111 if (markerCount > 0) {
112 readLine();
113 }
114 }
115 catch (NumberFormatException e) {
116 e.printStackTrace();
117 throw new IOException("Invalid data in line " + currentLine + ", expected number");
118 }
119 catch (ParseException e) {
120 e.printStackTrace();
121 throw new IOException("Invalid data format in line " + currentLine);
122 }
123
124 tourSet.addTour(tour);
125 return tourSet;
126 }
127
128 private Type parseType(int mode, int version)
129 {
130
131 if (version == 1) {
132 switch (mode) {
133 case 0:
134 return Type.JOGGING;
135 case 2:
136 return Type.BIKE;
137 case 3:
138 return Type.SKI_BIKE;
139 }
140 }
141 else if (version == 2) {
142 switch (mode) {
143 case 2:
144 return Type.BIKE;
145 case 3:
146 return Type.BIKE;
147 }
148 }
149 return Type.OTHER;
150 }
151
152 private String parseName(String surname, String firstName)
153 {
154 return (firstName.length() == 0) ? surname : (surname.length() == 0) ? firstName
155 : surname + ", " + firstName;
156 }
157
158 private Date parseDate(String date) throws ParseException
159 {
160 if (date.length() == 0 || date.startsWith(".")) {
161 return null;
162 }
163 SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
164 return format.parse(date);
165 }
166
167 private Date parseTime(String date, String time) throws ParseException
168 {
169 SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm");
170 return format.parse(date + " " + time);
171 }
172
173 private TourRecord readRecords(Tour tour, int recordCount) throws IOException
174 {
175 if (recordCount <= 0) {
176 throw new IllegalArgumentException("recordCount must be greater than 0");
177 }
178
179 TourRecord record = null;
180 for (int i = 0; i < recordCount; i++) {
181 record = new TourRecord();
182 Calendar cal = Calendar.getInstance();
183 long date = (readUnsignedInt() - 86400) * 1000;
184 cal.setTimeInMillis(date - cal.getTimeZone().getOffset(date));
185 record.setTime(cal.getTime());
186 readInt();
187 record.setDistance(readInt() * 10);
188 record.setAltitude(readSignedShort());
189 record.setPulse(readUnsignedByte());
190 record.setCadence(readSignedByte());
191 record.setTemperature(readSignedByte());
192 readSignedByte();
193 readSignedByte();
194 readSignedByte();
195 tour.addRecord(record);
196 }
197 return record;
198 }
199
200 int readUnsignedByte() throws IOException
201 {
202 char[] buffer = new char[1];
203 if (in.read(buffer, 0, 1) == 1) {
204 return (int)buffer[0];
205 }
206 else {
207 throw new IOException("Unexpected end of file");
208 }
209 }
210
211 private void readMarkers(Tour tour, int markerCount)
212 {
213
214 }
215
216 int readSignedByte() throws IOException
217 {
218 char[] buffer = new char[1];
219 if (in.read(buffer, 0, 1) == 1) {
220 return (byte)buffer[0];
221 }
222 else {
223 throw new IOException("Unexpected end of file");
224 }
225 }
226
227 int readSignedShort() throws IOException
228 {
229 char[] buffer = new char[2];
230 if (in.read(buffer, 0, 2) == 2) {
231 return (short)(buffer[1] << 8 | buffer[0]);
232 }
233 else {
234 throw new IOException("Unexpected end of file");
235 }
236 }
237
238 long readUnsignedInt() throws IOException
239 {
240 char[] buffer = new char[4];
241 if (in.read(buffer, 0, 4) == 4) {
242 return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
243 }
244 else {
245 throw new IOException("Unexpected end of file");
246 }
247 }
248
249 int readInt() throws IOException
250 {
251 char[] buffer = new char[4];
252 if (in.read(buffer, 0, 4) == 4) {
253 return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
254 }
255 else {
256 throw new IOException("Unexpected end of file");
257 }
258 }
259
260 String readLine() throws IOException
261 {
262 currentLine++;
263 String line = in.readLine();
264 if (line == null) {
265 throw new IOException("Unexpected end of file");
266 }
267 return line;
268 }
269
270 }