/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.util;
import com.google.android.apps.mytracks.stats.TripStatistics;
import com.google.android.apps.mytracks.util.CalorieUtils.ActivityType;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.view.View;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.Locale;
/**
* Utilities for updating the statistics UI labels and values.
*
* @author Jimmy Shih
*/
public class StatsUtils {
private static final String GRADE_PERCENTAGE = "%";
private static final String GRADE_FORMAT = "%1$d";
private static final String CALORIES_FORMAT = "%1$,.0f";
private StatsUtils() {}
/**
* Sets the location values.
*
* @param context the context
* @param activity the activity for finding views. If null, the view cannot be
* null
* @param view the containing view for finding views. If null, the activity
* cannot be null
* @param location the location
* @param isRecording true if recording
*/
public static void setLocationValues(
Context context, Activity activity, View view, Location location, boolean isRecording) {
boolean metricUnits = PreferencesUtils.isMetricUnits(context);
boolean reportSpeed = PreferencesUtils.isReportSpeed(context);
// Set speed/pace
View speed = getView(activity, view, R.id.stats_speed);
speed.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
if (isRecording) {
double value = isRecording && location != null && location.hasSpeed() ? location.getSpeed()
: Double.NaN;
setSpeed(context, speed, R.string.stats_speed, R.string.stats_pace, value, metricUnits,
reportSpeed);
}
// Set elevation
boolean showGradeElevation = PreferencesUtils.getBoolean(
context, R.string.stats_show_grade_elevation_key,
PreferencesUtils.STATS_SHOW_GRADE_ELEVATION_DEFAULT) && isRecording;
View elevation = getView(activity, view, R.id.stats_elevation);
elevation.setVisibility(showGradeElevation ? View.VISIBLE : View.GONE);
if (showGradeElevation) {
double altitude = location != null && location.hasAltitude() ? location.getAltitude()
: Double.NaN;
setElevationValue(context, elevation, -1, altitude, metricUnits);
}
// Set coordinate
boolean showCoordinate = PreferencesUtils.getBoolean(
context, R.string.stats_show_coordinate_key, PreferencesUtils.STATS_SHOW_COORDINATE_DEFAULT)
&& isRecording;
View coordinateSeparator = getView(activity, view, R.id.stats_coordinate_separator);
View coordinateContainer = getView(activity, view, R.id.stats_coordinate_container);
if (coordinateSeparator != null) {
coordinateSeparator.setVisibility(showCoordinate ? View.VISIBLE : View.GONE);
}
coordinateContainer.setVisibility(showCoordinate ? View.VISIBLE : View.GONE);
if (showCoordinate) {
double latitude = location != null ? location.getLatitude() : Double.NaN;
double longitude = location != null ? location.getLongitude() : Double.NaN;
setCoordinateValue(
context, getView(activity, view, R.id.stats_latitude), R.string.stats_latitude, latitude);
setCoordinateValue(context, getView(activity, view, R.id.stats_longitude),
R.string.stats_longitude, longitude);
}
}
/**
* Sets the total time value.
*
* @param activity the activity
* @param totalTime the total time
*/
public static void setTotalTimeValue(Activity activity, long totalTime) {
setTimeValue(activity, activity.findViewById(R.id.stats_total_time), R.string.stats_total_time,
totalTime);
}
/**
* Sets the trip statistics values.
*
* @param context the context
* @param activity the activity for finding views. If null, then view cannot
* be null
* @param view the containing view for finding views. If null, the activity
* cannot be null
* @param tripStatistics the trip statistics
* @param activityType the activity type
* @param trackIconValue the track icon value or null to hide the track icon
* spinner
*/
public static void setTripStatisticsValues(Context context, Activity activity, View view,
TripStatistics tripStatistics, ActivityType activityType, String trackIconValue) {
boolean metricUnits = PreferencesUtils.isMetricUnits(context);
boolean reportSpeed = PreferencesUtils.isReportSpeed(context);
// Set total distance
double totalDistance = tripStatistics == null ? Double.NaN : tripStatistics.getTotalDistance();
setDistanceValue(
context, getView(activity, view, R.id.stats_distance), totalDistance, metricUnits);
// Set calorie
double calorie = tripStatistics == null || activityType == ActivityType.INVALID ? Double.NaN
: tripStatistics.getCalorie();
setCalorie(context, getView(activity, view, R.id.stats_calorie), calorie);
Spinner spinner = (Spinner) getView(activity, view, R.id.stats_activity_type_icon);
spinner.setVisibility(trackIconValue != null ? View.VISIBLE : View.GONE);
if (trackIconValue != null) {
TrackIconUtils.setIconSpinner(spinner, trackIconValue);
}
// Set total time
setTimeValue(context, getView(activity, view, R.id.stats_total_time), R.string.stats_total_time,
tripStatistics != null ? tripStatistics.getTotalTime() : -1L);
// Set moving time
setTimeValue(context, getView(activity, view, R.id.stats_moving_time),
R.string.stats_moving_time, tripStatistics != null ? tripStatistics.getMovingTime() : -1L);
// Set average speed/pace
double averageSpeed = tripStatistics != null ? tripStatistics.getAverageSpeed() : Double.NaN;
setSpeed(context, getView(activity, view, R.id.stats_average_speed),
R.string.stats_average_speed, R.string.stats_average_pace, averageSpeed, metricUnits,
reportSpeed);
// Set max speed/pace
double maxSpeed = tripStatistics == null ? Double.NaN : tripStatistics.getMaxSpeed();
setSpeed(context, getView(activity, view, R.id.stats_max_speed), R.string.stats_max_speed,
R.string.stats_fastest_pace, maxSpeed, metricUnits, reportSpeed);
// Set average moving speed/pace
double averageMovingSpeed = tripStatistics != null ? tripStatistics.getAverageMovingSpeed()
: Double.NaN;
setSpeed(context, getView(activity, view, R.id.stats_average_moving_speed),
R.string.stats_average_moving_speed, R.string.stats_average_moving_pace, averageMovingSpeed,
metricUnits, reportSpeed);
// Set grade/elevation
boolean showGradeElevation = PreferencesUtils.getBoolean(context,
R.string.stats_show_grade_elevation_key,
PreferencesUtils.STATS_SHOW_GRADE_ELEVATION_DEFAULT);
View gradeElevationSeparator = getView(activity, view, R.id.stats_grade_elevation_separator);
View gradeElevationContainer = getView(activity, view, R.id.stats_grade_elevation_container);
gradeElevationSeparator.setVisibility(showGradeElevation ? View.VISIBLE : View.GONE);
gradeElevationContainer.setVisibility(showGradeElevation ? View.VISIBLE : View.GONE);
if (showGradeElevation) {
// Set grade
double minGrade = tripStatistics == null ? Double.NaN : tripStatistics.getMinGrade();
double maxGrade = tripStatistics == null ? Double.NaN : tripStatistics.getMaxGrade();
setGradeValue(
context, getView(activity, view, R.id.stats_grade_min), R.string.stats_min, minGrade);
setGradeValue(
context, getView(activity, view, R.id.stats_grade_max), R.string.stats_max, maxGrade);
// Set elevation
double elevationGain = tripStatistics == null ? Double.NaN
: tripStatistics.getTotalElevationGain();
double minElevation = tripStatistics == null ? Double.NaN : tripStatistics.getMinElevation();
double maxElevation = tripStatistics == null ? Double.NaN : tripStatistics.getMaxElevation();
setElevationValue(context, getView(activity, view, R.id.stats_elevation_gain),
R.string.stats_gain, elevationGain, metricUnits);
setElevationValue(context, getView(activity, view, R.id.stats_elevation_min),
R.string.stats_min, minElevation, metricUnits);
setElevationValue(context, getView(activity, view, R.id.stats_elevation_max),
R.string.stats_max, maxElevation, metricUnits);
}
}
/**
* Sets speed.
*
* @param context the context
* @param view the containing view
* @param speedLabelId the speed label id
* @param paceLabelId the pace label id
* @param speed the speed in meters per second
* @param metricUnits true if metric units
* @param reportSpeed true if report speed
*/
private static void setSpeed(Context context, View view, int speedLabelId, int paceLabelId,
double speed, boolean metricUnits, boolean reportSpeed) {
String parts[] = StringUtils.getSpeedParts(context, speed, metricUnits, reportSpeed);
setItem(context, view, reportSpeed ? speedLabelId : paceLabelId, parts[0], parts[1]);
}
/**
* Sets calorie.
*
* @param context the context
* @param view the containing view
* @param calorie the value of calorie
*/
private static void setCalorie(Context context, View view, double calorie) {
String value = Double.isNaN(calorie) ? null
: String.format(Locale.getDefault(), CALORIES_FORMAT, calorie);
setItem(context, view, R.string.stats_calorie, value, context.getString(R.string.unit_calorie));
}
/**
* Sets distance value.
*
* @param context the context
* @param view the containing view
* @param distance the distance in meters
* @param metricUnits true if metric units
*/
private static void setDistanceValue(
Context context, View view, double distance, boolean metricUnits) {
String parts[] = StringUtils.getDistanceParts(context, distance, metricUnits);
setItem(context, view, R.string.stats_distance, parts[0], parts[1]);
}
/**
* Sets a time value.
*
* @param context the context
* @param view the containing view
* @param labelId the label id
* @param time the time
*/
private static void setTimeValue(Context context, View view, int labelId, long time) {
String value = time == -1L ? null : StringUtils.formatElapsedTime(time);
setItem(context, view, labelId, value, null);
}
/**
* Sets an elevation value.
*
* @param context the context
* @param view the containing view
* @param labelId the label id
* @param elevation the elevation in meters
* @param metricUnits true if metric units
*/
private static void setElevationValue(
Context context, View view, int labelId, double elevation, boolean metricUnits) {
String value;
String unit;
if (Double.isNaN(elevation) || Double.isInfinite(elevation)) {
value = null;
unit = null;
} else {
if (metricUnits) {
value = StringUtils.formatDecimal(elevation);
unit = context.getString(R.string.unit_meter);
} else {
elevation *= UnitConversions.M_TO_FT;
value = StringUtils.formatDecimal(elevation);
unit = context.getString(R.string.unit_feet);
}
}
setItem(context, view, labelId, value, unit);
}
/**
* Sets a grade value.
*
* @param context the context
* @param view the containing view
* @param labelId the label id
* @param grade the grade in fraction between 0 and 1
*/
private static void setGradeValue(Context context, View view, int labelId, double grade) {
String value = Double.isNaN(grade) || Double.isInfinite(grade) ? null
: String.format(Locale.getDefault(), GRADE_FORMAT, Math.round(grade * 100));
setItem(context, view, labelId, value, GRADE_PERCENTAGE);
}
/**
* Sets a coordinate value.
*
* @param context the context
* @param view the containing view
* @param labelId the label id
* @param coordinate the coordinate in degrees
*/
private static void setCoordinateValue(
Context context, View view, int labelId, double coordinate) {
String value = Double.isNaN(coordinate) || Double.isInfinite(coordinate) ? null
: StringUtils.formatCoordinate(coordinate);
setItem(context, view, labelId, value, null);
}
/**
* Sets an item.
*
* @param context the context
* @param view the containing view
* @param labelId the label id. -1 to hide the label
* @param value the value, can be null
* @param unit the unit. Null to hide the unit
*/
private static void setItem(
Context context, View view, int labelId, CharSequence value, CharSequence unit) {
TextView labelTextView = (TextView) view.findViewById(R.id.stats_label);
TextView valueTextView = (TextView) view.findViewById(R.id.stats_value);
TextView unitTextView = (TextView) view.findViewById(R.id.stats_unit);
if (labelTextView == null || valueTextView == null || unitTextView == null) {
return;
}
if (labelId == -1) {
labelTextView.setVisibility(View.GONE);
} else {
labelTextView.setVisibility(View.VISIBLE);
labelTextView.setText(labelId);
}
if (value == null) {
value = context.getString(R.string.value_unknown);
unitTextView.setVisibility(View.GONE);
} else {
if (unit == null) {
unitTextView.setVisibility(View.GONE);
} else {
unitTextView.setVisibility(View.VISIBLE);
unitTextView.setText(unit);
}
}
valueTextView.setText(value);
}
/**
* Get a view.
*
* @param activity the activity
* @param view the containing view
* @param id the id
*/
private static View getView(Activity activity, View view, int id) {
if (activity != null) {
return activity.findViewById(id);
} else {
return view.findViewById(id);
}
}
}