/* This file is part of Wattzap Community Edition.
*
* Wattzap Community Edtion is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Wattzap Community Edition 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 Wattzap. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wattzap.model.dto;
import com.wattzap.model.UserPreferences;
/**
* Represents a training item. Basically an object with Heart Rate, Power or Cadence targets.
*
* @author David George (c) Copyright 2013
* @date 19 August 2013
*/
public class TrainingItem {
int hrLow = 0;
int hrHigh;
int powerLow = 0;
int powerHigh;
int cadenceLow = 0;
int cadenceHigh;
int heartRate;
int power;
int cadence;
long time;
double distanceMeters;
String description;
public int getHr() {
return heartRate;
}
public String getHRMsg() {
String msg = "";
if (hrLow != 0) {
if (hrHigh != 0) {
msg = " HR: " + hrLow + " to " + hrHigh + " bpm";
} else {
msg = " HR > " + hrLow + " bpm";
}
} else if (hrHigh != 0) {
msg = " HR < " + hrHigh + " bpm";
}
return msg;
}
/**
* Says if Heart Rate is within range
*
* @param hr
* @return
*/
public int isHRInRange(int hr) {
if (hr >= hrLow) {
if (hr <= hrHigh || hrHigh == 0) {
return 0;
} else {
return 1;
}
}
return -1;
}
/**
* Set Heart Rate target based on Coggan/Friel heart rate levels
*
* @param String representing heart rate level
*/
public void setHr(String v) {
v = v.trim();
if (v.charAt(0) == '<') {
// less than
heartRate = Integer.parseInt(v.substring(1));
heartRate = (heartRate * UserPreferences.INSTANCE.getMaxHR()) / 100;
hrHigh = heartRate;
hrLow = 0;
} else if (v.charAt(0) == '>') {
// greater than
heartRate = Integer.parseInt(v.substring(1));
heartRate = (heartRate * UserPreferences.INSTANCE.getMaxHR()) / 100;
hrHigh = 0;
hrLow = heartRate;
} else if (v.indexOf('-') != -1) {
int i = v.indexOf('-');
hrLow = (Integer.parseInt(v.substring(0, i).trim()) * UserPreferences.INSTANCE
.getMaxHR()) / 100;
hrHigh = (Integer.parseInt(v.substring(i + 1).trim()) * UserPreferences.INSTANCE
.getMaxHR()) / 100;
heartRate = hrLow + ((hrHigh - hrLow) / 2);
} else {
heartRate = Integer.parseInt(v.trim());
if (heartRate <= 5) {
// training level
switch (heartRate) {
case 1:
// active recovery < 68%
hrHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxHR() * 0.68);
hrLow = 0;
heartRate = hrHigh;
break;
case 2:
// Endurance 69 - 83%
hrHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxHR() * 0.75);
hrLow = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 0.69);
heartRate = hrLow + ((hrHigh - hrLow) / 2);
break;
case 3:
// Tempo 84 - 94%
hrHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxHR() * 0.95);
hrLow = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 0.84);
heartRate = hrLow + ((hrHigh - hrLow) / 2);
break;
case 4:
// Lactate Threshold 95-105%
hrHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxHR() * 1.05);
hrLow = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 0.96);
heartRate = hrLow + ((hrHigh - hrLow) / 2);
break;
case 5:
// VO2Max
hrHigh = 0;
hrLow = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 1.06);
heartRate = hrLow;
break;
}
} else {
// percentage of max heartrate
heartRate = (heartRate * UserPreferences.INSTANCE.getMaxHR()) / 100;
hrHigh = (int) ((double) heartRate * 1.02);
hrLow = (int) ((double) heartRate * 0.98);
}
}
}
public int getPower() {
return power;
}
public String getPowerMsg() {
String msg = "";
if (powerLow != 0) {
if (powerHigh != 0) {
msg = " Power : " + powerLow + " to " + powerHigh + " watts";
} else {
msg = " Power > " + powerLow + " watts";
}
} else if (powerHigh != 0) {
msg = " Power < " + powerHigh + " watts";
}
return msg;
}
/**
* Says if power is within range
*
* @param power
* @return
*/
public int isPowerInRange(int power) {
if (power >= powerLow) {
if (power <= powerHigh || powerHigh == 0) {
return 0;
} else {
return 1;
}
}
return -1;
}
public void setPower(double power) {
// absolute power in watts
this.power = (int) power;
powerHigh = (int) (power * 1.025);
powerLow = (int) (power * 0.975);
}
/**
* Set power based on Coggan/Friel power levels
*
* @param v String representing level from 1-7
*/
public void setPower(String v) {
v = v.trim();
if (v.charAt(0) == '<') {
// less than
power = Integer.parseInt(v.substring(1));
power = (power * UserPreferences.INSTANCE.getMaxPower()) / 100;
powerHigh = power;
powerLow = 0;
} else if (v.charAt(0) == '>') {
// greater than
power = Integer.parseInt(v.substring(1));
power = (power * UserPreferences.INSTANCE.getMaxPower()) / 100;
powerHigh = 0;
powerLow = power;
} else if (v.indexOf('-') != -1) {
int i = v.indexOf('-');
powerLow = (Integer.parseInt(v.substring(0, i).trim()) * UserPreferences.INSTANCE
.getMaxPower()) / 100;
powerHigh = (Integer.parseInt(v.substring(i + 1).trim()) * UserPreferences.INSTANCE
.getMaxPower()) / 100;
power = powerLow + ((powerHigh - powerLow) / 2);
} else if (v.indexOf('w') != -1) {
// absolute power in watts
power = Integer.parseInt(v.substring(0, v.indexOf('w')).trim());
powerHigh = (int) ((double) power * 1.025);
powerLow = (int) ((double) power * 0.975);
} else {
power = Integer.parseInt(v.trim());
if (power <= 7) {
// training level
switch (power) {
case 1:
// active recovery < 55%
powerHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 0.55);
powerLow = 0;
power = powerHigh;
break;
case 2:
// Endurance 56 - 75%
powerHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 0.75);
powerLow = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 0.56);
power = powerLow + ((powerHigh - powerLow) / 2);
break;
case 3:
// Tempo 76 - 90%
powerHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 0.9);
powerLow = (int) ((UserPreferences.INSTANCE.getMaxPower()) * 0.66);
power = powerLow + ((powerHigh - powerLow) / 2);
break;
case 4:
// Lactate Threshold 91-105%
powerHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 1.05);
powerLow = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 0.91);
power = powerLow + ((powerHigh - powerLow) / 2);
break;
case 5:
// VO2Max 106-120
powerHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 1.2);
powerLow = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 1.06);
power = powerLow + ((powerHigh - powerLow) / 2);
break;
case 6:
// Anaerobic Capacity
powerHigh = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 1.50);
powerLow = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 1.21);
power = powerLow + ((powerHigh - powerLow) / 2);
break;
case 7:
// Neuromuscular
powerHigh = 0;
powerLow = (int) ((double) UserPreferences.INSTANCE
.getMaxPower() * 1.50);
power = powerLow;
break;
}
} else {
// percentage of max power
power = (power * UserPreferences.INSTANCE.getMaxPower()) / 100;
powerHigh = (int) ((double) power * 1.025);
powerLow = (int) ((double) power * 0.975);
}
}
}
public int getCadence() {
return cadence;
}
public String getCadenceMsg() {
String msg = "";
if (cadenceLow != 0) {
if (cadenceHigh != 0) {
msg = " Cadence: " + cadenceLow + " to " + cadenceHigh + " rpm";
} else {
msg = " Cadence > " + cadenceLow + " rpm";
}
} else if (cadenceHigh != 0) {
msg = " Cadence < " + cadenceHigh + " rpm";
}
return msg;
}
/**
* Says if Heart Rate is within range
*
* @param hr
* @return
*/
public int isCadenceInRange(int c) {
if (c >= cadenceLow) {
if (c <= cadenceHigh || cadenceHigh == 0) {
return 0;
} else {
return 1;
}
}
return -1;
}
public void setCadence(String c) {
if (c == null) {
return;
}
c = c.trim();
if (c.charAt(0) == '<') {
// less than
cadence = Integer.parseInt(c.substring(1));
cadenceHigh = cadence;
cadenceLow = 0;
} else if (c.charAt(0) == '>') {
// greater than
cadence = Integer.parseInt(c.substring(1));
cadenceHigh = 0;
cadenceLow = cadence;
} else if (c.indexOf('-') != -1) {
int i = c.indexOf('-');
cadenceLow = Integer.parseInt(c.substring(0, i).trim());
cadenceHigh = Integer.parseInt(c.substring(i + 1).trim());
cadence = cadenceLow + ((cadenceHigh - cadenceLow) / 2);
} else {
// absolute power in watts
cadence = Integer.parseInt(c.trim());
cadenceHigh = (int) ((double) cadence * 1.025);
cadenceLow = (int) ((double) cadence * 0.975);
}
}
public long getTime() {
return time;
}
public long getTimeInSeconds() {
return time / 1000;
}
public void setTime(long time) {
this.time = time * 1000;
}
public void setTimeMillis(long time) {
this.time = time;
}
public double getDistanceMeters() {
return distanceMeters;
}
public void setDistanceMeters(double distance) {
this.distanceMeters = distance;
}
@Override
public String toString() {
return "TrainingItem [power=" + power + ", time=" + time + "]";
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public static int getTrainingLevel(int power) {
// active recovery < 55%
int level1 = (int) ((double) UserPreferences.INSTANCE.getMaxPower() * 0.55);
// Endurance 56 - 75%
int level2 = (int) ((double) UserPreferences.INSTANCE.getMaxPower() * 0.75);
// Tempo 76 - 90%
int level3 = (int) ((double) UserPreferences.INSTANCE.getMaxPower() * 0.9);
// Lactate Threshold 91-105%
int level4 = (int) ((double) UserPreferences.INSTANCE.getMaxPower() * 1.05);
// VO2Max 106-120
int level5 = (int) ((double) UserPreferences.INSTANCE.getMaxPower() * 1.2);
// Anaerobic Capacity
int level6 = (int) ((double) UserPreferences.INSTANCE.getMaxPower() * 1.50);
// Neuromuscular
if (power >= 0 && power <= level1) {
return 1;
} else if (power > level1 && power <= level2) {
return 2;
} else if (power > level2 && power <= level3) {
return 3;
} else if (power > level3 && power <= level4) {
return 4;
} else if (power > level4 && power <= level5) {
return 5;
} else if (power > level5 && power <= level6) {
return 6;
}
return 7;
}
public static int getHRTrainingLevel(int hr) {
// active recovery < 68%
int level1 = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 0.68);
// Endurance 69 - 83%
int level2 = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 0.83);
// Tempo 84 - 94%
int level3 = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 0.94);
// Lactate Threshold 95-105%
int level4 = (int) ((double) UserPreferences.INSTANCE.getMaxHR() * 1.05);
if (hr >= 0 && hr <= level1) {
return 1;
} else if (hr > level1 && hr <= level2) {
return 2;
} else if (hr > level2 && hr <= level3) {
return 3;
} else if (hr > level3 && hr <= level4) {
return 4;
}
return 5;
}
/**
* Helper class to convert an integer power training level to its string representation
*
* @param level (1-7)
* @return Level description
*/
public static String getTrainingName(int level) {
switch (level) {
case 1:
return "Active Recovery";
case 2:
return "Endurance";
case 3:
return "Tempo";
case 4:
return "Lactate";
case 5:
return "VO2Max";
case 6:
return "Anaerobic";
}
return "Neuromuscular";
}
}