/* * 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 de.dennisguse.opentracks.content; import android.content.Context; import android.util.Pair; import androidx.annotation.VisibleForTesting; import java.time.Duration; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.content.data.Distance; import de.dennisguse.opentracks.content.data.Speed; import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.UnitConversions; /** * Generates descriptions for tracks and markers. * * @author Jimmy Shih */ public class DescriptionGenerator { private static final String HTML_LINE_BREAK = "
"; private static final String HTML_PARAGRAPH_SEPARATOR = "

"; private static final String TEXT_LINE_BREAK = "\n"; private static final String TEXT_PARAGRAPH_SEPARATOR = "\n\n"; private final Context context; public DescriptionGenerator(Context context) { this.context = context; } /** * Generates a track description. * * @param track the track * @param html true to output html, false to output plain text */ public String generateTrackDescription(Track track, boolean html) { String paragraphSeparator = html ? HTML_PARAGRAPH_SEPARATOR : TEXT_PARAGRAPH_SEPARATOR; String lineBreak = html ? HTML_LINE_BREAK : TEXT_LINE_BREAK; StringBuilder builder = new StringBuilder(); // Created by String creator = html ? "" + context.getString(R.string.app_name) + "" : context.getString(R.string.app_name); builder.append(creator); builder.append(paragraphSeparator); writeString(track.getName(), builder, R.string.generic_name_line, lineBreak); writeString(track.getCategory(), builder, R.string.description_activity_type, lineBreak); writeString(track.getDescription(), builder, R.string.generic_description_line, lineBreak); builder.append(generateTrackStatisticsDescription(track.getTrackStatistics(), html)); return builder.toString(); } /** * Writes a string to a string builder. * * @param text the string * @param builder the string builder * @param resId the resource id containing one string placeholder * @param lineBreak the line break */ private void writeString(String text, StringBuilder builder, int resId, String lineBreak) { if (text == null || text.length() == 0) { text = context.getString(R.string.value_unknown); } builder.append(context.getString(resId, text)); builder.append(lineBreak); } /** * Generates a description for a {@link TrackStatistics}. * * @param stats the track statistics * @param html true to use "
" for line break instead of "\n" */ private String generateTrackStatisticsDescription(TrackStatistics stats, boolean html) { String lineBreak = html ? HTML_LINE_BREAK : TEXT_LINE_BREAK; StringBuilder builder = new StringBuilder(); // Total distance writeDistance(stats.getTotalDistance(), builder, R.string.description_total_distance, lineBreak); // Total time writeTime(stats.getTotalTime(), builder, R.string.description_total_time, lineBreak); // Moving time writeTime(stats.getMovingTime(), builder, R.string.description_moving_time, lineBreak); // Average speed writeSpeed(stats.getAverageSpeed(), builder, R.string.description_average_speed, lineBreak); // Average moving speed writeSpeed(stats.getAverageMovingSpeed(), builder, R.string.description_average_moving_speed, lineBreak); // Max speed writeSpeed(stats.getMaxSpeed(), builder, R.string.description_max_speed, lineBreak); // Average pace writePace(stats.getAverageSpeed(), builder, R.string.description_average_pace_in_minute, lineBreak); // Average moving pace writePace(stats.getAverageMovingSpeed(), builder, R.string.description_average_moving_pace_in_minute, lineBreak); // Fastest pace writePace(stats.getMaxSpeed(), builder, R.string.description_fastest_pace_in_minute, lineBreak); // Max altitude if (stats.hasAltitudeMax()) { writeAltitude(stats.getMaxAltitude(), builder, R.string.description_max_altitude, lineBreak); } // Min altitude if (stats.hasAltitudeMin()) { writeAltitude(stats.getMinAltitude(), builder, R.string.description_min_altitude, lineBreak); } // Altitude gain if (stats.hasTotalAltitudeGain()) { writeAltitude(stats.getTotalAltitudeGain(), builder, R.string.description_altitude_gain, lineBreak); } // Altitude loss if (stats.hasTotalAltitudeLoss()) { writeAltitude(stats.getTotalAltitudeLoss(), builder, R.string.description_altitude_loss, lineBreak); } // Recorded time builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTime(context, stats.getStartTime()))); builder.append(lineBreak); return builder.toString(); } /** * Writes distance. * * @param distance distance in meters * @param builder StringBuilder to append distance * @param resId resource id of distance string * @param lineBreak line break string */ @VisibleForTesting void writeDistance(Distance distance, StringBuilder builder, int resId, String lineBreak) { double distanceInKm = distance.toKM(); double distanceInMi = distance.toMI(); builder.append(context.getString(resId, distanceInKm, distanceInMi)); builder.append(lineBreak); } /** * Writes time. * * @param time time in milliseconds. * @param builder StringBuilder to append time * @param resId resource id of time string * @param lineBreak line break string */ @VisibleForTesting void writeTime(Duration time, StringBuilder builder, int resId, String lineBreak) { builder.append(context.getString(resId, StringUtils.formatElapsedTime(time))); builder.append(lineBreak); } /** * Writes speed. * * @param speed speed in meters per second * @param builder StringBuilder to append speed * @param resId resource id of speed string * @param lineBreak line break string */ @VisibleForTesting void writeSpeed(Speed speed, StringBuilder builder, int resId, String lineBreak) { builder.append(context.getString(resId, speed.toKMH(), speed.toMPH())); builder.append(lineBreak); } /** * @param builder StringBuilder to append pace * @param resId resource id of pace string * @param lineBreak line break string */ @VisibleForTesting void writePace(Speed speed, StringBuilder builder, int resId, String lineBreak) { Pair paceInMetrics = StringUtils.getSpeedParts(context, speed, true, false); Pair paceInImperial = StringUtils.getSpeedParts(context, speed, false, false); String formattedPaceMetrics = paceInMetrics.first != null ? paceInMetrics.first : context.getString(R.string.value_unknown); String formattedPaceImperial = paceInImperial.first != null ? paceInImperial.first : context.getString(R.string.value_unknown); builder.append(context.getString(resId, formattedPaceMetrics, formattedPaceImperial)); builder.append(lineBreak); } /** * @param altitude_m altitude_m in meters * @param builder StringBuilder to append * @param resId resource id of altitude string * @param lineBreak line break string */ @VisibleForTesting void writeAltitude(double altitude_m, StringBuilder builder, int resId, String lineBreak) { long altitudeInM = Math.round(altitude_m); long altitudeInFt = Math.round(altitude_m * UnitConversions.M_TO_FT); builder.append(context.getString(resId, altitudeInM, altitudeInFt)); builder.append(lineBreak); } }