Skip to content

Commit

Permalink
Merge pull request #339 from valhalla/kk_32compat
Browse files Browse the repository at this point in the history
use integers to avoid precision issues
  • Loading branch information
kevinkreiser authored Jul 1, 2016
2 parents 7b4377f + ed348ee commit c2ca147
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 132 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ libvalhalla_odin.pc
valhalla/proto
src/proto
src/odin/locales.h
locales/*.utf8
locales/*.UTF-8
odin_service
*.o
.deps/
Expand Down
2 changes: 1 addition & 1 deletion locales/cs-CZ.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"posix_locale": "cs_CZ.utf8",
"posix_locale": "cs_CZ.UTF-8",
"instructions": {
"start": {
"phrases": {
Expand Down
2 changes: 1 addition & 1 deletion locales/de-DE.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"posix_locale": "de_DE.utf8",
"posix_locale": "de_DE.UTF-8",
"instructions": {
"start": {
"phrases": {
Expand Down
2 changes: 1 addition & 1 deletion locales/en-US.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"posix_locale": "en_US.utf8",
"posix_locale": "en_US.UTF-8",
"instructions": {
"start": {
"phrases": {
Expand Down
2 changes: 1 addition & 1 deletion locales/it-IT.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"posix_locale": "it_IT.utf8",
"posix_locale": "it_IT.UTF-8",
"instructions": {
"start": {
"phrases": {
Expand Down
8 changes: 3 additions & 5 deletions locales/make_locales.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
set -e

#install locales locally for testing
if [[ "$OSTYPE" == "linux"* ]]; then
for loc in $(grep -F posix_locale *.json | sed -e "s/.*locale[^a-z^A-Z]\+//g" -e "s/[^a-z^A-Z^0-9^.^_]\+//g"); do
localedef -i ${loc%.*} -f UTF-8 ./${loc}
done
fi
for loc in $(jq ".posix_locale" *.json | sed -e 's/"//g'); do
localedef -i "${loc%.*}" -f "${loc##*.}" "./${loc}"
done

#throw all the text into one big header
code=
Expand Down
2 changes: 1 addition & 1 deletion scripts/dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -e
export LD_LIBRARY_PATH=.:`cat /etc/ld.so.conf.d/* | grep -v -E "#" | tr "\\n" ":" | sed -e "s/:$//g"`
sudo add-apt-repository -y ppa:kevinkreiser/prime-server
sudo apt-get update -o Dir::Etc::sourcelist="sources.list.d/kevinkreiser-prime-server-$(lsb_release -c -s).list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0"
sudo apt-get install -y autoconf automake pkg-config libtool make gcc g++ lcov vim-common libboost1.54-all-dev protobuf-compiler libprotobuf-dev libprime-server-dev
sudo apt-get install -y autoconf automake pkg-config libtool make gcc g++ lcov vim-common jq libboost1.54-all-dev protobuf-compiler libprotobuf-dev libprime-server-dev

#clone async
mkdir -p deps
Expand Down
2 changes: 1 addition & 1 deletion src/odin/narrative_dictionary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void NarrativeDictionary::Load(
/////////////////////////////////////////////////////////////////////////////
LOG_TRACE("Populate posix_locale...");
// Populate posix locale
posix_locale = narrative_pt.get<std::string>(kPosixLocaleKey, "en_US.utf8");
posix_locale = narrative_pt.get<std::string>(kPosixLocaleKey, "en_US.UTF-8");
try {
locale = std::locale(posix_locale.c_str());
}
Expand Down
82 changes: 40 additions & 42 deletions src/odin/narrativebuilder.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <string>

Expand Down Expand Up @@ -3236,46 +3237,42 @@ std::string NarrativeBuilder::FormMetricLength(
std::string length_string;
length_string.reserve(kLengthStringInitialCapacity);

float kilometer_tenths = std::round(kilometers * 10) / 10;
uint32_t meters = 0;
// Follow locale rules turning numbers into strings
std::stringstream distance;
distance.imbue(dictionary_.GetLocale());
// These will determine what we say
int tenths = std::round(kilometers * 10);

if (kilometer_tenths > 1.0f) {
if (tenths > 10) {
// 0 "<KILOMETERS> kilometers"
length_string += metric_lengths.at(kKilometersIndex);
} else if (kilometer_tenths == 1.0f) {
distance << std::setiosflags(std::ios::fixed) << std::setprecision(tenths % 10 > 0) << kilometers;
} else if (tenths == 10) {
// 1 "1 kilometer"
length_string += metric_lengths.at(kOneKilometerIndex);
} else if (kilometer_tenths == 0.5f) {
} else if (tenths == 5) {
// 2 "a half kilometer"
length_string += metric_lengths.at(kHalfKilometerIndex);
} else {
float kilometer_hundredths = std::round(kilometers * 100) / 100;
float kilometer_thousandths = std::round(kilometers * 1000) / 1000;

// Process hundred meters
if (kilometer_hundredths > 0.09f) {
int meters = std::round(kilometers * 1000);
if (meters > 94) {
// 3 "<METERS> meters" (100-400 and 600-900 meters)
length_string += metric_lengths.at(kMetersIndex);
meters = static_cast<uint32_t>(kilometer_tenths * 1000);
} else if (kilometer_thousandths > 0.009f) {
distance << ((meters + 50) / 100) * 100;
} else if (meters > 9) {
// 3 "<METERS> meters" (10-90 meters)
length_string += metric_lengths.at(kMetersIndex);
meters = static_cast<uint32_t>(kilometer_hundredths * 1000);
distance << ((meters + 5) / 10) * 10;
} else {
// 4 "less than 10 meters"
length_string += metric_lengths.at(kSmallMetersIndex);
}
}

// Stream kilometers based on locale
std::ostringstream kilometers_stream;
kilometers_stream.imbue(dictionary_.GetLocale());
kilometers_stream << kilometer_tenths;

//TODO: why do we need separate tags for kilometers and meters?
// Replace tags with length values
boost::replace_all(length_string, kKilometersTag, kilometers_stream.str());
boost::replace_all(length_string, kMetersTag, std::to_string(meters)); //: locale specific numerals

boost::replace_all(length_string, kKilometersTag, distance.str());
boost::replace_all(length_string, kMetersTag, distance.str());

return length_string;
}
Expand All @@ -3293,50 +3290,51 @@ std::string NarrativeBuilder::FormUsCustomaryLength(

std::string length_string;
length_string.reserve(kLengthStringInitialCapacity);
float mile_tenths = std::round(miles * 10) / 10;
uint32_t tenths_of_mile = 0;
uint32_t feet = static_cast<uint32_t>(std::round(miles * 5280));

if (mile_tenths > 1.0f) {

// Follow locale rules turning numbers into strings
std::stringstream distance;
distance.imbue(dictionary_.GetLocale());
// These will determine what we say
int tenths = std::round(miles * 10);

if (tenths > 10) {
// 0 "<MILES> miles"
length_string += us_customary_lengths.at(kMilesIndex);
} else if (mile_tenths == 1.0f) {
distance << std::setiosflags(std::ios::fixed) << std::setprecision(tenths % 10 > 0) << miles;
} else if (tenths == 10) {
// 1 "1 mile"
length_string += us_customary_lengths.at(kOneMileIndex);
} else if (mile_tenths == 0.5f) {
} else if (tenths == 5) {
// 2 "a half mile"
length_string += us_customary_lengths.at(kHalfMileIndex);
} else if (mile_tenths > 0.1f) {
} else if (tenths > 1) {
// 3 "<TENTHS_OF_MILE> tenths of a mile" (2-4, 6-9)
length_string += us_customary_lengths.at(kTenthsOfMileIndex);
tenths_of_mile = static_cast<uint32_t>(mile_tenths * 10);
} else if ((miles > 0.0973f) && (mile_tenths == 0.1f)) {
distance << tenths;
} else if (miles > 0.0973f && tenths == 1) {
// 4 "1 tenth of a mile"
length_string += us_customary_lengths.at(kOneTenthOfMileIndex);
} else {
int feet = std::round(miles * 5280);
if (feet > 94) {
// 5 "<FEET> feet" (100-500)
length_string += us_customary_lengths.at(kFeetIndex);
feet = static_cast<uint32_t>(std::round(feet / 100.0f) * 100);
distance << ((feet + 50) / 100) * 100;
} else if (feet > 9) {
// 5 "<FEET> feet" (10-90)
length_string += us_customary_lengths.at(kFeetIndex);
feet = static_cast<uint32_t>(std::round(feet / 10.0f) * 10);
distance << ((feet + 5) / 10) * 10;
} else {
// 6 "less than 10 feet"
length_string += us_customary_lengths.at(kSmallFeetIndex);
}
}

// Stream miles based on locale
std::ostringstream miles_stream;
miles_stream.imbue(dictionary_.GetLocale());
miles_stream << mile_tenths;

//TODO: why do we need separate tags for miles, tenths and feet?
// Replace tags with length values
boost::replace_all(length_string, kMilesTag, miles_stream.str());
boost::replace_all(length_string, kTenthsOfMilesTag, std::to_string(tenths_of_mile)); //TODO: locale specific numerals
boost::replace_all(length_string, kFeetTag, std::to_string(feet)); //TODO: locale specific numerals
boost::replace_all(length_string, kMilesTag, distance.str());
boost::replace_all(length_string, kTenthsOfMilesTag, distance.str());
boost::replace_all(length_string, kFeetTag, distance.str());

return length_string;
}
Expand Down
86 changes: 43 additions & 43 deletions src/odin/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,74 +100,74 @@ DirectionsOptions GetDirectionsOptions(const boost::property_tree::ptree& pt) {
//date_time is in the format of 2015-05-06T08:00
std::string get_localized_time(const std::string& date_time,
const std::locale& locale) {
std::stringstream ss("");
try {
if (date_time.find("T") == std::string::npos)
return ss.str();
if (date_time.find("T") == std::string::npos) return "";

boost::local_time::local_time_input_facet* input_facet =
new boost::local_time::local_time_input_facet("%Y-%m-%dT%H:%M");
boost::posix_time::time_facet* output_facet =
new boost::posix_time::time_facet("%X");
std::string time = date_time;
try {
// formatting for in and output
std::locale in_locale(std::locale::classic(), new boost::local_time::local_time_input_facet("%Y-%m-%dT%H:%M"));
std::stringstream in_stream; in_stream.imbue(in_locale);
std::locale out_locale(locale, new boost::posix_time::time_facet("%X"));
std::stringstream out_stream; out_stream.imbue(out_locale);

ss.imbue(std::locale(ss.getloc(), input_facet));
//parse the input
boost::posix_time::ptime pt;
ss.str(date_time);
ss >> pt; // read in with the format of "%Y-%m-%dT%H:%M"
ss.str("");
ss.imbue(std::locale(locale, output_facet)); // output in the locale requested
ss << pt;
std::string time = ss.str();
in_stream.str(date_time);
in_stream >> pt;

//format the output
out_stream << pt;
time = out_stream.str();

//seconds is too granular so we try to remove
if (time.find("PM") == std::string::npos
&& time.find("AM") == std::string::npos) { //AM or PM
std::size_t found = time.find_last_of(":"); // remove seconds.
&& time.find("AM") == std::string::npos) {
size_t found = time.find_last_of(":");
if (found != std::string::npos)
time = time.substr(0, found);
else {
found = time.find_last_of("00"); // remove seconds.
found = time.find_last_of("00");
if (found != std::string::npos)
time = time.substr(0, found - 1);
}
} else { // has AM or PM
} else {
boost::replace_all(time, ":00 ", " ");
if (time.substr(0, 1) == "0")
time = time.substr(1, time.size());
}
ss.str(time);
} catch (std::exception& e) {
}
std::string result = ss.str();
boost::algorithm::trim(result);
return result;
} catch (std::exception&) { return ""; }

boost::algorithm::trim(time);
return time;
}

//Get the date from the inputed date.
//date_time is in the format of 2015-05-06T08:00
std::string get_localized_date(const std::string& date_time,
const std::locale& locale) {
std::stringstream ss("");
if (date_time.find("T") == std::string::npos) return "";

std::string date = date_time;
try {
if (date_time.find("T") == std::string::npos)
return ss.str();

boost::local_time::local_time_input_facet* input_facet =
new boost::local_time::local_time_input_facet("%Y-%m-%dT%H:%M");
boost::posix_time::time_facet* output_facet =
new boost::posix_time::time_facet("%x");
// formatting for in and output
std::locale in_locale(std::locale::classic(), new boost::local_time::local_time_input_facet("%Y-%m-%dT%H:%M"));
std::stringstream in_stream; in_stream.imbue(in_locale);
std::locale out_locale(locale, new boost::posix_time::time_facet("%x"));
std::stringstream out_stream; out_stream.imbue(out_locale);

ss.imbue(std::locale(ss.getloc(), input_facet));
//parse the input
boost::posix_time::ptime pt;
ss.str(date_time);
ss >> pt; // read in with the format of "%Y-%m-%dT%H:%M"
ss.str("");
ss.imbue(std::locale(locale, output_facet)); // output in the locale requested
ss << pt;
} catch (std::exception& e) {
}
std::string result = ss.str();
boost::algorithm::trim(result);
return result;
in_stream.str(date_time);
in_stream >> pt;

//format the output
out_stream << pt;
date = out_stream.str();
} catch (std::exception& e) { return ""; }

boost::algorithm::trim(date);
return date;
}

const locales_singleton_t& get_locales() {
Expand Down
Loading

0 comments on commit c2ca147

Please sign in to comment.