Coverage details for net.sf.tourviewer.ciclo.CicloReader

LineHitsSource
1 package net.sf.tourviewer.ciclo;
2  
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.PrintStream;
6 import java.util.Calendar;
7 import net.sf.tourviewer.Bike;
8 import net.sf.tourviewer.Marker;
9 import net.sf.tourviewer.Tour;
10 import net.sf.tourviewer.TourRecord;
11 import net.sf.tourviewer.TourSet;
12  
130public class CicloReader
14 {
15  
16     private static final String FILE_SIGNATURE = "AFRO";
17     
18     private static final int CCHAC4_SIGNATURE = 0xB735;
19     private static final int CM414M_SIGNATURE = 0xB723;
20  
21     private static final int RECORD_COUNT = 2048;
22     private static final int WORDS_PER_RECORD = 8;
23     private static final int BITS_PER_WORD = 32;
24  
25     private static final int INFO_RECORD_INDEX = 16;
26     private static final int TOUR_RECORD_INDEX = 19;
27     private static final int LAST_INDEX = RECORD_COUNT - 1;
28     
29     private static final int DATA_RECORD_INTERVAL = 20;
30  
310    private Record[] records = new Record[RECORD_COUNT];
32     
33     public boolean accept(InputStream in) throws IOException {
340        byte[] buffer = new byte[5];
350        in.mark(5);
360        in.read(buffer);
37         
38         try {
390            return FILE_SIGNATURE.equalsIgnoreCase(new String(buffer, 0, 4));
40         }
410        finally {
420            in.reset();
430        }
44     }
45     
46     public TourSet read(InputStream in) throws IOException {
470        int checksum = 0, lastValue = 0;
480        byte[] buffer = new byte[5];
490        int[] data = new int[32768];
500        int offset = 0;
51         
520        in.read(buffer);
530        if (!FILE_SIGNATURE.equalsIgnoreCase(new String(buffer, 0, 4))) {
540            throw new IOException("Invalid file signature, expected " + FILE_SIGNATURE);
55         }
56         
570        StringBuffer recordBuffer = new StringBuffer(32);
580        while (in.read(buffer) != -1) {
590            checksum = (checksum + lastValue) & 0xFFFF;
60             
610            String bufferText = new String(buffer, 0, 4);
620            lastValue = Integer.parseInt(bufferText, 16);
63             
640            if (offset < data.length) {
650                data[offset] = lastValue;
66             }
670            else if (offset > data.length) {
680                throw new IOException("File is too long, expected 81930 byte");
69             }
700            offset ++;
71         }
72         
730        System.out.println("Calculated Value: " + Integer.toHexString(checksum));
740        System.out.println("File Checksum : " + Integer.toHexString(lastValue));
75         
760        return analyze(data);
77     }
78     
79     public void print(PrintStream out)
80     {
810        for (int i = 0; i < records.length; i++) {
820            System.out.printf("%04d: ", i);
830            if (records[i] != null) {
840                out.println(records[i]);
85             }
86             else {
870                out.println();
88             }
89         }
900    }
91  
92     private TourSet analyze(int[] data)
93     {
940        if (data[128] == CCHAC4_SIGNATURE) {
950            return analyzeCCHAC4(data);
96         }
970        else if (data[128] == CM414M_SIGNATURE) {
980            return analyzeCM414M(data);
99         }
1000        return null;
101     }
102     
103     private TourSet analyzeCM414M(int[] data)
104     {
1050        if (data.length != 32768) {
1060            throw new IllegalArgumentException("Expected data.length == 32768");
107         }
108         
109         // prepare records
1100        records[INFO_RECORD_INDEX] = new CM414MInfo1Record(getRecordData(data, INFO_RECORD_INDEX));
1110        records[INFO_RECORD_INDEX + 1] = new CM414MInfo2Record(getRecordData(data, INFO_RECORD_INDEX + 1));
1120        records[INFO_RECORD_INDEX + 2] = new CM414MInfo3Record(getRecordData(data, INFO_RECORD_INDEX + 2));
1130        analyzeTourData(data);
114  
115         // parse records
1160        TourSet tourSet = new TourSet();
117         
1180        CM414MInfo1Record info1Record = (CM414MInfo1Record)records[INFO_RECORD_INDEX];
1190        tourSet.setDeviceName("CM 414 Alti M/CM 436 Alti M");
1200        tourSet.setPersonWeight(info1Record.getWeight());
121  
1220        CM414MInfo2Record info2Record = (CM414MInfo2Record)records[INFO_RECORD_INDEX + 1];
1230        CM414MInfo3Record info3Record = (CM414MInfo3Record)records[INFO_RECORD_INDEX + 2];
124         
1250        Bike bike = new Bike();
1260        bike.setDistance(info3Record.getTotalDistance1());
1270        bike.setTravelTime(info3Record.getTotalTravelTime1());
1280        bike.setWheelPerimeter(info1Record.getWheelPerimeter1());
1290        tourSet.addBike(bike);
130         
1310        bike = new Bike();
1320        bike.setDistance(info3Record.getTotalDistance2());
1330        bike.setTravelTime(info3Record.getTotalTravelTime2());
1340        bike.setWheelPerimeter(info1Record.getWheelPerimeter2());
1350        tourSet.addBike(bike);
136         
1370        parseTourRecords(tourSet, info2Record.getLastDDOffset());
138         
1390        return tourSet;
140     }
141  
142     private TourSet analyzeCCHAC4(int[] data)
143     {
1440        if (data.length != 32768) {
1450            throw new IllegalArgumentException("Expected data.length == 32768");
146         }
147         
148         // prepare records
1490        records[INFO_RECORD_INDEX] = new HAC4Info1Record(getRecordData(data, INFO_RECORD_INDEX));
1500        records[INFO_RECORD_INDEX + 1] = new HAC4Info2Record(getRecordData(data, INFO_RECORD_INDEX + 1));
1510        records[INFO_RECORD_INDEX + 2] = new HAC4Info3Record(getRecordData(data, INFO_RECORD_INDEX + 2));
1520        analyzeTourData(data);
153  
154         // parse records
1550        TourSet tourSet = new TourSet();
156         
1570        HAC4Info1Record info1Record = (HAC4Info1Record)records[INFO_RECORD_INDEX];
1580        tourSet.setDeviceName("HAC4");
1590        tourSet.setPersonWeight(info1Record.getWeight());
160         
1610        HAC4Info2Record info2Record = (HAC4Info2Record)records[INFO_RECORD_INDEX + 1];
1620        HAC4Info3Record info3Record = (HAC4Info3Record)records[INFO_RECORD_INDEX + 2];
163         
1640        Bike bike = new Bike();
1650        bike.setDistance(info2Record.getTotalDistance());
1660        bike.setTravelTime(info3Record.getTotalTravelTime());
1670        bike.setWheelPerimeter(info1Record.getWheelPerimeter());
1680        tourSet.addBike(bike);
169  
1700        parseTourRecords(tourSet, info3Record.getLastDDOffset());
171         
1720        return tourSet;
173     }
174     
175     private void parseTourRecords(TourSet tourSet, int lastDDOffset)
176     {
1770        Bike[] bikes = tourSet.getBikes();
1780        if (bikes == null) {
1790            throw new IllegalArgumentException("Bikes may not be null or empty");
180         }
181         
1820        int index = offsetToIndex(lastDDOffset);
1830        int startIndex = index;
1840        int lastIndex = index;
185         
1860        while ((index < startIndex)
1870                ? (index < lastIndex)
1880                : (unwrapIndex(index) < startIndex && unwrapIndex(index) < lastIndex)) {
1890            if (records[index] instanceof DDRecord) {
1900                DDRecord endRecord = (DDRecord)records[index];
191  
1920                index = offsetToIndex(endRecord.getAAOffset());
1930                if (records[index] instanceof AARecord) {
1940                    AARecord startRecord = (AARecord)records[index];
1950                    Tour tour = parseTour(startRecord, index);
1960                    if (tour != null) {
1970                        setTourType(tour, startRecord, bikes);
1980                        tourSet.addTour(tour);
199                     }
2000                    lastIndex = (index < startIndex) ? index : unwrapIndex(index);
2010                    index = decTourIndex(index);
202                 }
203                 else {
2040                    return;
205                 }
206             }
207             else {
2080                return;
209             }
210         }
2110    }
212  
213     private void setTourType(Tour tour, AARecord startRecord, Bike[] bikes)
214     {
2150        AARecord.TourType type = startRecord.getTourType();
2160        if (type == AARecord.TourType.BIKE || type == AARecord.TourType.BIKE1) {
2170            tour.setType(Tour.Type.BIKE);
2180            if (bikes.length >= 1) {
2190                tour.setBike(bikes[0]);
220             }
221         }
2220        else if (type == AARecord.TourType.SKI_BIKE) {
2230            tour.setType(Tour.Type.SKI_BIKE);
2240            if (bikes.length >= 1) {
2250                tour.setBike(bikes[0]);
226             }
227         }
2280        else if (type == AARecord.TourType.BIKE2) {
2290            tour.setType(Tour.Type.BIKE);
2300            if (bikes.length >= 2) {
2310                tour.setBike(bikes[1]);
232             }
233         }
2340        else if (type == AARecord.TourType.JOGGING) {
2350            tour.setType(Tour.Type.JOGGING);
236  
237         }
2380    }
239  
240     private int unwrapIndex(int index)
241     {
2420        return TOUR_RECORD_INDEX - (LAST_INDEX - index);
243     }
244     
245     private Tour parseTour(AARecord startRecord, int startIndex)
246     {
2470        Calendar cal = Calendar.getInstance();
248         
2490        Tour tour = new Tour();
2500        cal.set(Calendar.MONTH, startRecord.getTimeMonth() - 1);
2510        cal.set(Calendar.DAY_OF_MONTH, startRecord.getTimeDay());
2520        cal.set(Calendar.HOUR_OF_DAY, startRecord.getTimeHour());
2530        cal.set(Calendar.MINUTE, startRecord.getTimeMinute());
2540        tour.setStartTime(cal.getTime());
255         
2560        TourRecord prevRecord = new TourRecord();
2570        prevRecord.setAltitude(startRecord.getInitialAltitude());
2580        prevRecord.setDistance(0);
2590        prevRecord.setPulse(startRecord.getInitialPulse());
2600        prevRecord.setTime(tour.getStartTime());
2610        tour.addRecord(prevRecord);
262         
2630        boolean valid = false;
2640        int index = startIndex;
2650        while (true) {
2660            index = incTourIndex(index);
2670            if (records[index] instanceof BBRecord) {
2680                BBRecord dataRecord = (BBRecord)records[index];
2690                if (!valid) {
2700                    valid = true;
271                     // the first record always has the temperature of the
272                     // first data record
2730                    prevRecord.setTemperature(dataRecord.getTemperature());
274                 }
2750                if (dataRecord.getMarker() != 0) {
2760                    cal.add(Calendar.SECOND, dataRecord.getMarker());
2770                    tour.addMarker(new Marker(cal.getTime()));
2780                    cal.add(Calendar.SECOND, -dataRecord.getMarker());
279                 }
2800                prevRecord = addTourRecord(cal, tour, prevRecord, dataRecord.getDataRecords(),
2810                        dataRecord.getCadence(), dataRecord.getTemperature());
282             }
2830            else if (records[index] instanceof CCRecord) {
2840                if (!valid) {
285                     // tour contains no data
2860                    return null;
287                 }
288                 
2890                CCRecord dataRecord = (CCRecord)records[index];
2900                cal.add(Calendar.SECOND, dataRecord.getEndMarker());
2910                tour.setEndTime(cal.getTime());
2920                cal.add(Calendar.SECOND, -dataRecord.getEndMarker());
293                 // FIXME: do not add all 6 records
2940                prevRecord = addTourRecord(cal, tour, prevRecord, dataRecord.getDataRecords(),
2950                        dataRecord.getCadence(), dataRecord.getTemperature());
2960                tour.setDistance(prevRecord.getDistance());
297                 
2980                index = incTourIndex(index);
2990                if (records[index] instanceof DDRecord) {
3000                    DDRecord endRecord = (DDRecord)records[index];
3010                    return tour;
302                 }
303                 else {
3040                    return null;
305                 }
306             }
307             else {
3080                return null;
309             }
310         }
311     }
312     
313     private TourRecord addTourRecord(Calendar cal, Tour tour, TourRecord prevRecord, DataRecord[] data, int cadence, int temperature)
314     {
3150        for (int i = 0; i < data.length; i++) {
3160            TourRecord record = new TourRecord();
3170            record.setCadence(cadence);
3180            record.setTemperature(temperature);
3190            record.setAltitude(prevRecord.getAltitude() + data[i].getAltitudeDelta());
3200            record.setDistance(prevRecord.getDistance() + data[i].getDistanceDelta());
3210            record.setPulse(prevRecord.getPulse() + data[i].getPulseDelta());
3220            cal.add(Calendar.SECOND, DATA_RECORD_INTERVAL);
3230            record.setTime(cal.getTime());
3240            tour.addRecord(record);
3250            prevRecord = record;
326         }
3270        return prevRecord;
328     }
329  
330     private int decTourIndex(int index)
331     {
3320        return (index == TOUR_RECORD_INDEX) ? LAST_INDEX : index - 1;
333     }
334  
335     private int incTourIndex(int index)
336     {
3370        return (index == LAST_INDEX) ? TOUR_RECORD_INDEX : index + 1;
338     }
339     
340     protected void analyzeTourData(int[] data)
341     {
3420        for (int i = TOUR_RECORD_INDEX; i < RECORD_COUNT; i++) {
3430            int[] recordData = getRecordData(data, i);
3440            int type = recordData[0] & 0xFF;
3450            if (type == 0xAA) {
3460                records[i] = new AARecord(recordData);
347             }
3480            else if (type == 0xBB) {
3490                records[i] = new BBRecord(recordData);
350             }
3510            else if (type == 0xCC) {
3520                records[i] = new CCRecord(recordData);
353             }
3540            else if (type == 0xDD) {
3550                records[i] = new DDRecord(recordData);
356             }
357             else {
3580                records[i] = new UnknownRecord(recordData);
359             }
360         }
3610    }
362  
363     private int[] getRecordData(int[] data, int index)
364     {
3650        int[] recordData = new int[WORDS_PER_RECORD];
3660        System.arraycopy(data, index * WORDS_PER_RECORD, recordData, 0, WORDS_PER_RECORD);
3670        return recordData;
368     }
369  
370     private int offsetToIndex(int offset)
371     {
3720        return offset / WORDS_PER_RECORD / 2;
373     }
374     
375 }

this report was generated by version 1.0.5 of jcoverage.
visit www.jcoverage.com for updates.

copyright © 2003, jcoverage ltd. all rights reserved.
Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.