com.rowtheboat.input.VariableSplitInput.java Source code

Java tutorial

Introduction

Here is the source code for com.rowtheboat.input.VariableSplitInput.java

Source

/*
 * PC-Rower   PC-Rower is a piece of software that allows the connection of a Concept II rowing
 *          machine to a PC to provide real-time and post workout analysis of performance.
 * Copyright (C) 2003-2005 George Palmer
 * 
 * 
 * This file is part of PC-Rower.  PC-Rower is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License(GPL) as published by the Free 
 * Software Foundation; either version 2 of the License, or (at your option) any later version.  
 * Under the GPL any derivations or alterations of this software must keep this header intact.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this program; if
 * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 * MA 02111-1307 USA
 * 
 * The author may be contacted at feedback@rowtheboat.com
 */

/*
* File: VariableSplitInput.java
* 
* Date         Version      User      Description
* 28-Nov-2003   1.0         GeorgeP      Initial version coded
* 02-Nov-2004   1.03      GeorgeP      Added apache xerces parser for native build
* 
*/

package com.rowtheboat.input;

import java.io.File;
import java.net.MalformedURLException;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import com.rowtheboat.workout.ComputerRower;
import com.rowtheboat.workout.Workout;

/**
 * VariableSplitInput uses an xml file to create a variable pace boat against which to race
 * 
 * @author GeorgeP
 */

public class VariableSplitInput implements IInputDevice {

    /* Class Variables */

    private Element root; /* The root element */
    private float[] times; /* The stroke times */
    private int[] timeIndexes; /* The indexes for the times */
    private int lastStrokeIndex = 0; /* The last stroke index */

    /* This is needed to correct files that are compiled in gcj */
    private static final Class dom4j = org.dom4j.io.aelfred.SAXDriver.class;

    /* Constructor */

    /**
     * Construct the variable split class
     * 
     * @param   file   the file from which to pull the xml workout data
     */
    public VariableSplitInput(File file) throws MalformedURLException, DocumentException {

        /* Initialise the arrays */
        times = new float[10];
        timeIndexes = new int[10];

        /* Create the reader */
        SAXReader reader = new SAXReader();
        Document document = reader.read(file);

        /* Get the root element */
        root = document.getRootElement();

        /* Create the rower */
        for (Iterator i = root.elementIterator("Rower"); i.hasNext();) {

            Element rowerElement = (Element) i.next();
            ComputerRower rower = new ComputerRower(ComputerRower.VARIABLE_SPLIT);
            rower.setName(rowerElement.elementText("Name"));
        }

        /* Create the workout */
        for (Iterator i = root.elementIterator("Details"); i.hasNext();) {

            Element wElement = (Element) i.next();
            Workout workout = new Workout(Integer.parseInt(wElement.elementText("Type")));
            workout.setDate(wElement.elementText("Date"));
            if (workout.getType() == Workout.DISTANCE_WORKOUT) {
                workout.setDistance(Integer.parseInt(wElement.elementText("Distance")));
            } else {
                workout.setTime(Integer.parseInt(wElement.elementText("Time")));
            }
        }

        /* Populate the stroke times and time index arrays */
        int arrayIndex = 0;
        for (int i = 0, size = root.nodeCount(); i < size; i++) {
            Node node = root.node(i);
            if (node instanceof Element && node.getName().equals("Stroke")) {
                Element el = (Element) node;
                times[arrayIndex] = Float.parseFloat(el.elementText("Time"));
                timeIndexes[arrayIndex] = i;
                arrayIndex++;
                if (arrayIndex == times.length) {
                    increaseArraySizes();
                }
            }
        }
    }

    /* Public Methods */

    /* Inherited Javadoc */
    public void cleanUp() throws Exception {

    }

    /* Inherited Javadoc */
    public void displayCount(byte time) {
    }

    /* Inherited Javadoc */
    public StrokeData retrieveStrokeData(float time) throws Exception {

        boolean nextStrokeExists = true;

        while (true) {
            if (lastStrokeIndex != 0 && times[lastStrokeIndex] == 0.0) {
                /* If this isn't the first stroke index and the distance is 0.0 then the last
                 * distance was the final one because any uninitialised floats are 0.0  Thus
                 * decrease the index and break */
                lastStrokeIndex--;
                nextStrokeExists = false;
                break;
            }
            if (time >= times[lastStrokeIndex]) {
                /* If the time required is greater or equal than the stroke then proceed  */

                if (lastStrokeIndex < times.length - 1) {
                    /* If the last stroke index is less than the length - 1 then proceed and test
                     * whether the time required is less than the next stroke.  If so break as we
                     * have the correct stroke index.  Otherwise fall out of if statements,
                     * increase index and try again. */
                    if (time < times[lastStrokeIndex + 1]) {
                        break;
                    }
                }

                /* Increment the index if not broken out already (i.e. found the required stroke
                 * index) */
                lastStrokeIndex++;
            }
        }

        /* Create the stroke */
        StrokeData stroke = new StrokeData();
        Element strokeEl = (Element) root.node(timeIndexes[lastStrokeIndex]);

        /* If there's another stroke available create more accurate distances and times */
        if (nextStrokeExists) {
            float time1 = times[lastStrokeIndex];
            float time2 = times[lastStrokeIndex + 1];
            float dist1 = Float.parseFloat(strokeEl.elementText("Distance"));
            Element e = (Element) root.node(timeIndexes[lastStrokeIndex + 1]);
            float dist2 = Float.parseFloat(e.elementText("Distance"));
            double mPerS = (dist2 - dist1) / (time2 - time1);
            stroke.setDistance((float) (((time - time1) * mPerS) + dist1));
            stroke.setTime(time);
        } else {
            stroke.setDistance(Float.parseFloat(strokeEl.elementText("Distance")));
            stroke.setTime(times[lastStrokeIndex]);
        }

        /* Check to see whether full stroke information is available */
        double split = Double.parseDouble(strokeEl.elementText("Split"));
        if (split != 0.0) {
            /* Full stroke data was switched on */
            stroke.setPower(Double.parseDouble(strokeEl.elementText("Power")));
            stroke.setStrokeRate(Integer.parseInt(strokeEl.elementText("SPM")));
            stroke.setHeartRate(Float.parseFloat(strokeEl.elementText("HR")));
        }

        /* Return the stroke */
        return stroke;
    }

    /* Inherited Javadoc */
    public void setupWorkout(Workout workout) throws Exception {
        /* Nothing required */
    }

    /* Inherited Javadoc */
    public void startRowing(int startType) {
        /* Nothing required in this implementation */
    }

    /* Private Methods */

    /**
     * Doubles the times array size
     */
    private void increaseArraySizes() {

        /* Create a temp array to store the times data */
        float[] temp = times;
        int[] indexTemps = timeIndexes;
        times = new float[times.length * 2];
        timeIndexes = new int[timeIndexes.length * 2];

        /* Copy over the data */
        for (int i = 0; i < temp.length; i++) {
            times[i] = temp[i];
            timeIndexes[i] = indexTemps[i];
        }
    }
}