#include "routing/turns_sound_settings.hpp" #include "platform/measurement_utils.hpp" #include "base/string_utils.hpp" #include "std/algorithm.hpp" using namespace measurement_utils; namespace routing { namespace turns { namespace sound { void Settings::SetState(uint32_t notificationTimeSeconds, uint32_t minNotificationDistanceUnits, uint32_t maxNotificationDistanceUnits, vector const & soundedDistancesUnits, measurement_utils::Units lengthUnits) { m_timeSeconds = notificationTimeSeconds; m_minDistanceUnits = minNotificationDistanceUnits; m_maxDistanceUnits = maxNotificationDistanceUnits; m_soundedDistancesUnits = soundedDistancesUnits; m_lengthUnits = lengthUnits; } bool Settings::IsValid() const { return m_minDistanceUnits <= m_maxDistanceUnits && !m_soundedDistancesUnits.empty() && is_sorted(m_soundedDistancesUnits.cbegin(), m_soundedDistancesUnits.cend()); } uint32_t Settings::ComputeTurnDistanceM(double speedMetersPerSecond) const { ASSERT(IsValid(), ()); double const turnNotificationDistanceM = m_timeSeconds * speedMetersPerSecond; return static_cast(my::clamp(turnNotificationDistanceM, ConvertUnitsToMeters(m_minDistanceUnits), ConvertUnitsToMeters(m_maxDistanceUnits))); } bool Settings::TooCloseForFisrtNotification(double distToTurnMeters) const { return m_minDistToSayNotificationMeters >= distToTurnMeters; } uint32_t Settings::RoundByPresetSoundedDistancesUnits(uint32_t turnNotificationUnits) const { ASSERT(IsValid(), ()); auto it = upper_bound(m_soundedDistancesUnits.cbegin(), m_soundedDistancesUnits.cend(), turnNotificationUnits, less_equal()); // Rounding up the result. if (it != m_soundedDistancesUnits.cend()) return *it; ASSERT(false, ("m_soundedDistancesUnits shall contain bigger values.")); return m_soundedDistancesUnits.empty() ? 0 : m_soundedDistancesUnits.back(); } double Settings::ConvertMetersPerSecondToUnitsPerSecond(double speedInMetersPerSecond) const { switch (m_lengthUnits) { case Units::Metric: return speedInMetersPerSecond; case Units::Imperial: return MetersToFeet(speedInMetersPerSecond); } ASSERT(false, ("m_lengthUnits is equal to unknown value.")); return 0.; } double Settings::ConvertUnitsToMeters(double distanceInUnits) const { switch (m_lengthUnits) { case Units::Metric: return distanceInUnits; case Units::Imperial: return FeetToMeters(distanceInUnits); } ASSERT(false, ()); return 0.; } double Settings::ConvertMetersToUnits(double distanceInMeters) const { switch (m_lengthUnits) { case Units::Metric: return distanceInMeters; case Units::Imperial: return MetersToFeet(distanceInMeters); } ASSERT(false, ()); return 0.; } uint32_t Settings::ComputeDistToPronounceDistM(double speedMetersPerSecond) const { ASSERT_LESS_OR_EQUAL(0, speedMetersPerSecond, ()); uint32_t const startBeforeMeters = static_cast(speedMetersPerSecond * m_startBeforeSeconds); return my::clamp(startBeforeMeters, m_minStartBeforeMeters, m_maxStartBeforeMeters); } string DebugPrint(Notification const & notification) { string units; stringstream out; out << "Notification [ m_distanceUnits == " << notification.m_distanceUnits << ", m_exitNum == " << notification.m_exitNum << ", m_useThenInsteadOfDistance == " << notification.m_useThenInsteadOfDistance << ", m_turnDir == " << DebugPrint(notification.m_turnDir) << ", m_lengthUnits == " << DebugPrint(notification.m_lengthUnits) << " ]" << endl; return out.str(); } VecPairDist const & GetAllSoundedDistMeters() { // The vector below has to be sorted. It is checked in unit test GetAllSoundedDistMetersTest static VecPairDist const inst = {{50, "in_50_meters"}, {100, "in_100_meters"}, {200, "in_200_meters"}, {250, "in_250_meters"}, {300, "in_300_meters"}, {400, "in_400_meters"}, {500, "in_500_meters"}, {600, "in_600_meters"}, {700, "in_700_meters"}, {750, "in_750_meters"}, {800, "in_800_meters"}, {900, "in_900_meters"}, {1000, "in_1_kilometer"}, {1500, "in_1_5_kilometers"}, {2000, "in_2_kilometers"}, {2500, "in_2_5_kilometers"}, {3000, "in_3_kilometers"}}; return inst; } VecPairDist const & GetAllSoundedDistFeet() { // The vector below has to be sorted. It is checked in unit test GetAllSoundedDistFeet static VecPairDist const inst = {{50, "in_50_feet"}, {100, "in_100_feet"}, {200, "in_200_feet"}, {300, "in_300_feet"}, {400, "in_400_feet"}, {500, "in_500_feet"}, {600, "in_600_feet"}, {700, "in_700_feet"}, {800, "in_800_feet"}, {900, "in_900_feet"}, {1000, "in_1000_feet"}, {1500, "in_1500_feet"}, {2000, "in_2000_feet"}, {2500, "in_2500_feet"}, {3000, "in_3000_feet"}, {3500, "in_3500_feet"}, {4000, "in_4000_feet"}, {4500, "in_4500_feet"}, {5000, "in_5000_feet"}, {5280, "in_1_mile"}, {7920, "in_1_5_miles"}, {10560, "in_2_miles"}}; return inst; } vector const & GetSoundedDistMeters() { // The vector has to be sorted. Besides that any of its elements has to be contained in // the vector which GetAllSoundedDistMeters() returns. // It is checked in the unit test GetSoundedDistMeters. static vector const inst = {200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500, 2000}; return inst; } vector const & GetSoundedDistFeet() { // The vector has to be sorted. Besides that any of its elements has to be contained in // the vector which GetAllSoundedDistFeet() returns. // It is checked in the unit test GetSoundedDistFeet. static vector const inst = {500, 600, 700, 800, 900, 1000, 1500, 2000, 3000, 4000, 5000}; return inst; } } // namespace sound } // namespace turns } // namespace routing