mirror of
https://codeberg.org/comaps/comaps
synced 2026-01-03 19:33:49 +00:00
Compare commits
7 Commits
zyphlar-pa
...
generate-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a04b59b047 | ||
|
|
2bf22bd8a7 | ||
|
|
75f345288e | ||
|
|
85cb731693 | ||
|
|
3f9b6e82b5 | ||
|
|
dd204ae036 | ||
|
|
1bd734d417 |
@@ -107,7 +107,6 @@ import app.organicmaps.sdk.routing.RoutingOptions;
|
|||||||
import app.organicmaps.sdk.search.SearchEngine;
|
import app.organicmaps.sdk.search.SearchEngine;
|
||||||
import app.organicmaps.sdk.settings.RoadType;
|
import app.organicmaps.sdk.settings.RoadType;
|
||||||
import app.organicmaps.sdk.settings.UnitLocale;
|
import app.organicmaps.sdk.settings.UnitLocale;
|
||||||
import app.organicmaps.sdk.sound.TtsPlayer;
|
|
||||||
import app.organicmaps.sdk.util.Config;
|
import app.organicmaps.sdk.util.Config;
|
||||||
import app.organicmaps.sdk.util.LocationUtils;
|
import app.organicmaps.sdk.util.LocationUtils;
|
||||||
import app.organicmaps.sdk.util.PowerManagment;
|
import app.organicmaps.sdk.util.PowerManagment;
|
||||||
@@ -133,6 +132,7 @@ import com.google.android.material.appbar.MaterialToolbar;
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.google.android.material.textview.MaterialTextView;
|
import com.google.android.material.textview.MaterialTextView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -1813,18 +1813,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverTtsMessage()
|
|
||||||
{
|
|
||||||
if (Config.isTtsMessageDelivered())
|
|
||||||
return;
|
|
||||||
|
|
||||||
String navigationStartMessage = getResources().getString(R.string.navigation_start_tts_message);
|
|
||||||
navigationStartMessage += TtsPlayer.INSTANCE.getLanguageDisplayName();
|
|
||||||
Toast.makeText(this, navigationStartMessage, Toast.LENGTH_LONG).show();
|
|
||||||
|
|
||||||
Config.setTtsMessageDelivered();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean showStartPointNotice()
|
private boolean showStartPointNotice()
|
||||||
{
|
{
|
||||||
final RoutingController controller = RoutingController.get();
|
final RoutingController controller = RoutingController.get();
|
||||||
@@ -2201,8 +2189,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||||||
if (!showRoutingDisclaimer())
|
if (!showRoutingDisclaimer())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
deliverTtsMessage();
|
|
||||||
|
|
||||||
closeFloatingPanels();
|
closeFloatingPanels();
|
||||||
setFullscreen(false);
|
setFullscreen(false);
|
||||||
RoutingController.get().start();
|
RoutingController.get().start();
|
||||||
|
|||||||
@@ -24,6 +24,6 @@
|
|||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:fontFamily="@string/robotoMedium"
|
android:fontFamily="@string/robotoMedium"
|
||||||
tools:text="Some text should go here"
|
tools:text="Some text should go here"
|
||||||
android:textAppearance="@style/MwmTextAppearance.Body1"
|
android:textAppearance="@style/MwmTextAppearance.Body3"
|
||||||
android:textColor="?colorSecondary"/>
|
android:textColor="?colorSecondary"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start|bottom"
|
android:layout_gravity="start|bottom"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:gravity="start|top"
|
android:gravity="start|top"
|
||||||
android:text="@string/category_desc_more"
|
android:text="@string/category_desc_more"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/editor_height_field"
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
@@ -14,7 +14,8 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:hint="@string/editor_edit_place_name_hint">
|
android:hint="@string/editor_edit_place_name_hint"
|
||||||
|
android:textColorHint="?android:textColorSecondary">
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/input"
|
android:id="@+id/input"
|
||||||
style="@style/MwmWidget.Editor.FieldLayout.EditText"
|
style="@style/MwmWidget.Editor.FieldLayout.EditText"
|
||||||
@@ -30,5 +31,5 @@
|
|||||||
android:background="?selectableItemBackgroundBorderless"
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
android:padding="@dimen/margin_half_plus"
|
android:padding="@dimen/margin_half_plus"
|
||||||
app:srcCompat="@drawable/ic_close"
|
app:srcCompat="@drawable/ic_close"
|
||||||
app:tint="?iconTint" />
|
app:tint="@color/base_red" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -35,10 +35,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:padding="@dimen/margin_half"
|
android:padding="@dimen/margin_quarter"
|
||||||
android:autoSizeTextType="uniform"
|
android:autoSizeTextType="uniform"
|
||||||
android:autoSizeMinTextSize="19sp"
|
android:autoSizeMinTextSize="19sp"
|
||||||
android:autoSizeMaxTextSize="24sp"
|
android:autoSizeMaxTextSize="25sp"
|
||||||
android:minHeight="60dp"
|
android:minHeight="60dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
|||||||
@@ -34,7 +34,8 @@
|
|||||||
android:textAppearance="?android:attr/textAppearance"
|
android:textAppearance="?android:attr/textAppearance"
|
||||||
android:gravity="start|top"
|
android:gravity="start|top"
|
||||||
android:textColor="?attr/colorSecondary"
|
android:textColor="?attr/colorSecondary"
|
||||||
android:text="@string/category_desc_more" />
|
android:text="@string/category_desc_more"
|
||||||
|
android:background="@android:color/transparent"/>
|
||||||
<include
|
<include
|
||||||
layout="@layout/item_divider"/>
|
layout="@layout/item_divider"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
<string name="pref_tts_info" translatable="false">TtsInfo</string>
|
<string name="pref_tts_info" translatable="false">TtsInfo</string>
|
||||||
<string name="pref_tts_info_link" translatable="false">TtsInfoLink</string>
|
<string name="pref_tts_info_link" translatable="false">TtsInfoLink</string>
|
||||||
<string name="pref_tts_speed_cameras" translatable="false">SpeedCameras</string>
|
<string name="pref_tts_speed_cameras" translatable="false">SpeedCameras</string>
|
||||||
<string name="pref_tts_speed_cameras_info" translatable="false">SpeedCamerasInfo</string>
|
|
||||||
<string name="prefs_routing" translatable="false">RoutingOptions</string>
|
<string name="prefs_routing" translatable="false">RoutingOptions</string>
|
||||||
<string name="pref_autodownload" translatable="false">AutoDownloadMap</string>
|
<string name="pref_autodownload" translatable="false">AutoDownloadMap</string>
|
||||||
<string name="pref_3d" translatable="false">3D</string>
|
<string name="pref_3d" translatable="false">3D</string>
|
||||||
|
|||||||
@@ -609,7 +609,6 @@
|
|||||||
\nOpen your device\'s settings → Language and input → Speech → Text to speech output.
|
\nOpen your device\'s settings → Language and input → Speech → Text to speech output.
|
||||||
\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine.</string>
|
\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine.</string>
|
||||||
<string name="prefs_languages_information_off_link">For more information please check this guide</string>
|
<string name="prefs_languages_information_off_link">For more information please check this guide</string>
|
||||||
<string name="prefs_speed_cameras_information">Speed camera warnings are disabled in countries where alerts are prohibited by local law.</string>
|
|
||||||
<string name="transliteration_title">Transliterate into Latin alphabet</string>
|
<string name="transliteration_title">Transliterate into Latin alphabet</string>
|
||||||
<string name="learn_more">Learn more</string>
|
<string name="learn_more">Learn more</string>
|
||||||
<!-- User selected the destination by pressing Route To, but the current position is unknown. User needs to select a starting point of a route using search or by tapping on the map and then pressing "Route From". -->
|
<!-- User selected the destination by pressing Route To, but the current position is unknown. User needs to select a starting point of a route using search or by tapping on the map and then pressing "Route From". -->
|
||||||
@@ -933,7 +932,6 @@
|
|||||||
<string name="share_track">Share Track</string>
|
<string name="share_track">Share Track</string>
|
||||||
<string name="delete_track_dialog_title">Delete %s?</string>
|
<string name="delete_track_dialog_title">Delete %s?</string>
|
||||||
<string name="pref_tts_no_system_tts_short">No text-to-speech engine found, check the app settings</string>
|
<string name="pref_tts_no_system_tts_short">No text-to-speech engine found, check the app settings</string>
|
||||||
<string name="navigation_start_tts_message">"Starting Navigation, voice instruction language: "</string>
|
|
||||||
<string name="unknown_power_output">unknown</string>
|
<string name="unknown_power_output">unknown</string>
|
||||||
<string name="charge_socket_type2">Type 2 (no cable)</string>
|
<string name="charge_socket_type2">Type 2 (no cable)</string>
|
||||||
<string name="charge_socket_type2_cable">Type 2 (w/ cable)</string>
|
<string name="charge_socket_type2_cable">Type 2 (w/ cable)</string>
|
||||||
|
|||||||
@@ -57,11 +57,4 @@
|
|||||||
android:entryValues="@array/speed_cameras_values"
|
android:entryValues="@array/speed_cameras_values"
|
||||||
android:defaultValue="@string/auto_enum_value"
|
android:defaultValue="@string/auto_enum_value"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
<Preference
|
|
||||||
android:enabled="true"
|
|
||||||
android:key="@string/pref_tts_info_link"
|
|
||||||
android:persistent="false"
|
|
||||||
android:selectable="false"
|
|
||||||
android:summary="@string/prefs_speed_cameras_information"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package app.organicmaps.sdk.sound;
|
package app.organicmaps.sdk.sound;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -15,8 +14,6 @@ import android.util.Pair;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.os.ConfigurationCompat;
|
|
||||||
import androidx.core.os.LocaleListCompat;
|
|
||||||
import androidx.media.AudioAttributesCompat;
|
import androidx.media.AudioAttributesCompat;
|
||||||
import androidx.media.AudioFocusRequestCompat;
|
import androidx.media.AudioFocusRequestCompat;
|
||||||
import androidx.media.AudioManagerCompat;
|
import androidx.media.AudioManagerCompat;
|
||||||
@@ -26,7 +23,6 @@ import app.organicmaps.sdk.util.log.Logger;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code TtsPlayer} class manages available TTS voice languages.
|
* {@code TtsPlayer} class manages available TTS voice languages.
|
||||||
@@ -37,9 +33,9 @@ import java.util.Set;
|
|||||||
* unsupported voices are excluded.
|
* unsupported voices are excluded.
|
||||||
* <p>
|
* <p>
|
||||||
* At startup we check whether currently selected language is in our list of supported voices and its data is
|
* At startup we check whether currently selected language is in our list of supported voices and its data is
|
||||||
* downloaded. If not, we check system default locale. If failed, the same check is made for other system locales.
|
* downloaded. If not, we check system default locale. If failed, the same check is made for English language. Finally,
|
||||||
* If those fail too, we check for English language. Then, as a final resort, all installed TTS locales are checked.
|
* if mentioned checks fail we manually disable TTS, so the user must go to the settings and select preferred voice
|
||||||
* <p> If no core supported languages can be used by the system, TTS is locked down and can not be
|
* language by hand. <p> If no core supported languages can be used by the system, TTS is locked down and can not be
|
||||||
* enabled and used.
|
* enabled and used.
|
||||||
*/
|
*/
|
||||||
public enum TtsPlayer
|
public enum TtsPlayer
|
||||||
@@ -82,8 +78,6 @@ public enum TtsPlayer
|
|||||||
// TTS is locked down due to absence of supported languages
|
// TTS is locked down due to absence of supported languages
|
||||||
private boolean mUnavailable;
|
private boolean mUnavailable;
|
||||||
|
|
||||||
private LocaleListCompat mInstalledSystemLocales;
|
|
||||||
|
|
||||||
TtsPlayer() {}
|
TtsPlayer() {}
|
||||||
|
|
||||||
private static @Nullable LanguageData findSupportedLanguage(String internalCode, List<LanguageData> langs)
|
private static @Nullable LanguageData findSupportedLanguage(String internalCode, List<LanguageData> langs)
|
||||||
@@ -132,59 +126,30 @@ public enum TtsPlayer
|
|||||||
return (lang != null && setLanguageInternal(lang));
|
return (lang != null && setLanguageInternal(lang));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs)
|
|
||||||
{
|
|
||||||
return findSupportedLanguage(Config.TTS.getLanguage(), langs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private @Nullable LanguageData getSystemLanguage(List<LanguageData> langs)
|
|
||||||
{
|
|
||||||
LanguageData res;
|
|
||||||
|
|
||||||
// Try default system locale
|
|
||||||
Locale defLocale = Locale.getDefault();
|
|
||||||
res = findSupportedLanguage(defLocale, langs);
|
|
||||||
if (res != null && res.downloaded)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
// Try other installed system locales
|
|
||||||
for (int i = 0; i < mInstalledSystemLocales.size(); i++)
|
|
||||||
{
|
|
||||||
Locale loc = mInstalledSystemLocales.get(i);
|
|
||||||
res = findSupportedLanguage(loc, langs);
|
|
||||||
if (res != null && res.downloaded)
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private @Nullable LanguageData getTTSLanguage(List<LanguageData> langs)
|
|
||||||
{
|
|
||||||
LanguageData res;
|
|
||||||
|
|
||||||
// Try all TTS installed languages
|
|
||||||
Set<Locale> ttsLocales = mTts.getAvailableLanguages();
|
|
||||||
for (Locale loc : ttsLocales)
|
|
||||||
{
|
|
||||||
res = findSupportedLanguage(loc, langs);
|
|
||||||
if (res != null && res.downloaded)
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs)
|
private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs)
|
||||||
{
|
{
|
||||||
LanguageData res;
|
LanguageData res;
|
||||||
|
|
||||||
// Try default app locale (en.US)
|
Locale defLocale = Locale.getDefault();
|
||||||
|
if (defLocale != null)
|
||||||
|
{
|
||||||
|
res = findSupportedLanguage(defLocale, langs);
|
||||||
|
if (res != null && res.downloaded)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
res = findSupportedLanguage(DEFAULT_LOCALE, langs);
|
res = findSupportedLanguage(DEFAULT_LOCALE, langs);
|
||||||
if (res != null && res.downloaded)
|
if (res != null && res.downloaded)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs)
|
||||||
|
{
|
||||||
|
return findSupportedLanguage(Config.TTS.getLanguage(), langs);
|
||||||
|
}
|
||||||
|
|
||||||
private void lockDown()
|
private void lockDown()
|
||||||
{
|
{
|
||||||
mUnavailable = true;
|
mUnavailable = true;
|
||||||
@@ -202,10 +167,6 @@ public enum TtsPlayer
|
|||||||
// TextToSpeech.OnInitListener() can be called from a non-main thread
|
// TextToSpeech.OnInitListener() can be called from a non-main thread
|
||||||
// on LineageOS '20.0-20231127-RELEASE-thyme' 'Xiaomi/thyme/thyme'.
|
// on LineageOS '20.0-20231127-RELEASE-thyme' 'Xiaomi/thyme/thyme'.
|
||||||
// https://github.com/organicmaps/organicmaps/issues/6903
|
// https://github.com/organicmaps/organicmaps/issues/6903
|
||||||
|
|
||||||
Configuration config = context.getResources().getConfiguration();
|
|
||||||
mInstalledSystemLocales = ConfigurationCompat.getLocales(config);
|
|
||||||
|
|
||||||
mTts = new TextToSpeech(context, status -> UiThread.run(() -> {
|
mTts = new TextToSpeech(context, status -> UiThread.run(() -> {
|
||||||
if (status == TextToSpeech.ERROR)
|
if (status == TextToSpeech.ERROR)
|
||||||
{
|
{
|
||||||
@@ -278,17 +239,6 @@ public enum TtsPlayer
|
|||||||
return (INSTANCE.mTts != null && !INSTANCE.mUnavailable && !INSTANCE.mInitializing);
|
return (INSTANCE.mTts != null && !INSTANCE.mUnavailable && !INSTANCE.mInitializing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Locale getVoiceLocale()
|
|
||||||
{
|
|
||||||
return mTts.getVoice().getLocale();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLanguageDisplayName()
|
|
||||||
{
|
|
||||||
Locale locale = getVoiceLocale();
|
|
||||||
return locale.getDisplayName(locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void speak(String textToSpeak)
|
public void speak(String textToSpeak)
|
||||||
{
|
{
|
||||||
if (Config.TTS.isEnabled())
|
if (Config.TTS.isEnabled())
|
||||||
@@ -378,49 +328,24 @@ public enum TtsPlayer
|
|||||||
|
|
||||||
if (outList.isEmpty())
|
if (outList.isEmpty())
|
||||||
{
|
{
|
||||||
Logger.d("TtsPlayer", "No supported languages found, lock down TTS :( ");
|
// No supported languages found, lock down TTS :(
|
||||||
lockDown();
|
lockDown();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
LanguageData res = getSelectedLanguage(outList);
|
LanguageData res = getSelectedLanguage(outList);
|
||||||
if (res != null && res.downloaded)
|
if (res == null || !res.downloaded)
|
||||||
{
|
// Selected locale is not available or not downloaded
|
||||||
Logger.d("TtsPlayer", "Selected locale " + res.internalCode + " will be used for TTS");
|
res = getDefaultLanguage(outList);
|
||||||
return res;
|
|
||||||
}
|
|
||||||
Logger.d("TtsPlayer", "Selected locale " + Config.TTS.getLanguage()
|
|
||||||
+ " is not available or not downloaded, trying system locales...");
|
|
||||||
|
|
||||||
res = getSystemLanguage(outList);
|
if (res == null || !res.downloaded)
|
||||||
if (res != null && res.downloaded)
|
|
||||||
{
|
{
|
||||||
Logger.d("TtsPlayer", "System locale " + res.internalCode + " will be used for TTS");
|
// Default locale can not be used too
|
||||||
return res;
|
Config.TTS.setEnabled(false);
|
||||||
}
|
return null;
|
||||||
Logger.d("TtsPlayer",
|
|
||||||
"None of the system locales are available, or they are not downloaded, trying default locale...");
|
|
||||||
|
|
||||||
res = getDefaultLanguage(outList);
|
|
||||||
if (res != null && res.downloaded)
|
|
||||||
{
|
|
||||||
Logger.d("TtsPlayer", "Default locale " + res.internalCode + " will be used for TTS");
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
Logger.d("TtsPlayer",
|
|
||||||
"Default locale " + DEFAULT_LOCALE + " can not be used either, trying all installed TTS locales...");
|
|
||||||
|
|
||||||
res = getTTSLanguage(outList);
|
|
||||||
if (res != null && res.downloaded)
|
|
||||||
{
|
|
||||||
Logger.d("TtsPlayer", "TTS locale " + res.internalCode + " will be used for TTS");
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.d("TtsPlayer",
|
return res;
|
||||||
"None of the TTS engine locales are available, or they are not downloaded, disabling TTS :( ");
|
|
||||||
Config.TTS.setEnabled(false);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull List<LanguageData> refreshLanguages()
|
public @NonNull List<LanguageData> refreshLanguages()
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ public final class Config
|
|||||||
private static final String KEY_PREF_USE_GS = "UseGoogleServices";
|
private static final String KEY_PREF_USE_GS = "UseGoogleServices";
|
||||||
|
|
||||||
private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved";
|
private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved";
|
||||||
private static final String KEY_MISC_TTS_MESSAGE_DELIVERED = "TtsMessageDelivered";
|
|
||||||
private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested";
|
private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested";
|
||||||
private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData";
|
private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData";
|
||||||
private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp";
|
private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp";
|
||||||
@@ -238,16 +237,6 @@ public final class Config
|
|||||||
setBool(KEY_MISC_DISCLAIMER_ACCEPTED);
|
setBool(KEY_MISC_DISCLAIMER_ACCEPTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isTtsMessageDelivered()
|
|
||||||
{
|
|
||||||
return getBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setTtsMessageDelivered()
|
|
||||||
{
|
|
||||||
setBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isLocationRequested()
|
public static boolean isLocationRequested()
|
||||||
{
|
{
|
||||||
return getBool(KEY_MISC_LOCATION_REQUESTED);
|
return getBool(KEY_MISC_LOCATION_REQUESTED);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ node[shop],
|
|||||||
node[amenity=car_wash],
|
node[amenity=car_wash],
|
||||||
node[amenity=fuel],
|
node[amenity=fuel],
|
||||||
node[amenity=studio],
|
node[amenity=studio],
|
||||||
|
node[amenity=toilets],
|
||||||
node[amenity=vehicle_inspection],
|
node[amenity=vehicle_inspection],
|
||||||
node[craft],
|
node[craft],
|
||||||
node[landuse=industrial][industrial=mine],
|
node[landuse=industrial][industrial=mine],
|
||||||
@@ -137,7 +138,6 @@ node[amenity=prison],
|
|||||||
node[amenity=recycling][recycling_type=centre],
|
node[amenity=recycling][recycling_type=centre],
|
||||||
node[amenity=sailing_school],
|
node[amenity=sailing_school],
|
||||||
node[amenity=school],
|
node[amenity=school],
|
||||||
node[amenity=toilets],
|
|
||||||
node[amenity=townhall],
|
node[amenity=townhall],
|
||||||
node[amenity=university][name],
|
node[amenity=university][name],
|
||||||
node[barrier=border_control],
|
node[barrier=border_control],
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ This document gives some guidelines to write and review PR with essential elemen
|
|||||||
- New functionality and unit or integration tests for it should be developed in the same PR
|
- New functionality and unit or integration tests for it should be developed in the same PR
|
||||||
- Every commit of all PRs should be compilable under all platforms and all tests should pass. If changes break unit or integration tests, then these tests should be fixed, ideally before opening a PR.
|
- Every commit of all PRs should be compilable under all platforms and all tests should pass. If changes break unit or integration tests, then these tests should be fixed, ideally before opening a PR.
|
||||||
- Every commit should reflect a completed idea and have an understandable comment. Review fixes should be merged into one commit
|
- Every commit should reflect a completed idea and have an understandable comment. Review fixes should be merged into one commit
|
||||||
- When some source files are changed and then some other source files based on them are auto-generated, they should be committed in different commits. For example, if you change style (mapcss) files, then put auto-generated files into a separate [styles] Regenerate commit
|
|
||||||
- Whitespace and formatting changes should be a separate commit from logical changes, and possibly even be a separate cleanup PR, to make reviewing and merging easier.
|
|
||||||
- All commits and PR captions should be written in English.
|
- All commits and PR captions should be written in English.
|
||||||
- We suggest PRs should have prefixes in square brackets depending on the changed subsystem. For example, [routing], [generator], or [android]. Commits may have several prefixes (See `git log --oneline|egrep -o '\[[0-9a-z]*\]'|sort|uniq -c|sort -nr|less` for ideas.)
|
- We suggest PRs should have prefixes in square brackets depending on the changed subsystem. For example, [routing], [generator], or [android]. Commits may have several prefixes (See `git log --oneline|egrep -o '\[[0-9a-z]*\]'|sort|uniq -c|sort -nr|less` for ideas.)
|
||||||
- Use imperative mood in commit's message, e.g. `[core] Fix gcc warnings` not `[core] Fixed gcc warnings`
|
- Use imperative mood in commit's message, e.g. `[core] Fix gcc warnings` not `[core] Fixed gcc warnings`
|
||||||
|
- When some source files are changed and then some other source files based on them are auto-generated, they should be committed in different commits. For example, if you change style (mapcss) files, then put auto-generated files into a separate [styles] Regenerate commit
|
||||||
- All code bases should conform to ./docs/CPP_STYLE.md, ./docs/OBJC_STYLE.md, ./docs/JAVA_STYLE.md or other style in ./docs/ depending on the language
|
- All code bases should conform to ./docs/CPP_STYLE.md, ./docs/OBJC_STYLE.md, ./docs/JAVA_STYLE.md or other style in ./docs/ depending on the language
|
||||||
- The description field of every PR should contain a description to explain **what and why** vs. how.
|
- The description field of every PR should contain a description to explain **what and why** vs. how.
|
||||||
- If your changes are visual (e.g. app UI or map style changes) then please add before/after screenshots or videos.
|
- If your changes are visual (e.g. app UI or map style changes) then please add before/after screenshots or videos.
|
||||||
|
|||||||
@@ -441,13 +441,12 @@ void DrapeEngine::SetCompassInfo(location::CompassInfo const & info)
|
|||||||
MessagePriority::Normal);
|
MessagePriority::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable,
|
||||||
location::RouteMatchingInfo const & routeInfo)
|
location::RouteMatchingInfo const & routeInfo)
|
||||||
{
|
{
|
||||||
m_threadCommutator->PostMessage(
|
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
|
||||||
ThreadsCommutator::RenderThread,
|
make_unique_dp<GpsInfoMessage>(info, isNavigable, routeInfo),
|
||||||
make_unique_dp<GpsInfoMessage>(info, isNavigable, distToNextTurn, speedLimit, routeInfo),
|
MessagePriority::Normal);
|
||||||
MessagePriority::Normal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrapeEngine::SwitchMyPositionNextMode()
|
void DrapeEngine::SwitchMyPositionNextMode()
|
||||||
|
|||||||
@@ -154,8 +154,7 @@ public:
|
|||||||
void UpdateMapStyle();
|
void UpdateMapStyle();
|
||||||
|
|
||||||
void SetCompassInfo(location::CompassInfo const & info);
|
void SetCompassInfo(location::CompassInfo const & info);
|
||||||
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo);
|
||||||
location::RouteMatchingInfo const & routeInfo);
|
|
||||||
void SwitchMyPositionNextMode();
|
void SwitchMyPositionNextMode();
|
||||||
void LoseLocation();
|
void LoseLocation();
|
||||||
void StopLocationFollow();
|
void StopLocationFollow();
|
||||||
|
|||||||
@@ -438,8 +438,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
ref_ptr<GpsInfoMessage> msg = message;
|
ref_ptr<GpsInfoMessage> msg = message;
|
||||||
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), msg->GetDistanceToNextTurn(),
|
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), m_userEventStream.GetCurrentScreen());
|
||||||
msg->GetSpeedLimit(), m_userEventStream.GetCurrentScreen());
|
|
||||||
|
|
||||||
location::RouteMatchingInfo const & info = msg->GetRouteInfo();
|
location::RouteMatchingInfo const & info = msg->GetRouteInfo();
|
||||||
if (info.HasDistanceFromBegin())
|
if (info.HasDistanceFromBegin())
|
||||||
|
|||||||
@@ -481,12 +481,9 @@ private:
|
|||||||
class GpsInfoMessage : public Message
|
class GpsInfoMessage : public Message
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo)
|
||||||
location::RouteMatchingInfo const & routeInfo)
|
|
||||||
: m_info(info)
|
: m_info(info)
|
||||||
, m_isNavigable(isNavigable)
|
, m_isNavigable(isNavigable)
|
||||||
, m_distToNextTurn(distToNextTurn)
|
|
||||||
, m_speedLimit(speedLimit)
|
|
||||||
, m_routeInfo(routeInfo)
|
, m_routeInfo(routeInfo)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -494,15 +491,11 @@ public:
|
|||||||
|
|
||||||
location::GpsInfo const & GetInfo() const { return m_info; }
|
location::GpsInfo const & GetInfo() const { return m_info; }
|
||||||
bool IsNavigable() const { return m_isNavigable; }
|
bool IsNavigable() const { return m_isNavigable; }
|
||||||
double const & GetSpeedLimit() const { return m_speedLimit; }
|
|
||||||
double const & GetDistanceToNextTurn() const { return m_distToNextTurn; }
|
|
||||||
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
|
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
location::GpsInfo const m_info;
|
location::GpsInfo const m_info;
|
||||||
bool const m_isNavigable;
|
bool const m_isNavigable;
|
||||||
double const m_distToNextTurn;
|
|
||||||
double const m_speedLimit;
|
|
||||||
location::RouteMatchingInfo const m_routeInfo;
|
location::RouteMatchingInfo const m_routeInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -56,18 +56,32 @@ inline double GetVisualScale()
|
|||||||
return df::VisualParams::Instance().GetVisualScale();
|
return df::VisualParams::Instance().GetVisualScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
double CalculateZoomByMaxSpeed(double speedMpS, bool isPerspectiveAllowed)
|
// Calculate zoom value in meters per pixel
|
||||||
|
double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
|
||||||
{
|
{
|
||||||
using TSpeedScale = std::pair<double, double>;
|
using TSpeedScale = std::pair<double, double>;
|
||||||
static std::array<TSpeedScale, 2> const scales2d = {{
|
static std::array<TSpeedScale, 6> const scales3d = {{
|
||||||
{0.0, 1.75}, {77.0, 4.50} // 48 mph
|
{20.0, 0.25},
|
||||||
|
{40.0, 0.75},
|
||||||
|
{60.0, 1.50},
|
||||||
|
{75.0, 2.50},
|
||||||
|
{85.0, 3.75},
|
||||||
|
{95.0, 6.00},
|
||||||
}};
|
}};
|
||||||
static std::array<TSpeedScale, 2> const scales3d = {{{0.0, 1.00}, {77.0, 4.50}}};
|
|
||||||
|
|
||||||
std::array<TSpeedScale, 2> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
|
static std::array<TSpeedScale, 6> const scales2d = {{
|
||||||
|
{20.0, 0.70},
|
||||||
|
{40.0, 1.25},
|
||||||
|
{60.0, 2.25},
|
||||||
|
{75.0, 3.00},
|
||||||
|
{85.0, 3.75},
|
||||||
|
{95.0, 6.00},
|
||||||
|
}};
|
||||||
|
|
||||||
double constexpr kDefaultSpeedLimitKmpH = 50.0;
|
std::array<TSpeedScale, 6> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
|
||||||
double const speedKmpH = speedMpS > 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedLimitKmpH;
|
|
||||||
|
double constexpr kDefaultSpeedKmpH = 80.0;
|
||||||
|
double const speedKmpH = speedMpS >= 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedKmpH;
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (size_t sz = scales.size(); i < sz; ++i)
|
for (size_t sz = scales.size(); i < sz; ++i)
|
||||||
@@ -78,64 +92,20 @@ double CalculateZoomByMaxSpeed(double speedMpS, bool isPerspectiveAllowed)
|
|||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return scales.front().second / vs;
|
return scales.front().second / vs;
|
||||||
|
if (i == scales.size())
|
||||||
|
return scales.back().second / vs;
|
||||||
|
|
||||||
return scales[i - 1].second / vs;
|
double const minSpeed = scales[i - 1].first;
|
||||||
}
|
double const maxSpeed = scales[i].first;
|
||||||
|
double const k = (speedKmpH - minSpeed) / (maxSpeed - minSpeed);
|
||||||
|
|
||||||
double CalculateZoomByDistanceToTurn(double distance, bool isPerspectiveAllowed)
|
double const minScale = scales[i - 1].second;
|
||||||
{
|
double const maxScale = scales[i].second;
|
||||||
using TSpeedScale = std::pair<double, double>;
|
|
||||||
static std::array<TSpeedScale, 5> const scales2d = {{
|
|
||||||
{200, 0.50},
|
|
||||||
{500, 0.80}, // 0.3 mi
|
|
||||||
{1200, 1.75}, // 0.75 mi
|
|
||||||
{2000, 3.50}, // 1.2 mi
|
|
||||||
{5000, 6.50} // 3 mi
|
|
||||||
}};
|
|
||||||
static std::array<TSpeedScale, 5> const scales3d = {{
|
|
||||||
{200, 0.25},
|
|
||||||
{500, 0.60}, // 0.3 mi
|
|
||||||
{1200, 1.25}, // 0.75 mi
|
|
||||||
{2000, 3.50}, // 1.2 mi
|
|
||||||
{5000, 6.50} // 3 mi
|
|
||||||
}};
|
|
||||||
|
|
||||||
std::array<TSpeedScale, 5> const & scale = isPerspectiveAllowed ? scales3d : scales2d;
|
|
||||||
|
|
||||||
double constexpr kDefaultDistance = 2000;
|
|
||||||
double const distanceM = distance >= 0 ? distance : kDefaultDistance;
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
for (size_t sz = scale.size(); i < sz; ++i)
|
|
||||||
if (scale[i].first >= distanceM)
|
|
||||||
break;
|
|
||||||
|
|
||||||
double const vs = GetVisualScale();
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
return scale.front().second / vs;
|
|
||||||
if (i == scale.size())
|
|
||||||
return scale.back().second / vs;
|
|
||||||
|
|
||||||
double const minDist = scale[i - 1].first;
|
|
||||||
double const maxDist = scale[i].first;
|
|
||||||
double const k = (distanceM - minDist) / (maxDist - minDist);
|
|
||||||
|
|
||||||
double const minScale = scale[i - 1].second;
|
|
||||||
double const maxScale = scale[i].second;
|
|
||||||
double const zoom = minScale + k * (maxScale - minScale);
|
double const zoom = minScale + k * (maxScale - minScale);
|
||||||
|
|
||||||
return zoom / vs;
|
return zoom / vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
double CalculateAutoZoom(double speedMpS, double distanceToTurn, bool isPerspectiveAllowed)
|
|
||||||
{
|
|
||||||
double const zoomByDistance = CalculateZoomByDistanceToTurn(distanceToTurn, isPerspectiveAllowed);
|
|
||||||
double const zoomByMaxSpeed = CalculateZoomByMaxSpeed(speedMpS, isPerspectiveAllowed);
|
|
||||||
|
|
||||||
return std::min(zoomByDistance, zoomByMaxSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResetNotification(uint64_t & notifyId)
|
void ResetNotification(uint64_t & notifyId)
|
||||||
{
|
{
|
||||||
notifyId = DrapeNotifier::kInvalidId;
|
notifyId = DrapeNotifier::kInvalidId;
|
||||||
@@ -425,8 +395,7 @@ void MyPositionController::NextMode(ScreenBase const & screen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn,
|
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen)
|
||||||
double speedLimit, ScreenBase const & screen)
|
|
||||||
{
|
{
|
||||||
m2::PointD const oldPos = GetDrawablePosition();
|
m2::PointD const oldPos = GetDrawablePosition();
|
||||||
double const oldAzimut = GetDrawableAzimut();
|
double const oldAzimut = GetDrawableAzimut();
|
||||||
@@ -438,13 +407,11 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool
|
|||||||
m_errorRadius = rect.SizeX() * 0.5;
|
m_errorRadius = rect.SizeX() * 0.5;
|
||||||
m_horizontalAccuracy = info.m_horizontalAccuracy;
|
m_horizontalAccuracy = info.m_horizontalAccuracy;
|
||||||
|
|
||||||
if (distanceToNextTurn >= 0.0 || speedLimit >= 0.0)
|
if (info.m_speed > 0.0)
|
||||||
{
|
{
|
||||||
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
|
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
|
||||||
m_autoScale2d =
|
m_autoScale2d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, false /* isPerspectiveAllowed */);
|
||||||
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, false /* isPerspectiveAllowed */);
|
m_autoScale3d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, true /* isPerspectiveAllowed */);
|
||||||
m_autoScale3d =
|
|
||||||
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, true /* isPerspectiveAllowed */);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -117,8 +117,7 @@ public:
|
|||||||
void OnEnterBackground();
|
void OnEnterBackground();
|
||||||
|
|
||||||
void OnCompassTapped();
|
void OnCompassTapped();
|
||||||
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn, double speedLimit,
|
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen);
|
||||||
ScreenBase const & screen);
|
|
||||||
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
|
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
|
||||||
|
|
||||||
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,
|
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,
|
||||||
|
|||||||
@@ -1171,7 +1171,6 @@ void RoutingManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAl
|
|||||||
{
|
{
|
||||||
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
|
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
|
||||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
|
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
|
||||||
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
|
|
||||||
routeMatchingInfo);
|
routeMatchingInfo);
|
||||||
m_gpsInfoCache.reset();
|
m_gpsInfoCache.reset();
|
||||||
}
|
}
|
||||||
@@ -1516,9 +1515,7 @@ void RoutingManager::OnExtrapolatedLocationUpdate(location::GpsInfo const & info
|
|||||||
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
|
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
|
||||||
|
|
||||||
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
|
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
|
||||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(),
|
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(), routeMatchingInfo);
|
||||||
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
|
|
||||||
routeMatchingInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoutingManager::DeleteSavedRoutePoints()
|
void RoutingManager::DeleteSavedRoutePoints()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "base/assert.hpp"
|
#include "base/assert.hpp"
|
||||||
#include "base/buffer_vector.hpp"
|
#include "base/buffer_vector.hpp"
|
||||||
|
|
||||||
|
#include <execution>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -117,27 +118,31 @@ public:
|
|||||||
template <class FnT>
|
template <class FnT>
|
||||||
void ForEachEnter(FnT && fn) const
|
void ForEachEnter(FnT && fn) const
|
||||||
{
|
{
|
||||||
for (auto const & [key, transit] : m_transitions)
|
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair)
|
||||||
{
|
{
|
||||||
|
auto const & [key, transit] = pair;
|
||||||
|
|
||||||
if (transit.m_forwardIsEnter)
|
if (transit.m_forwardIsEnter)
|
||||||
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
||||||
|
|
||||||
if (!transit.m_oneWay && !transit.m_forwardIsEnter)
|
if (!transit.m_oneWay && !transit.m_forwardIsEnter)
|
||||||
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class FnT>
|
template <class FnT>
|
||||||
void ForEachExit(FnT && fn) const
|
void ForEachExit(FnT && fn) const
|
||||||
{
|
{
|
||||||
for (auto const & [key, transit] : m_transitions)
|
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair)
|
||||||
{
|
{
|
||||||
|
auto const & [key, transit] = pair;
|
||||||
|
|
||||||
if (!transit.m_forwardIsEnter)
|
if (!transit.m_forwardIsEnter)
|
||||||
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
|
||||||
|
|
||||||
if (!transit.m_oneWay && transit.m_forwardIsEnter)
|
if (!transit.m_oneWay && transit.m_forwardIsEnter)
|
||||||
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetOutgoingEdgeList(Segment const & segment, EdgeListT & edges) const
|
void GetOutgoingEdgeList(Segment const & segment, EdgeListT & edges) const
|
||||||
|
|||||||
@@ -4,16 +4,14 @@
|
|||||||
#include "routing/routing_options.hpp"
|
#include "routing/routing_options.hpp"
|
||||||
#include "routing/world_graph.hpp"
|
#include "routing/world_graph.hpp"
|
||||||
|
|
||||||
#include "platform/settings.hpp"
|
|
||||||
|
|
||||||
#include "base/assert.hpp"
|
#include "base/assert.hpp"
|
||||||
#include "base/checked_cast.hpp"
|
#include "base/checked_cast.hpp"
|
||||||
#include "base/exception.hpp"
|
|
||||||
#include "base/timer.hpp"
|
#include "base/timer.hpp"
|
||||||
|
|
||||||
#include "geometry/distance_on_sphere.hpp"
|
#include "geometry/distance_on_sphere.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <execution>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -321,7 +319,9 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
|
|
||||||
auto const & weightTimeToParent = parentVertexData.m_realDistance;
|
auto const & weightTimeToParent = parentVertexData.m_realDistance;
|
||||||
auto const & parentJoint = parentVertexData.m_vertex;
|
auto const & parentJoint = parentVertexData.m_vertex;
|
||||||
for (size_t i = 0; i < firstChildren.size(); ++i)
|
|
||||||
|
auto const range = std::ranges::views::iota(0uz, firstChildren.size());
|
||||||
|
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
|
||||||
{
|
{
|
||||||
auto const & firstChild = firstChildren[i];
|
auto const & firstChild = firstChildren[i];
|
||||||
auto const lastPointId = lastPointIds[i];
|
auto const lastPointId = lastPointIds[i];
|
||||||
@@ -335,22 +335,21 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
{ return currentPointId < lastPointId ? pointId + 1 : pointId - 1; };
|
{ return currentPointId < lastPointId ? pointId + 1 : pointId - 1; };
|
||||||
|
|
||||||
if (IsAccessNoForSure(firstChild.GetFeatureId(), weightTimeToParent, true /* useAccessConditional */))
|
if (IsAccessNoForSure(firstChild.GetFeatureId(), weightTimeToParent, true /* useAccessConditional */))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
if (IsAccessNoForSure(parent.GetRoadPoint(isOutgoing), weightTimeToParent, true /* useAccessConditional */))
|
if (IsAccessNoForSure(parent.GetRoadPoint(isOutgoing), weightTimeToParent, true /* useAccessConditional */))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
if (IsUTurn(parent, firstChild) && IsUTurnAndRestricted(parent, firstChild, isOutgoing))
|
if (IsUTurn(parent, firstChild) && IsUTurnAndRestricted(parent, firstChild, isOutgoing))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
if (IsRestricted(parentJoint, parent.GetFeatureId(), firstChild.GetFeatureId(), isOutgoing, parents))
|
if (IsRestricted(parentJoint, parent.GetFeatureId(), firstChild.GetFeatureId(), isOutgoing, parents))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
RouteWeight summaryWeight;
|
RouteWeight summaryWeight;
|
||||||
// Check current JointSegment for bad road access between segments.
|
// Check current JointSegment for bad road access between segments.
|
||||||
RoadPoint rp = firstChild.GetRoadPoint(isOutgoing);
|
RoadPoint rp = firstChild.GetRoadPoint(isOutgoing);
|
||||||
uint32_t start = currentPointId;
|
uint32_t start = currentPointId;
|
||||||
bool noRoadAccess = false;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// This is optimization: we calculate accesses of road points before calculating weight of
|
// This is optimization: we calculate accesses of road points before calculating weight of
|
||||||
@@ -360,19 +359,13 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
// until this |rp|. But we assume that segments have small length and inaccuracy will not
|
// until this |rp|. But we assume that segments have small length and inaccuracy will not
|
||||||
// affect user.
|
// affect user.
|
||||||
if (IsAccessNoForSure(rp, weightTimeToParent, true /* useAccessConditional */))
|
if (IsAccessNoForSure(rp, weightTimeToParent, true /* useAccessConditional */))
|
||||||
{
|
return;
|
||||||
noRoadAccess = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = increment(start);
|
start = increment(start);
|
||||||
rp.SetPointId(start);
|
rp.SetPointId(start);
|
||||||
}
|
}
|
||||||
while (start != lastPointId);
|
while (start != lastPointId);
|
||||||
|
|
||||||
if (noRoadAccess)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bool forward = currentPointId < lastPointId;
|
bool forward = currentPointId < lastPointId;
|
||||||
Segment current = firstChild;
|
Segment current = firstChild;
|
||||||
Segment prev = parent;
|
Segment prev = parent;
|
||||||
@@ -396,7 +389,7 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
|
|
||||||
jointEdges.emplace_back(isOutgoing ? JointSegment(firstChild, prev) : JointSegment(prev, firstChild),
|
jointEdges.emplace_back(isOutgoing ? JointSegment(firstChild, prev) : JointSegment(prev, firstChild),
|
||||||
summaryWeight);
|
summaryWeight);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexGraph::GetNeighboringEdge(astar::VertexData<Segment, RouteWeight> const & fromVertexData, Segment const & to,
|
void IndexGraph::GetNeighboringEdge(astar::VertexData<Segment, RouteWeight> const & fromVertexData, Segment const & to,
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
#include "indexer/feature_meta.hpp"
|
#include "indexer/feature_meta.hpp"
|
||||||
|
|
||||||
#include "geometry/point2d.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "3party/skarupke/bytell_hash_map.hpp" // needed despite of IDE warning
|
#include "3party/skarupke/bytell_hash_map.hpp" // needed despite of IDE warning
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <execution>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -474,7 +475,8 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex));
|
CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex));
|
||||||
|
|
||||||
Weight const weight = it->second;
|
Weight const weight = it->second;
|
||||||
for (size_t i = 0; i < edges.size(); ++i)
|
auto const range = std::ranges::views::iota(0uz, edges.size());
|
||||||
|
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
|
||||||
{
|
{
|
||||||
// Saving weight of current edges for returning in the next iterations.
|
// Saving weight of current edges for returning in the next iterations.
|
||||||
auto & w = edges[i].GetWeight();
|
auto & w = edges[i].GetWeight();
|
||||||
@@ -490,7 +492,7 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
// |parentWeights[]|. So the weight of an ith edge is a cached "weight of parent JointSegment" +
|
// |parentWeights[]|. So the weight of an ith edge is a cached "weight of parent JointSegment" +
|
||||||
// "parentWeight[i]".
|
// "parentWeight[i]".
|
||||||
w = weight + parentWeights[i];
|
w = weight + parentWeights[i];
|
||||||
}
|
});
|
||||||
|
|
||||||
// Delete useless weight of parent JointSegment.
|
// Delete useless weight of parent JointSegment.
|
||||||
m_savedWeight.erase(vertex);
|
m_savedWeight.erase(vertex);
|
||||||
@@ -498,8 +500,9 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This needs for correct weights calculation of FakeJointSegments during forward A* search.
|
// This needs for correct weights calculation of FakeJointSegments during forward A* search.
|
||||||
for (size_t i = firstFakeId; i < edges.size(); ++i)
|
auto const range = std::ranges::views::iota(firstFakeId, edges.size());
|
||||||
edges[i].GetWeight() += parentWeights[i];
|
std::for_each(std::execution::par_unseq, range.begin(), range.end(),
|
||||||
|
[&edges, &parentWeights](auto const i) { edges[i].GetWeight() += parentWeights[i]; });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const vertexMwmId = vertex.GetMwmId();
|
auto const vertexMwmId = vertex.GetMwmId();
|
||||||
@@ -510,12 +513,12 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
|
|||||||
/// a weight of v1->v2 transition moving backward (v2 ingoing). This is impossible in current (m_savedWeight)
|
/// a weight of v1->v2 transition moving backward (v2 ingoing). This is impossible in current (m_savedWeight)
|
||||||
/// logic, so I moved Cross-MWM penalty into separate block here after _all_ weights calculations.
|
/// logic, so I moved Cross-MWM penalty into separate block here after _all_ weights calculations.
|
||||||
|
|
||||||
for (auto & e : edges)
|
std::for_each(std::execution::par_unseq, edges.begin(), edges.end(), [&, this](auto & e)
|
||||||
{
|
{
|
||||||
auto const targetMwmId = e.GetTarget().GetMwmId();
|
auto const targetMwmId = e.GetTarget().GetMwmId();
|
||||||
if (targetMwmId != kFakeNumMwmId && vertexMwmId != targetMwmId)
|
if (targetMwmId != kFakeNumMwmId && vertexMwmId != targetMwmId)
|
||||||
e.GetWeight() += m_graph.GetCrossBorderPenalty(vertexMwmId, targetMwmId);
|
e.GetWeight() += m_graph.GetCrossBorderPenalty(vertexMwmId, targetMwmId);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -363,32 +363,6 @@ void GetFullRoadName(RouteSegment::RoadNameInfo & road, std::string & name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double RoutingSession::GetDistanceToNextTurn() const
|
|
||||||
{
|
|
||||||
if (!m_route->IsValid())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
double distanceToTurnMeters = 0.;
|
|
||||||
turns::TurnItem turn;
|
|
||||||
m_route->GetNearestTurn(distanceToTurnMeters, turn);
|
|
||||||
return distanceToTurnMeters;
|
|
||||||
}
|
|
||||||
|
|
||||||
double RoutingSession::GetCurrentSpeedLimit() const
|
|
||||||
{
|
|
||||||
if (!m_route->IsValid())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
SpeedInUnits speedLimit;
|
|
||||||
m_route->GetCurrentSpeedLimit(speedLimit);
|
|
||||||
if (speedLimit.IsNumeric())
|
|
||||||
return measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
|
|
||||||
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
||||||
{
|
{
|
||||||
CHECK_THREAD_CHECKER(m_threadChecker, ());
|
CHECK_THREAD_CHECKER(m_threadChecker, ());
|
||||||
@@ -418,7 +392,14 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
|||||||
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
|
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
|
||||||
info.m_turn = turn.m_turn;
|
info.m_turn = turn.m_turn;
|
||||||
|
|
||||||
info.m_speedLimitMps = GetCurrentSpeedLimit();
|
SpeedInUnits speedLimit;
|
||||||
|
m_route->GetCurrentSpeedLimit(speedLimit);
|
||||||
|
if (speedLimit.IsNumeric())
|
||||||
|
info.m_speedLimitMps = measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
|
||||||
|
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
|
||||||
|
info.m_speedLimitMps = 0;
|
||||||
|
else
|
||||||
|
info.m_speedLimitMps = -1.0;
|
||||||
|
|
||||||
// The turn after the next one.
|
// The turn after the next one.
|
||||||
if (m_routingSettings.m_showTurnAfterNext)
|
if (m_routingSettings.m_showTurnAfterNext)
|
||||||
|
|||||||
@@ -100,8 +100,6 @@ public:
|
|||||||
|
|
||||||
SessionState OnLocationPositionChanged(location::GpsInfo const & info);
|
SessionState OnLocationPositionChanged(location::GpsInfo const & info);
|
||||||
void GetRouteFollowingInfo(FollowingInfo & info) const;
|
void GetRouteFollowingInfo(FollowingInfo & info) const;
|
||||||
double GetDistanceToNextTurn() const;
|
|
||||||
double GetCurrentSpeedLimit() const;
|
|
||||||
|
|
||||||
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
|
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
|
||||||
void MatchLocationToRoadGraph(location::GpsInfo & location);
|
void MatchLocationToRoadGraph(location::GpsInfo & location);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ char const * g_strings[] = {
|
|||||||
// ./clusterize-tag-values.lisp house-number path-to-taginfo-db.db > numbers.txt
|
// ./clusterize-tag-values.lisp house-number path-to-taginfo-db.db > numbers.txt
|
||||||
// tail -n +2 numbers.txt | head -78 | sed 's/^.*) \(.*\) \[.*$/"\1"/g;s/[ -/]//g;s/$/,/' |
|
// tail -n +2 numbers.txt | head -78 | sed 's/^.*) \(.*\) \[.*$/"\1"/g;s/[ -/]//g;s/$/,/' |
|
||||||
// sort | uniq
|
// sort | uniq
|
||||||
array<string_view, 48> constexpr g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
|
vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
|
||||||
"N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN",
|
"N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN",
|
||||||
"NLNL", "NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS",
|
"NLNL", "NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS",
|
||||||
"S", "SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS",
|
"S", "SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS",
|
||||||
@@ -85,14 +85,13 @@ array<string_view, 48> constexpr g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL"
|
|||||||
"NNBNL"};
|
"NNBNL"};
|
||||||
|
|
||||||
// List of patterns which look like house numbers more than other patterns. Constructed by hand.
|
// List of patterns which look like house numbers more than other patterns. Constructed by hand.
|
||||||
array<string_view, 4> constexpr g_patternsStrict = {"N", "NBN", "NBL", "NL"};
|
vector<string> const g_patternsStrict = {"N", "NBN", "NBL", "NL"};
|
||||||
|
|
||||||
// List of common synonyms for building parts. Constructed by hand.
|
// List of common synonyms for building parts. Constructed by hand.
|
||||||
char const * g_buildingPartSynonyms[] = {"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус",
|
char const * g_buildingPartSynonyms[] = {"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус",
|
||||||
"корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"};
|
"корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"};
|
||||||
|
|
||||||
// List of common stop words for buildings. Constructed by hand.
|
// List of common stop words for buildings. Constructed by hand.
|
||||||
// TODO: add more stop words?
|
|
||||||
UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house"), MakeUniString("д")};
|
UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house"), MakeUniString("д")};
|
||||||
|
|
||||||
bool IsStopWord(UniString const & s, bool isPrefix)
|
bool IsStopWord(UniString const & s, bool isPrefix)
|
||||||
@@ -168,8 +167,7 @@ class HouseNumberClassifier
|
|||||||
public:
|
public:
|
||||||
using Patterns = StringSet<Token::Type, 4>;
|
using Patterns = StringSet<Token::Type, 4>;
|
||||||
|
|
||||||
template <size_t size>
|
HouseNumberClassifier(vector<string> const & patterns = g_patterns)
|
||||||
HouseNumberClassifier(array<string_view, size> const & patterns)
|
|
||||||
{
|
{
|
||||||
for (auto const & p : patterns)
|
for (auto const & p : patterns)
|
||||||
m_patterns.Add(make_transform_iterator(p.begin(), &CharToType), make_transform_iterator(p.end(), &CharToType));
|
m_patterns.Add(make_transform_iterator(p.begin(), &CharToType), make_transform_iterator(p.end(), &CharToType));
|
||||||
@@ -592,7 +590,7 @@ bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & qu
|
|||||||
|
|
||||||
bool LooksLikeHouseNumber(UniString const & s, bool isPrefix)
|
bool LooksLikeHouseNumber(UniString const & s, bool isPrefix)
|
||||||
{
|
{
|
||||||
static HouseNumberClassifier const classifier(g_patterns);
|
static HouseNumberClassifier const classifier;
|
||||||
return classifier.LooksGood(s, isPrefix);
|
return classifier.LooksGood(s, isPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -298,7 +298,8 @@ void LocalityScorer::GetDocVecs(uint32_t localityId, vector<DocVec> & dvs) const
|
|||||||
DocVec::Builder builder;
|
DocVec::Builder builder;
|
||||||
ForEachNormalizedToken(name, [&](strings::UniString const & token)
|
ForEachNormalizedToken(name, [&](strings::UniString const & token)
|
||||||
{
|
{
|
||||||
builder.Add(token);
|
if (!IsStopWord(token))
|
||||||
|
builder.Add(token);
|
||||||
});
|
});
|
||||||
dvs.emplace_back(std::move(builder));
|
dvs.emplace_back(std::move(builder));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,21 @@ m2::RectD GetRectAroundPosition(m2::PointD const & position)
|
|||||||
return mercator::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM);
|
return mercator::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Removes all full-token stop words from |tokens|.
|
||||||
|
// Does nothing if all tokens are non-prefix stop words.
|
||||||
|
void RemoveStopWordsIfNeeded(QueryTokens & tokens, strings::UniString & prefix)
|
||||||
|
{
|
||||||
|
size_t numStopWords = 0;
|
||||||
|
for (auto const & token : tokens)
|
||||||
|
if (IsStopWord(token))
|
||||||
|
++numStopWords;
|
||||||
|
|
||||||
|
if (numStopWords == tokens.size() && prefix.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
tokens.erase_if(&IsStopWord);
|
||||||
|
}
|
||||||
|
|
||||||
void TrimLeadingSpaces(string & s)
|
void TrimLeadingSpaces(string & s)
|
||||||
{
|
{
|
||||||
while (!s.empty() && strings::IsASCIISpace(s.front()))
|
while (!s.empty() && strings::IsASCIISpace(s.front()))
|
||||||
@@ -262,6 +277,9 @@ void Processor::SetQuery(string const & query, bool categorialRequest /* = false
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove stopwords *after* FillCategories call (it makes exact tokens match).
|
||||||
|
RemoveStopWordsIfNeeded(m_query.m_tokens, m_query.m_prefix);
|
||||||
|
|
||||||
if (!m_isCategorialRequest)
|
if (!m_isCategorialRequest)
|
||||||
{
|
{
|
||||||
// Assign tokens and prefix to scorer.
|
// Assign tokens and prefix to scorer.
|
||||||
|
|||||||
@@ -1482,7 +1482,13 @@ unordered_map<string, vector<string>> const kSynonyms = {
|
|||||||
// QueryParams::Token ------------------------------------------------------------------------------
|
// QueryParams::Token ------------------------------------------------------------------------------
|
||||||
void QueryParams::Token::AddSynonym(string const & s)
|
void QueryParams::Token::AddSynonym(string const & s)
|
||||||
{
|
{
|
||||||
m_synonyms.push_back(strings::MakeUniString(s));
|
AddSynonym(strings::MakeUniString(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryParams::Token::AddSynonym(String const & s)
|
||||||
|
{
|
||||||
|
if (!IsStopWord(s))
|
||||||
|
m_synonyms.push_back(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
string DebugPrint(QueryParams::Token const & token)
|
string DebugPrint(QueryParams::Token const & token)
|
||||||
@@ -1504,12 +1510,10 @@ void QueryParams::ClearStreetIndices()
|
|||||||
AdditionalCommonTokens()
|
AdditionalCommonTokens()
|
||||||
{
|
{
|
||||||
char const * arr[] = {
|
char const * arr[] = {
|
||||||
"a", "and", "s", "the", // English
|
"the", // English
|
||||||
"am", "an", "auf", "der", "im", "und", "zum", // German
|
"der", "zum", "und", "auf", // German
|
||||||
"as", "d", "da", "das", "de", "del", "di", "do",
|
"del", "les", // Spanish
|
||||||
"dos", "du", "e", "el", "et", "la", "las", "le",
|
"в", "на" // Cyrillic
|
||||||
"les", "los", "o", "os", "y", // French, Italian, Portuguese, Spanish
|
|
||||||
"в", "и", "на", "я" // Cyrillic
|
|
||||||
};
|
};
|
||||||
for (char const * s : arr)
|
for (char const * s : arr)
|
||||||
m_strings.insert(NormalizeAndSimplifyString(s));
|
m_strings.insert(NormalizeAndSimplifyString(s));
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public:
|
|||||||
Token(String const & original) : m_original(original) {}
|
Token(String const & original) : m_original(original) {}
|
||||||
|
|
||||||
void AddSynonym(std::string const & s);
|
void AddSynonym(std::string const & s);
|
||||||
|
void AddSynonym(String const & s);
|
||||||
|
|
||||||
template <typename Fn>
|
template <typename Fn>
|
||||||
void ForEachSynonym(Fn && fn) const
|
void ForEachSynonym(Fn && fn) const
|
||||||
|
|||||||
@@ -94,9 +94,42 @@ ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token, strings::UniStr
|
|||||||
}
|
}
|
||||||
} // namespace impl
|
} // namespace impl
|
||||||
|
|
||||||
|
bool IsStopWord(UniString const & s)
|
||||||
|
{
|
||||||
|
/// @todo Get all common used stop words and take out this array into search_string_utils.cpp module for example.
|
||||||
|
/// Should skip this tokens when building search index?
|
||||||
|
class StopWordsChecker
|
||||||
|
{
|
||||||
|
set<UniString> m_set;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StopWordsChecker()
|
||||||
|
{
|
||||||
|
// Don't want to put _full_ stopwords list, not to break current ranking.
|
||||||
|
// Only 2-letters and the most common.
|
||||||
|
char const * arr[] = {
|
||||||
|
"a", "s", "the", // English
|
||||||
|
"am", "im", "an", // German
|
||||||
|
"d", "da", "de", "di", "du", "la", "le", // French, Spanish, Italian
|
||||||
|
"и", "я" // Cyrillic
|
||||||
|
};
|
||||||
|
for (char const * s : arr)
|
||||||
|
m_set.insert(MakeUniString(s));
|
||||||
|
}
|
||||||
|
bool Has(UniString const & s) const { return m_set.count(s) > 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
static StopWordsChecker const swChecker;
|
||||||
|
return swChecker.Has(s);
|
||||||
|
}
|
||||||
|
|
||||||
TokensVector::TokensVector(string_view name)
|
TokensVector::TokensVector(string_view name)
|
||||||
{
|
{
|
||||||
m_tokens = NormalizeAndTokenizeString(std::move(name));
|
ForEachNormalizedToken(name, [this](strings::UniString && token)
|
||||||
|
{
|
||||||
|
if (!IsStopWord(token))
|
||||||
|
m_tokens.push_back(std::move(token));
|
||||||
|
});
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ struct NameScores
|
|||||||
std::string DebugPrint(NameScore const & score);
|
std::string DebugPrint(NameScore const & score);
|
||||||
std::string DebugPrint(NameScores const & scores);
|
std::string DebugPrint(NameScores const & scores);
|
||||||
|
|
||||||
|
// Returns true when |s| is a stop-word and may be removed from a query.
|
||||||
|
bool IsStopWord(strings::UniString const & s);
|
||||||
|
|
||||||
class TokensVector
|
class TokensVector
|
||||||
{
|
{
|
||||||
std::vector<strings::UniString> m_tokens;
|
std::vector<strings::UniString> m_tokens;
|
||||||
|
|||||||
@@ -44,7 +44,11 @@ public:
|
|||||||
m_scorer.SetPivotForTesting(pivot);
|
m_scorer.SetPivotForTesting(pivot);
|
||||||
|
|
||||||
vector<UniString> tokens;
|
vector<UniString> tokens;
|
||||||
tokens = NormalizeAndTokenizeString(query);
|
search::ForEachNormalizedToken(query, [&tokens](strings::UniString && token)
|
||||||
|
{
|
||||||
|
if (!IsStopWord(token))
|
||||||
|
tokens.push_back(std::move(token));
|
||||||
|
});
|
||||||
|
|
||||||
m_params.Init(query, tokens, lastTokenIsPrefix);
|
m_params.Init(query, tokens, lastTokenIsPrefix);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ def multithread_run_if_one_country(func):
|
|||||||
kwargs.update({"threads_count": settings.THREADS_COUNT})
|
kwargs.update({"threads_count": settings.THREADS_COUNT})
|
||||||
# Otherwise index stage of Taiwan_* mwms continues to run after all other mwms have finished:
|
# Otherwise index stage of Taiwan_* mwms continues to run after all other mwms have finished:
|
||||||
elif country == 'Taiwan_North':
|
elif country == 'Taiwan_North':
|
||||||
kwargs.update({"threads_count": 5})
|
kwargs.update({"threads_count": 3})
|
||||||
elif country == 'Taiwan_South':
|
elif country == 'Taiwan_South':
|
||||||
kwargs.update({"threads_count": 2})
|
kwargs.update({"threads_count": 2})
|
||||||
func(env, country, **kwargs)
|
func(env, country, **kwargs)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ MAIN_OUT_PATH: /mnt/4tbexternal/osm-maps
|
|||||||
# Path to the data/ folder in the repository:
|
# Path to the data/ folder in the repository:
|
||||||
USER_RESOURCE_PATH: ${Developer:OMIM_PATH}/data
|
USER_RESOURCE_PATH: ${Developer:OMIM_PATH}/data
|
||||||
# Features stage only parallelism level. Set to 0 for auto detection.
|
# Features stage only parallelism level. Set to 0 for auto detection.
|
||||||
THREADS_COUNT_FEATURES_STAGE: 0
|
THREADS_COUNT_FEATURES_STAGE: 64
|
||||||
# Do not change it. This is determined automatically.
|
# Do not change it. This is determined automatically.
|
||||||
NODE_STORAGE: mem
|
NODE_STORAGE: mem
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user