package net.osmand.core.samples.android.sample1;
import android.content.Context;
import net.osmand.data.Amenity;
import net.osmand.data.City.CityType;
import net.osmand.osm.AbstractPoiType;
import net.osmand.osm.MapPoiTypes;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.util.Algorithms;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.Map.Entry;
public class SampleFormatter {
public final static float METERS_IN_KILOMETER = 1000f;
public final static float METERS_IN_ONE_MILE = 1609.344f; // 1609.344
public final static float METERS_IN_ONE_NAUTICALMILE = 1852f; // 1852
public final static float YARDS_IN_ONE_METER = 1.0936f;
public final static float FEET_IN_ONE_METER = YARDS_IN_ONE_METER * 3f;
private static final DecimalFormat fixed2 = new DecimalFormat("0.00");
private static final DecimalFormat fixed1 = new DecimalFormat("0.0");
{
fixed2.setMinimumFractionDigits(2);
fixed1.setMinimumFractionDigits(1);
fixed1.setMinimumIntegerDigits(1);
fixed2.setMinimumIntegerDigits(1);
}
public static String getFormattedDuration(int seconds, SampleApplication ctx) {
int hours = seconds / (60 * 60);
int minutes = (seconds / 60) % 60;
if (hours > 0) {
return hours + " "
+ ctx.getString(R.string.shared_string_hour_short)
+ (minutes > 0 ? " " + minutes + " "
+ ctx.getString(R.string.shared_string_minute_short) : "");
} else {
return minutes + " " + ctx.getString(R.string.shared_string_minute_short);
}
}
public static double calculateRoundedDist(double distInMeters, SampleApplication ctx) {
MetricsConstants mc = ctx.getMetricsConstants();
double mainUnitInMeter = 1;
double metersInSecondUnit = METERS_IN_KILOMETER;
if (mc == MetricsConstants.MILES_AND_FEET) {
mainUnitInMeter = FEET_IN_ONE_METER;
metersInSecondUnit = METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_METERS) {
mainUnitInMeter = 1;
metersInSecondUnit = METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.NAUTICAL_MILES) {
mainUnitInMeter = 1;
metersInSecondUnit = METERS_IN_ONE_NAUTICALMILE;
} else if (mc == MetricsConstants.MILES_AND_YARDS) {
mainUnitInMeter = YARDS_IN_ONE_METER;
metersInSecondUnit = METERS_IN_ONE_MILE;
}
// 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 ...
int generator = 1;
byte pointer = 1;
double point = mainUnitInMeter;
double roundDist = 1;
while (distInMeters * point > generator) {
roundDist = (generator / point);
if (pointer++ % 3 == 2) {
generator = generator * 5 / 2;
} else {
generator *= 2;
}
if (point == mainUnitInMeter && metersInSecondUnit * mainUnitInMeter * 0.9f <= generator) {
point = 1 / metersInSecondUnit;
generator = 1;
pointer = 1;
}
}
//Miles exceptions: 2000ft->0.5mi, 1000ft->0.25mi, 1000yd->0.5mi, 500yd->0.25mi, 1000m ->0.5mi, 500m -> 0.25mi
if (mc == MetricsConstants.MILES_AND_METERS && roundDist == 1000) {
roundDist = 0.5f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_METERS && roundDist == 500) {
roundDist = 0.25f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_FEET && roundDist == 2000 / (double) FEET_IN_ONE_METER) {
roundDist = 0.5f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_FEET && roundDist == 1000 / (double) FEET_IN_ONE_METER) {
roundDist = 0.25f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_YARDS && roundDist == 1000 / (double) YARDS_IN_ONE_METER) {
roundDist = 0.5f * METERS_IN_ONE_MILE;
} else if (mc == MetricsConstants.MILES_AND_YARDS && roundDist == 500 / (double) YARDS_IN_ONE_METER) {
roundDist = 0.25f * METERS_IN_ONE_MILE;
}
return roundDist;
}
public static String getFormattedRoundDistanceKm(float meters, int digits, SampleApplication ctx) {
int mainUnitStr = R.string.km;
float mainUnitInMeters = METERS_IN_KILOMETER;
if (digits == 0) {
return (int) (meters / mainUnitInMeters + 0.5) + " " + ctx.getString(mainUnitStr); //$NON-NLS-1$
} else if (digits == 1) {
return fixed1.format(((float) meters) / mainUnitInMeters) + " " + ctx.getString(mainUnitStr);
} else {
return fixed2.format(((float) meters) / mainUnitInMeters) + " " + ctx.getString(mainUnitStr);
}
}
public static String getFormattedDistance(float meters, SampleApplication ctx) {
return getFormattedDistance(meters, ctx, true);
}
public static String getFormattedDistance(float meters, SampleApplication ctx, boolean forceTrailingZeros) {
String format1 = forceTrailingZeros ? "{0,number,0.0} " : "{0,number,0.#} ";
String format2 = forceTrailingZeros ? "{0,number,0.00} " : "{0,number,0.##} ";
MetricsConstants mc = ctx.getMetricsConstants();
int mainUnitStr;
float mainUnitInMeters;
if (mc == MetricsConstants.KILOMETERS_AND_METERS) {
mainUnitStr = R.string.km;
mainUnitInMeters = METERS_IN_KILOMETER;
} else if (mc == MetricsConstants.NAUTICAL_MILES) {
mainUnitStr = R.string.nm;
mainUnitInMeters = METERS_IN_ONE_NAUTICALMILE;
} else {
mainUnitStr = R.string.mile;
mainUnitInMeters = METERS_IN_ONE_MILE;
}
if (meters >= 100 * mainUnitInMeters) {
return (int) (meters / mainUnitInMeters + 0.5) + " " + ctx.getString(mainUnitStr); //$NON-NLS-1$
} else if (meters > 9.99f * mainUnitInMeters) {
return MessageFormat.format(format1 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (meters > 0.999f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_FEET && meters > 0.249f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_METERS && meters > 0.249f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_YARDS && meters > 0.249f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else if (mc == MetricsConstants.NAUTICAL_MILES && meters > 0.99f * mainUnitInMeters) {
return MessageFormat.format(format2 + ctx.getString(mainUnitStr), ((float) meters) / mainUnitInMeters).replace('\n', ' '); //$NON-NLS-1$
} else {
if (mc == MetricsConstants.KILOMETERS_AND_METERS || mc == MetricsConstants.MILES_AND_METERS) {
return ((int) (meters + 0.5)) + " " + ctx.getString(R.string.m); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_FEET) {
int feet = (int) (meters * FEET_IN_ONE_METER + 0.5);
return feet + " " + ctx.getString(R.string.foot); //$NON-NLS-1$
} else if (mc == MetricsConstants.MILES_AND_YARDS) {
int yards = (int) (meters * YARDS_IN_ONE_METER + 0.5);
return yards + " " + ctx.getString(R.string.yard); //$NON-NLS-1$
}
return ((int) (meters + 0.5)) + " " + ctx.getString(R.string.m); //$NON-NLS-1$
}
}
public static String getFormattedAlt(double alt, SampleApplication ctx) {
MetricsConstants mc = ctx.getMetricsConstants();
if (mc == MetricsConstants.KILOMETERS_AND_METERS) {
return ((int) (alt + 0.5)) + " " + ctx.getString(R.string.m);
} else {
return ((int) (alt * FEET_IN_ONE_METER + 0.5)) + " " + ctx.getString(R.string.foot);
}
}
public static String getFormattedSpeed(float metersperseconds, SampleApplication ctx) {
SpeedConstants mc = ctx.getSpeedConstants();
float kmh = metersperseconds * 3.6f;
if (mc == SpeedConstants.KILOMETERS_PER_HOUR) {
// e.g. car case and for high-speeds: Display rounded to 1 km/h (5% precision at 20 km/h)
if (kmh >= 20) {
return ((int) Math.round(kmh)) + " " + mc.toShortString(ctx);
}
// for smaller values display 1 decimal digit x.y km/h, (0.5% precision at 20 km/h)
int kmh10 = (int) Math.round(kmh * 10f);
return (kmh10 / 10f) + " " + mc.toShortString(ctx);
} else if (mc == SpeedConstants.MILES_PER_HOUR) {
float mph = kmh * METERS_IN_KILOMETER / METERS_IN_ONE_MILE;
if (mph >= 20) {
return ((int) Math.round(mph)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(mph * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else if (mc == SpeedConstants.NAUTICALMILES_PER_HOUR) {
float mph = kmh * METERS_IN_KILOMETER / METERS_IN_ONE_NAUTICALMILE;
if (mph >= 20) {
return ((int) Math.round(mph)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(mph * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else if (mc == SpeedConstants.MINUTES_PER_KILOMETER) {
if (metersperseconds < 0.111111111) {
return "-" + mc.toShortString(ctx);
}
float minperkm = METERS_IN_KILOMETER / (metersperseconds * 60);
if (minperkm >= 10) {
return ((int) Math.round(minperkm)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(minperkm * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else if (mc == SpeedConstants.MINUTES_PER_MILE) {
if (metersperseconds < 0.111111111) {
return "-" + mc.toShortString(ctx);
}
float minperm = (METERS_IN_ONE_MILE) / (metersperseconds * 60);
if (minperm >= 10) {
return ((int) Math.round(minperm)) + " " + mc.toShortString(ctx);
} else {
int mph10 = (int) Math.round(minperm * 10f);
return (mph10 / 10f) + " " + mc.toShortString(ctx);
}
} else /*if (mc == SpeedConstants.METERS_PER_SECOND) */ {
if (metersperseconds >= 10) {
return ((int) Math.round(metersperseconds)) + " " + SpeedConstants.METERS_PER_SECOND.toShortString(ctx);
}
// for smaller values display 1 decimal digit x.y km/h, (0.5% precision at 20 km/h)
int kmh10 = (int) Math.round(metersperseconds * 10f);
return (kmh10 / 10f) + " " + SpeedConstants.METERS_PER_SECOND.toShortString(ctx);
}
}
public static String toPublicString(CityType t, SampleApplication ctx) {
switch (t) {
case CITY:
return ctx.getString("city_type_city");
case HAMLET:
return ctx.getString("city_type_hamlet");
case TOWN:
return ctx.getString("city_type_town");
case VILLAGE:
return ctx.getString("city_type_village");
case SUBURB:
return ctx.getString("city_type_suburb");
default:
break;
}
return "";
}
public static String getPoiStringWithoutType(Amenity amenity, String locale, boolean transliterate) {
PoiCategory pc = amenity.getType();
PoiType pt = pc.getPoiTypeByKeyName(amenity.getSubType());
String nm = amenity.getSubType();
if (pt != null) {
nm = pt.getTranslation();
} else if(nm != null){
nm = Algorithms.capitalizeFirstLetterAndLowercase(nm.replace('_', ' '));
}
String n = amenity.getName(locale, transliterate);
if (n.indexOf(nm) != -1) {
// type is contained in name e.g.
// n = "Bakery the Corner"
// type = "Bakery"
// no need to repeat this
return n;
}
if (n.length() == 0) {
return nm;
}
return nm + " " + n; //$NON-NLS-1$
}
public static String getAmenityDescriptionContent(SampleApplication ctx, Amenity amenity, boolean shortDescription) {
StringBuilder d = new StringBuilder();
if(amenity.getType().isWiki()) {
return "";
}
MapPoiTypes poiTypes = ctx.getPoiTypes();
for(Entry<String, String> e : amenity.getAdditionalInfo().entrySet()) {
String key = e.getKey();
String vl = e.getValue();
if(key.startsWith("name:")) {
continue;
} else if(vl.length() >= 150) {
if(shortDescription) {
continue;
}
} else if(Amenity.OPENING_HOURS.equals(key)) {
d.append(ctx.getString("opening_hours") + ": ");
} else if(Amenity.PHONE.equals(key)) {
d.append(ctx.getString("phone") + ": ");
} else if(Amenity.WEBSITE.equals(key)) {
d.append(ctx.getString("website") + ": ");
} else {
AbstractPoiType pt = poiTypes.getAnyPoiAdditionalTypeByKey(e.getKey());
if (pt != null) {
if(pt instanceof PoiType && !((PoiType) pt).isText()) {
vl = pt.getTranslation();
} else {
vl = pt.getTranslation() + ": " + amenity.unzipContent(e.getValue());
}
} else {
vl = Algorithms.capitalizeFirstLetterAndLowercase(e.getKey()) +
": " + amenity.unzipContent(e.getValue());
}
}
d.append(vl).append('\n');
}
return d.toString().trim();
}
public enum MetricsConstants {
KILOMETERS_AND_METERS(R.string.si_km_m),
MILES_AND_FEET(R.string.si_mi_feet),
MILES_AND_METERS(R.string.si_mi_meters),
MILES_AND_YARDS(R.string.si_mi_yard),
NAUTICAL_MILES(R.string.si_nm);
private final int key;
MetricsConstants(int key) {
this.key = key;
}
public String toHumanString(Context ctx) {
return ctx.getString(key);
}
}
public enum SpeedConstants {
KILOMETERS_PER_HOUR(R.string.km_h, R.string.si_kmh),
MILES_PER_HOUR(R.string.mile_per_hour, R.string.si_mph),
METERS_PER_SECOND(R.string.m_s, R.string.si_m_s),
MINUTES_PER_MILE(R.string.min_mile, R.string.si_min_m),
MINUTES_PER_KILOMETER(R.string.min_km, R.string.si_min_km),
NAUTICALMILES_PER_HOUR(R.string.nm_h, R.string.si_nm_h);
private final int key;
private int descr;
SpeedConstants(int key, int descr) {
this.key = key;
this.descr = descr;
}
public String toHumanString(Context ctx) {
return ctx.getString(descr);
}
public String toShortString(Context ctx) {
return ctx.getString(key);
}
}
}