diff --git a/routing/routing.pro b/routing/routing.pro index bf9bde190f..b4926f8792 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -39,8 +39,10 @@ SOURCES += \ turns_generator.cpp \ turns_sound.cpp \ turns_sound_settings.cpp \ + turns_tts_text.cpp \ vehicle_model.cpp \ + HEADERS += \ async_router.hpp \ base/astar_algorithm.hpp \ @@ -72,4 +74,5 @@ HEADERS += \ turns_generator.hpp \ turns_sound.hpp \ turns_sound_settings.hpp \ + turns_tts_text.hpp \ vehicle_model.hpp \ diff --git a/routing/turns_sound.cpp b/routing/turns_sound.cpp index e438a6d9a7..431fa0195b 100644 --- a/routing/turns_sound.cpp +++ b/routing/turns_sound.cpp @@ -115,13 +115,13 @@ void TurnsSound::SetLengthUnits(LengthUnits units) case LengthUnits::Meters: m_settings = Settings(20 /* notificationTimeSeconds */, 200 /* minNotificationDistanceUnits */, 2000 /* maxNotificationDistanceUnits */, - {200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500, 2000} /* soundedDistancesUnits */, + soundedDistancesMeters /* soundedDistancesUnits */, LengthUnits::Meters /* lengthUnits */); return; case LengthUnits::Feet: m_settings = Settings(20 /* notificationTimeSeconds */, 500 /* minNotificationDistanceUnits */, 5000 /* maxNotificationDistanceUnits */, - {500, 600, 700, 800, 900, 1000, 1500, 2000, 3000, 4000, 5000} /* soundedDistancesUnits */, + soundedDistancesFeet /* soundedDistancesUnits */, LengthUnits::Feet /* lengthUnits */); return; } diff --git a/routing/turns_sound_settings.hpp b/routing/turns_sound_settings.hpp index 9877e69e60..5295c7a340 100644 --- a/routing/turns_sound_settings.hpp +++ b/routing/turns_sound_settings.hpp @@ -15,6 +15,81 @@ enum class LengthUnits Feet }; +// All sounded distance for TTS in meters and kilometers. +enum class AllSoundedDistancesMeters +{ + In50 = 50, + In100 = 100, + In200 = 200, + In250 = 250, + In300 = 300, + In400 = 400, + In500 = 500, + In600 = 600, + In700 = 700, + In750 = 750, + In800 = 800, + In900 = 900, + InOneKm = 1000, + InOneAndHalfKm = 1500, + InTwoKm = 2000, + InTwoAndHalfKm = 2500, + InThreeKm = 3000 +}; + +// All sounded distance for TTS in feet and miles. +enum class AllSoundedDistancesFeet +{ + In50 = 50, + In100 = 100, + In200 = 200, + In300 = 300, + In400 = 400, + In500 = 500, + In600 = 600, + In700 = 700, + In800 = 800, + In900 = 900, + In1000 = 1000, + In1500 = 1500, + In2000 = 2000, + In2500 = 2500, + In3000 = 3000, + In3500 = 3500, + In4000 = 4000, + In4500 = 4500, + In5000 = 5000, + InOneMile = 5280, + InOneAndHalfMiles = 7920, + InTwoMiles = 10560 +}; + +vector const soundedDistancesMeters = + { static_cast(AllSoundedDistancesMeters::In200), + static_cast(AllSoundedDistancesMeters::In300), + static_cast(AllSoundedDistancesMeters::In400), + static_cast(AllSoundedDistancesMeters::In500), + static_cast(AllSoundedDistancesMeters::In600), + static_cast(AllSoundedDistancesMeters::In700), + static_cast(AllSoundedDistancesMeters::In800), + static_cast(AllSoundedDistancesMeters::In900), + static_cast(AllSoundedDistancesMeters::InOneKm), + static_cast(AllSoundedDistancesMeters::InOneAndHalfKm), + static_cast(AllSoundedDistancesMeters::InTwoKm)}; + +vector const soundedDistancesFeet = + { static_cast(AllSoundedDistancesFeet::In500), + static_cast(AllSoundedDistancesFeet::In600), + static_cast(AllSoundedDistancesFeet::In700), + static_cast(AllSoundedDistancesFeet::In800), + static_cast(AllSoundedDistancesFeet::In900), + static_cast(AllSoundedDistancesFeet::In1000), + static_cast(AllSoundedDistancesFeet::In1500), + static_cast(AllSoundedDistancesFeet::In2000), + static_cast(AllSoundedDistancesFeet::In3000), + static_cast(AllSoundedDistancesFeet::In4000), + static_cast(AllSoundedDistancesFeet::In5000)}; + string DebugPrint(LengthUnits const & lengthUnits); /// \brief The Settings struct is a structure for gathering information about turn sound diff --git a/routing/turns_tts_text.cpp b/routing/turns_tts_text.cpp new file mode 100644 index 0000000000..c1027248dc --- /dev/null +++ b/routing/turns_tts_text.cpp @@ -0,0 +1,212 @@ +#include "routing/turns_sound_settings.hpp" +#include "routing/turns_tts_text.hpp" + +#include "std/utility.hpp" + + +namespace routing +{ +namespace turns +{ +namespace sound +{ +GetTtsText::GetTtsText() +{ + m_getEng.reset(new platform::GetTextById(platform::TextSource::TtsSound, "en")); + ASSERT(m_getEng && m_getEng->IsValid(), ()); +} + +void GetTtsText::SetLocale(string const & locale) +{ + m_getCurLang.reset(new platform::GetTextById(platform::TextSource::TtsSound, locale)); + ASSERT(m_getCurLang && m_getCurLang->IsValid(), ()); +} + +string GetTtsText::operator()(Notification const & notification) const +{ + if (notification.m_distanceUnits == 0) + return GetTextById(GetDirectionTextId(notification)); + + return GetTextById(GetDistanceTextId(notification)) + " " + + GetTextById(GetDirectionTextId(notification)); +} + +string GetTtsText::GetTextById(string const & textId) const +{ + ASSERT(!textId.empty(), ()); + + platform::GetTextById const & getCurLang = *m_getCurLang; + platform::GetTextById const & getEng = *m_getEng; + if (m_getCurLang && m_getCurLang->IsValid()) + { + pair const text = getCurLang(textId); + if (text.second) + return text.first; // textId is found in m_getCurLang + return getEng(textId).first; // textId is not found in m_getCurLang + } + return getEng(textId).first; +} + +string GetDistanceTextId(Notification const & notification) +{ + if (!notification.IsValid()) + { + ASSERT(false, ()); + return ""; + } + + if (notification.m_useThenInsteadOfDistance) + return "then"; + + switch(notification.m_lengthUnits) + { + case LengthUnits::Undefined: + ASSERT(false, ()); + return ""; + case LengthUnits::Meters: + for (uint32_t const dist : soundedDistancesMeters) + { + if (notification.m_distanceUnits == dist) + { + switch(static_cast(notification.m_distanceUnits)) + { + case AllSoundedDistancesMeters::In50: + return "in_50_meters"; + case AllSoundedDistancesMeters::In100: + return "in_100_meters"; + case AllSoundedDistancesMeters::In200: + return "in_200_meters"; + case AllSoundedDistancesMeters::In250: + return "in_250_meters"; + case AllSoundedDistancesMeters::In300: + return "in_300_meters"; + case AllSoundedDistancesMeters::In400: + return "in_400_meters"; + case AllSoundedDistancesMeters::In500: + return "in_500_meters"; + case AllSoundedDistancesMeters::In600: + return "in_600_meters"; + case AllSoundedDistancesMeters::In700: + return "in_700_meters"; + case AllSoundedDistancesMeters::In750: + return "in_750_meters"; + case AllSoundedDistancesMeters::In800: + return "in_800_meters"; + case AllSoundedDistancesMeters::In900: + return "in_900_meters"; + case AllSoundedDistancesMeters::InOneKm: + return "in_1_kilometer"; + case AllSoundedDistancesMeters::InOneAndHalfKm: + return "in_1_5_kilometers"; + case AllSoundedDistancesMeters::InTwoKm: + return "in_2_kilometers"; + case AllSoundedDistancesMeters::InTwoAndHalfKm: + return "in_2_5_kilometers"; + case AllSoundedDistancesMeters::InThreeKm: + return "in_3_kilometers"; + } + } + } + ASSERT(false, ("notification.m_distanceUnits is not correct. Check soundedDistancesMeters.")); + return ""; + case LengthUnits::Feet: + for (uint32_t const dist : soundedDistancesFeet) + { + if (notification.m_distanceUnits == dist) + { + switch(static_cast(notification.m_distanceUnits)) + { + case AllSoundedDistancesFeet::In50: + return "in_50_feet"; + case AllSoundedDistancesFeet::In100: + return "in_100_feet"; + case AllSoundedDistancesFeet::In200: + return "in_200_feet"; + case AllSoundedDistancesFeet::In300: + return "in_300_feet"; + case AllSoundedDistancesFeet::In400: + return "in_400_feet"; + case AllSoundedDistancesFeet::In500: + return "in_500_feet"; + case AllSoundedDistancesFeet::In600: + return "in_600_feet"; + case AllSoundedDistancesFeet::In700: + return "in_700_feet"; + case AllSoundedDistancesFeet::In800: + return "in_800_feet"; + case AllSoundedDistancesFeet::In900: + return "in_900_feet"; + case AllSoundedDistancesFeet::In1000: + return "in_1000_feet"; + case AllSoundedDistancesFeet::In1500: + return "in_1500_feet"; + case AllSoundedDistancesFeet::In2000: + return "in_2000_feet"; + case AllSoundedDistancesFeet::In2500: + return "in_2500_feet"; + case AllSoundedDistancesFeet::In3000: + return "in_3000_feet"; + case AllSoundedDistancesFeet::In3500: + return "in_3500_feet"; + case AllSoundedDistancesFeet::In4000: + return "in_4000_feet"; + case AllSoundedDistancesFeet::In4500: + return "in_4500_feet"; + case AllSoundedDistancesFeet::In5000: + return "in_5000_feet"; + case AllSoundedDistancesFeet::InOneMile: + return "in_1_mile"; + case AllSoundedDistancesFeet::InOneAndHalfMiles: + return "in_1_5_miles"; + case AllSoundedDistancesFeet::InTwoMiles: + return "in_2_miles"; + } + } + } + ASSERT(false, ("notification.m_distanceUnits is not correct. Check soundedDistancesFeet.")); + return ""; + } + ASSERT(false, ()); + return ""; +} + +string GetDirectionTextId(Notification const & notification) +{ + switch(notification.m_turnDir) + { + case TurnDirection::GoStraight: + return "go_straight"; + case TurnDirection::TurnRight: + return "make_a_right_turn"; + case TurnDirection::TurnSharpRight: + return "make_a_sharp_right_turn"; + case TurnDirection::TurnSlightRight: + return "make_a_slight_right_turn"; + case TurnDirection::TurnLeft: + return "make_a_left_turn"; + case TurnDirection::TurnSharpLeft: + return "make_a_sharp_left_turn"; + case TurnDirection::TurnSlightLeft: + return "make_a_slight_left_turn"; + case TurnDirection::UTurn: + return "make_a_u_turn"; + case TurnDirection::EnterRoundAbout: + return "enter_the_roundabout"; + case TurnDirection::LeaveRoundAbout: + return "leave_the_roundabout"; + case TurnDirection::ReachedYourDestination: + return "you_have_reached_the_destination"; + case TurnDirection::StayOnRoundAbout: + case TurnDirection::StartAtEndOfStreet: + case TurnDirection::TakeTheExit: + case TurnDirection::NoTurn: + case TurnDirection::Count: + ASSERT(false, ()); + return ""; + } + ASSERT(false, ()); + return ""; +} +} // namespace sound +} // namespace turns +} // namespace routing diff --git a/routing/turns_tts_text.hpp b/routing/turns_tts_text.hpp new file mode 100644 index 0000000000..a74c455207 --- /dev/null +++ b/routing/turns_tts_text.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "platform/get_text_by_id.hpp" + +#include "std/string.hpp" +#include "std/unique_ptr.hpp" + + +namespace routing +{ +namespace turns +{ +namespace sound +{ +struct Notification; + +/// GetTtsText is responsible for generating text message for TTS in a specified locale +/// by notification. To get this message use operator(). +/// If the message is not available for specified locale GetTtsText tries to find it in +/// English locale. +class GetTtsText +{ +public: + GetTtsText(); + + string operator()(Notification const & notification) const; + void SetLocale(string const & locale); + +private: + string GetTextById(string const & textId) const; + + unique_ptr m_getCurLang; + unique_ptr m_getEng; +}; + +/// Generates text message id about the distance of the notification. For example: In 300 meters. +string GetDistanceTextId(Notification const & notification); +/// Generates text message id about the direction of the notification. For example: Make a right turn. +string GetDirectionTextId(Notification const & notification); +} // namespace sound +} // namespace turns +} // namespace routing