package de.saring.exerciseviewer.parser; import de.saring.exerciseviewer.core.EVException; import de.saring.exerciseviewer.data.EVExercise; import de.saring.exerciseviewer.data.Lap; import de.saring.util.unitcalc.CalculationUtils; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.util.ArrayList; import java.util.List; /** * This abstract ExerciseParser implementation class contains the basic * functionality which can be used by all ExerciseParser implementations. * * @author Stefan Saring * @version 1.0 */ public abstract class AbstractExerciseParser implements ExerciseParser { /** * This is a helper method for all parser implementations, which reads * the specified binary exercise file into a int buffer. * The reason for integers in the buffer is: byte values are -128 to 127, * int values are converted to 0 to 255, this makes parsing much easier. * * @param filename filename of exercise file to read * @return byte buffer with the file content * @throws EVException thrown on read problems */ protected int[] readFileToByteArray(String filename) throws EVException { File file = new File(filename); // open exercise file and create buffer with same length try (FileInputStream fiStream = new FileInputStream(file)) { int fileLength = (int) file.length(); byte[] byteBuffer = new byte[fileLength]; int[] intBuffer = new int[fileLength]; // read all bytes to buffer if (fiStream.read(byteBuffer) != fileLength) { throw new Exception("Failed to read complete file content ..."); } // convert signed byte buffer to int buffer for (int i = 0; i < fileLength; i++) { intBuffer[i] = unsignedByteToInt(byteBuffer[i]); } return intBuffer; } catch (Exception e) { throw new EVException("Failed to read binary content from exercise file '" + filename + "' ...", e); } } /** * This is a helper method for all parser implementations, which reads * the specified text-based exercise file into an array of strings * (one string for each line). * * @param filename filename of exercise file to read * @return String array with the file content * @throws EVException thrown on read problems */ protected String[] readFileToStringArray(String filename) throws EVException { try (BufferedReader bufReader = new BufferedReader(new FileReader(filename))) { List<String> lLines = new ArrayList<>(); String strCurrentLine = null; // add all lines of file to temporary ArrayList while ((strCurrentLine = bufReader.readLine()) != null) { lLines.add(strCurrentLine); } // return a normal string array return lLines.toArray(new String[lLines.size()]); } catch (Exception e) { throw new EVException("Failed to read text content from exercise file '" + filename + "' ...", e); } } /** * This helper method converts the unisgned byte value (0..255) to the * appropriate int value. It's usefull for reading binary file content. * * @param value unsigned byte value * @return appropriate int value */ private int unsignedByteToInt(byte value) { return value & 0xff; } /** * This helper method calculates the average speed for all laps of the * specified exercise. This needs to be done for many models because the * average lap speed is not part of the recorded data. * * @param exercise the exercise for calculation */ protected void calculateAverageLapSpeed(EVExercise exercise) { // abort calculation when speed or lap data was not recorded if (!exercise.getRecordingMode().isSpeed() || exercise.getLapList() == null) { return; } // calculate AVG speed for all laps int distanceBefore = 0; int timeSplitBefore = 0; for (Lap lap : exercise.getLapList()) { int lapDistance = lap.getSpeed().getDistance() - distanceBefore; int lapDuration = lap.getTimeSplit() - timeSplitBefore; distanceBefore = lap.getSpeed().getDistance(); timeSplitBefore = lap.getTimeSplit(); lap.getSpeed().setSpeedAVG(CalculationUtils.calculateAvgSpeed( lapDistance / 1000f, Math.round(lapDuration / 10f))); } } }