"use strict";
// ==UserScript==
// @name WME Road Shield Assistant
// @namespace https://greasyfork.org/en/users/286957-skidooguy
// @version 2025.06.19.001
// @description Adds shield information display to WME
// @author SkiDooGuy, jm6087, Karlsosha
// @match https://www.waze.com/editor*
// @match https://www.waze.com/*/editor*
// @match https://beta.waze.com/editor*
// @match https://beta.waze.com/*/editor*
// @exclude https://www.waze.com/user/editor*
// @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
// @require https://cdn.jsdelivr.net/npm/@turf/[email protected]/turf.min.js
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/proj4.min.js
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// @connect greasyfork.org
// @contributionURL https://github.com/WazeDev/Thank-The-Authors
// ==/UserScript==
/* global W */
/* global WazeWrap */
// import type { Node, Segment, SegmentAddress, Street, Turn, WmeSDK } from "wme-sdk-typings";
// import type { Point, LineString, Position, Feature } from "geojson";
// import * as turf from "@turf/turf";
// import _ from "underscore";
// import proj4 from "proj4";
// import WazeWrap from "https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js";
let sdk;
unsafeWindow.SDK_INITIALIZED.then(() => {
if (!unsafeWindow.getWmeSdk) {
throw new Error("SDK is not installed");
}
sdk = unsafeWindow.getWmeSdk({ scriptId: "wme-road-shield-assistant", scriptName: "WME Road Shield Assistant" });
console.log(`SDK v ${sdk.getSDKVersion()} on ${sdk.getWMEVersion()} initialized`);
sdk.Events.once({ eventName: "wme-ready" }).then(rsaInit);
});
function rsaInit() {
if (!WazeWrap.Ready) {
setTimeout(() => {
rsaInit();
}, 100);
return;
}
const GF_LINK = "https://greasyfork.org/en/scripts/425050-wme-road-shield-assisstant";
const FORUM_LINK = "https://www.waze.com/discuss/t/script-road-shield-assistant-rsa/227100";
const RSA_UPDATE_NOTES = `<b>NEW:</b><br>
- Converted to WME SDK<br>
- <b>Make Sure to Enable RSA Layers to See the Shields</b><br>
- Added Rules for Shield Checking Logic for Mexico<br>
- Updated Shield Highlight Rules for All States in US<br>
- Updated Some Highlight Rules for Canada<br><br>
<b>BUGFIXES:</b><br>
- Fix error with undefined point Radius for Circle Tag<br><br>
<b>KNOWN ISSUES:</b><br>
- Missing Exit Sign Shields on Node<br>
- Some of the highlighting may be incorrect showing issues when there are none<br><br>`;
let CountryID;
(function (CountryID) {
CountryID[CountryID["AFGANISTAN"] = 1] = "AFGANISTAN";
CountryID[CountryID["ALBANIA"] = 2] = "ALBANIA";
CountryID[CountryID["ALGERIA"] = 3] = "ALGERIA";
CountryID[CountryID["AMERICAN_SAMOA"] = 4] = "AMERICAN_SAMOA";
CountryID[CountryID["ANDORRA"] = 5] = "ANDORRA";
CountryID[CountryID["ANGOLA"] = 6] = "ANGOLA";
CountryID[CountryID["ANGUILLA"] = 7] = "ANGUILLA";
CountryID[CountryID["ANTARCTICA"] = 8] = "ANTARCTICA";
CountryID[CountryID["ANTIGUA_AND_BARBUDA"] = 9] = "ANTIGUA_AND_BARBUDA";
CountryID[CountryID["ARGENTINA"] = 10] = "ARGENTINA";
CountryID[CountryID["ARMENIA"] = 11] = "ARMENIA";
CountryID[CountryID["ARUBA"] = 12] = "ARUBA";
CountryID[CountryID["AUSTRALIA"] = 13] = "AUSTRALIA";
CountryID[CountryID["AUSTRIA"] = 14] = "AUSTRIA";
CountryID[CountryID["AZERBAIJAN"] = 15] = "AZERBAIJAN";
CountryID[CountryID["BAHAMAS"] = 16] = "BAHAMAS";
CountryID[CountryID["BAHRAIN"] = 17] = "BAHRAIN";
CountryID[CountryID["BAKER_ISLAND"] = 18] = "BAKER_ISLAND";
CountryID[CountryID["BANGLADESH"] = 19] = "BANGLADESH";
CountryID[CountryID["BARBADOS"] = 20] = "BARBADOS";
CountryID[CountryID["BELGUIM"] = 21] = "BELGUIM";
CountryID[CountryID["BELIZE"] = 22] = "BELIZE";
CountryID[CountryID["BENIN"] = 23] = "BENIN";
CountryID[CountryID["BERMUDA"] = 24] = "BERMUDA";
CountryID[CountryID["BHUTAN"] = 25] = "BHUTAN";
CountryID[CountryID["BOLIVIA"] = 26] = "BOLIVIA";
CountryID[CountryID["BOSNIA_AND_HERZEGOWINA"] = 27] = "BOSNIA_AND_HERZEGOWINA";
CountryID[CountryID["BOTSWANA"] = 28] = "BOTSWANA";
CountryID[CountryID["BOUVET_ISLAND"] = 29] = "BOUVET_ISLAND";
CountryID[CountryID["BRAZIL"] = 30] = "BRAZIL";
CountryID[CountryID["BRITISH_INDIAN_OCEAN_TERRITORY"] = 31] = "BRITISH_INDIAN_OCEAN_TERRITORY";
CountryID[CountryID["BRITISH_VIRGIN_ISLANDS"] = 32] = "BRITISH_VIRGIN_ISLANDS";
CountryID[CountryID["BRUNEI"] = 33] = "BRUNEI";
CountryID[CountryID["BULGARIA"] = 34] = "BULGARIA";
CountryID[CountryID["BURKINA_FASO"] = 35] = "BURKINA_FASO";
CountryID[CountryID["BURUNDI"] = 36] = "BURUNDI";
CountryID[CountryID["BELARUS"] = 37] = "BELARUS";
CountryID[CountryID["CAMBODIA"] = 38] = "CAMBODIA";
CountryID[CountryID["CAMEROON"] = 39] = "CAMEROON";
CountryID[CountryID["CANADA"] = 40] = "CANADA";
CountryID[CountryID["CAPE_VERDE"] = 41] = "CAPE_VERDE";
CountryID[CountryID["CAYMAN_ISLANDS"] = 42] = "CAYMAN_ISLANDS";
CountryID[CountryID["CENTRAL_AFRICAN_REPUBLIC"] = 43] = "CENTRAL_AFRICAN_REPUBLIC";
CountryID[CountryID["CHAD"] = 44] = "CHAD";
CountryID[CountryID["CHILE"] = 45] = "CHILE";
CountryID[CountryID["CHINA"] = 46] = "CHINA";
CountryID[CountryID["CHRISTMAS_ISLAND"] = 47] = "CHRISTMAS_ISLAND";
CountryID[CountryID["COCOS_ISLANDS"] = 48] = "COCOS_ISLANDS";
CountryID[CountryID["KEELING_ISLANDS"] = 48] = "KEELING_ISLANDS";
CountryID[CountryID["COLOMBIA"] = 49] = "COLOMBIA";
CountryID[CountryID["COMOROS"] = 50] = "COMOROS";
CountryID[CountryID["CONGO"] = 51] = "CONGO";
CountryID[CountryID["COOK_ISLANDS"] = 52] = "COOK_ISLANDS";
CountryID[CountryID["COSTA_RICA"] = 53] = "COSTA_RICA";
CountryID[CountryID["CROATIA"] = 54] = "CROATIA";
CountryID[CountryID["CUBA"] = 55] = "CUBA";
CountryID[CountryID["CYPRUS"] = 56] = "CYPRUS";
CountryID[CountryID["CZECH_REPUBLIC"] = 57] = "CZECH_REPUBLIC";
CountryID[CountryID["DENMARK"] = 58] = "DENMARK";
CountryID[CountryID["DJIBOUTI"] = 59] = "DJIBOUTI";
CountryID[CountryID["DOMINICA"] = 60] = "DOMINICA";
CountryID[CountryID["DOMINICAN_REPUBLIC"] = 61] = "DOMINICAN_REPUBLIC";
CountryID[CountryID["ECUADOR"] = 62] = "ECUADOR";
CountryID[CountryID["EGYPT"] = 63] = "EGYPT";
CountryID[CountryID["EL_SALVADOR"] = 64] = "EL_SALVADOR";
CountryID[CountryID["EQUATORIAL_GUINEA"] = 65] = "EQUATORIAL_GUINEA";
CountryID[CountryID["ERITREA"] = 66] = "ERITREA";
CountryID[CountryID["ESTONIA"] = 67] = "ESTONIA";
CountryID[CountryID["ETHIOPIA"] = 68] = "ETHIOPIA";
CountryID[CountryID["FALKLAND_ISLANDS"] = 69] = "FALKLAND_ISLANDS";
CountryID[CountryID["ISLAS_MALVINAS"] = 69] = "ISLAS_MALVINAS";
CountryID[CountryID["FAROE_ISLANDS"] = 70] = "FAROE_ISLANDS";
CountryID[CountryID["MICRONEISA"] = 71] = "MICRONEISA";
CountryID[CountryID["FIJI"] = 72] = "FIJI";
CountryID[CountryID["FRNACE"] = 73] = "FRNACE";
CountryID[CountryID["FRENCH_GUIANA"] = 74] = "FRENCH_GUIANA";
CountryID[CountryID["FRENCH_POLYNESIA"] = 75] = "FRENCH_POLYNESIA";
CountryID[CountryID["FRENCH_SOUTHERN_TERRITORIES"] = 76] = "FRENCH_SOUTHERN_TERRITORIES";
CountryID[CountryID["GABON"] = 77] = "GABON";
CountryID[CountryID["GAMBIA"] = 78] = "GAMBIA";
CountryID[CountryID["GEORGIA"] = 80] = "GEORGIA";
CountryID[CountryID["GERMANY"] = 81] = "GERMANY";
CountryID[CountryID["GHANA"] = 82] = "GHANA";
CountryID[CountryID["GIBRALTAR"] = 83] = "GIBRALTAR";
CountryID[CountryID["GLORIOSO_ISLANDS"] = 84] = "GLORIOSO_ISLANDS";
CountryID[CountryID["GREECE"] = 85] = "GREECE";
CountryID[CountryID["GREENLAND"] = 86] = "GREENLAND";
CountryID[CountryID["GRENADA"] = 87] = "GRENADA";
CountryID[CountryID["GUADELOUPE"] = 88] = "GUADELOUPE";
CountryID[CountryID["GUAM"] = 89] = "GUAM";
CountryID[CountryID["GUATEMALA"] = 90] = "GUATEMALA";
CountryID[CountryID["GUERNSEY"] = 91] = "GUERNSEY";
CountryID[CountryID["GUINEA"] = 92] = "GUINEA";
CountryID[CountryID["GUINEA_BISSAU"] = 93] = "GUINEA_BISSAU";
CountryID[CountryID["GUYANA"] = 94] = "GUYANA";
CountryID[CountryID["HAITI"] = 95] = "HAITI";
CountryID[CountryID["HEARD_AND_MCDONAL_ISLANDS"] = 96] = "HEARD_AND_MCDONAL_ISLANDS";
CountryID[CountryID["HONDURAS"] = 97] = "HONDURAS";
CountryID[CountryID["HOWLAND_ISLAND"] = 98] = "HOWLAND_ISLAND";
CountryID[CountryID["HUNGARY"] = 99] = "HUNGARY";
CountryID[CountryID["ICELAND"] = 100] = "ICELAND";
CountryID[CountryID["INDIA"] = 101] = "INDIA";
CountryID[CountryID["INDONESIA"] = 102] = "INDONESIA";
CountryID[CountryID["IRAN"] = 103] = "IRAN";
CountryID[CountryID["IRAQ"] = 104] = "IRAQ";
CountryID[CountryID["IRELAND"] = 105] = "IRELAND";
CountryID[CountryID["ITALY"] = 107] = "ITALY";
CountryID[CountryID["COTE_DIVORE"] = 108] = "COTE_DIVORE";
CountryID[CountryID["JAMAICA"] = 109] = "JAMAICA";
CountryID[CountryID["JAN_MAYEN"] = 110] = "JAN_MAYEN";
CountryID[CountryID["JAPAN"] = 111] = "JAPAN";
CountryID[CountryID["JARVIS_ISLAND"] = 112] = "JARVIS_ISLAND";
CountryID[CountryID["JERSEY"] = 113] = "JERSEY";
CountryID[CountryID["JOHNSTON_ATOLL"] = 114] = "JOHNSTON_ATOLL";
CountryID[CountryID["JORDAN"] = 115] = "JORDAN";
CountryID[CountryID["JUAN_DE_NOVA_ISLAND"] = 116] = "JUAN_DE_NOVA_ISLAND";
CountryID[CountryID["KAZAKHSTAN"] = 117] = "KAZAKHSTAN";
CountryID[CountryID["KENYA"] = 118] = "KENYA";
CountryID[CountryID["KIRIBATI"] = 119] = "KIRIBATI";
CountryID[CountryID["KUWAIT"] = 120] = "KUWAIT";
CountryID[CountryID["KYRGYZSTAN"] = 121] = "KYRGYZSTAN";
CountryID[CountryID["LAOS"] = 122] = "LAOS";
CountryID[CountryID["LATVIA"] = 123] = "LATVIA";
CountryID[CountryID["LEBANON"] = 124] = "LEBANON";
CountryID[CountryID["LESOTHO"] = 125] = "LESOTHO";
CountryID[CountryID["LIBERIA"] = 126] = "LIBERIA";
CountryID[CountryID["LIBYA"] = 127] = "LIBYA";
CountryID[CountryID["LIECHTENSTEIN"] = 128] = "LIECHTENSTEIN";
CountryID[CountryID["LITHUANIA"] = 129] = "LITHUANIA";
CountryID[CountryID["LUXEMBOURG"] = 130] = "LUXEMBOURG";
CountryID[CountryID["MACAU"] = 131] = "MACAU";
CountryID[CountryID["MACEDONIA"] = 132] = "MACEDONIA";
CountryID[CountryID["MADAGASCAR"] = 133] = "MADAGASCAR";
CountryID[CountryID["MALAWI"] = 134] = "MALAWI";
CountryID[CountryID["MALAYSIA"] = 135] = "MALAYSIA";
CountryID[CountryID["MALDIVES"] = 136] = "MALDIVES";
CountryID[CountryID["MALI"] = 137] = "MALI";
CountryID[CountryID["MALTA"] = 138] = "MALTA";
CountryID[CountryID["ISLE_OF_MAN"] = 139] = "ISLE_OF_MAN";
CountryID[CountryID["MARSHALL_ISLANDS"] = 140] = "MARSHALL_ISLANDS";
CountryID[CountryID["MARTINIQUE"] = 141] = "MARTINIQUE";
CountryID[CountryID["MAURITANIA"] = 142] = "MAURITANIA";
CountryID[CountryID["MAURITIUS"] = 143] = "MAURITIUS";
CountryID[CountryID["MAYOTTE"] = 144] = "MAYOTTE";
CountryID[CountryID["MEXICO"] = 145] = "MEXICO";
CountryID[CountryID["MIDWAY_ISLAND"] = 146] = "MIDWAY_ISLAND";
CountryID[CountryID["MOLDOVA"] = 147] = "MOLDOVA";
CountryID[CountryID["MONACO"] = 148] = "MONACO";
CountryID[CountryID["MONGOLIA"] = 149] = "MONGOLIA";
CountryID[CountryID["MONTENEGRO"] = 150] = "MONTENEGRO";
CountryID[CountryID["MONTSERRAT"] = 151] = "MONTSERRAT";
CountryID[CountryID["MOROCCO"] = 152] = "MOROCCO";
CountryID[CountryID["MOZAMBIQUE"] = 153] = "MOZAMBIQUE";
CountryID[CountryID["MYANMAR"] = 154] = "MYANMAR";
CountryID[CountryID["NAMIBIA"] = 155] = "NAMIBIA";
CountryID[CountryID["NAURU"] = 156] = "NAURU";
CountryID[CountryID["NEPAL"] = 157] = "NEPAL";
CountryID[CountryID["NETHERLANDS"] = 158] = "NETHERLANDS";
CountryID[CountryID["NEW_CALEDONIA"] = 159] = "NEW_CALEDONIA";
CountryID[CountryID["NEW_ZEALAND"] = 161] = "NEW_ZEALAND";
CountryID[CountryID["NICARAGUA"] = 162] = "NICARAGUA";
CountryID[CountryID["NIGER"] = 163] = "NIGER";
CountryID[CountryID["NIGERIA"] = 164] = "NIGERIA";
CountryID[CountryID["NIUE"] = 165] = "NIUE";
CountryID[CountryID["NORFOLK_ISLAND"] = 166] = "NORFOLK_ISLAND";
CountryID[CountryID["NORTHERN_MARIANA_ISLANDS"] = 167] = "NORTHERN_MARIANA_ISLANDS";
CountryID[CountryID["NORTH_KOREA"] = 168] = "NORTH_KOREA";
CountryID[CountryID["KOREA_NORTH"] = 168] = "KOREA_NORTH";
CountryID[CountryID["NORWAY"] = 169] = "NORWAY";
CountryID[CountryID["OMAN"] = 170] = "OMAN";
CountryID[CountryID["PASIFIC_ISLANDS"] = 171] = "PASIFIC_ISLANDS";
CountryID[CountryID["PALAU"] = 171] = "PALAU";
CountryID[CountryID["PAKISTAN"] = 172] = "PAKISTAN";
CountryID[CountryID["PANAMA"] = 173] = "PANAMA";
CountryID[CountryID["PAPUA_NEW_GUINEA"] = 174] = "PAPUA_NEW_GUINEA";
CountryID[CountryID["PARACEL_ISLANDS"] = 175] = "PARACEL_ISLANDS";
CountryID[CountryID["PARAGUAY"] = 176] = "PARAGUAY";
CountryID[CountryID["PERU"] = 177] = "PERU";
CountryID[CountryID["PHILIPPINES"] = 178] = "PHILIPPINES";
CountryID[CountryID["PITCAIRN_ISLANDS"] = 179] = "PITCAIRN_ISLANDS";
CountryID[CountryID["POLAND"] = 180] = "POLAND";
CountryID[CountryID["PORTUGAL"] = 181] = "PORTUGAL";
CountryID[CountryID["PUERTO_RICO"] = 182] = "PUERTO_RICO";
CountryID[CountryID["QATAR"] = 183] = "QATAR";
CountryID[CountryID["REUNION"] = 184] = "REUNION";
CountryID[CountryID["ROMANIA"] = 185] = "ROMANIA";
CountryID[CountryID["RUSSIA"] = 186] = "RUSSIA";
CountryID[CountryID["RWANDA"] = 187] = "RWANDA";
CountryID[CountryID["SAN_MARINO"] = 188] = "SAN_MARINO";
CountryID[CountryID["SAO_TOME_AND_PRINCIPE"] = 189] = "SAO_TOME_AND_PRINCIPE";
CountryID[CountryID["SAUDI_ARABIA"] = 190] = "SAUDI_ARABIA";
CountryID[CountryID["SENEGAL"] = 191] = "SENEGAL";
CountryID[CountryID["SERBIA"] = 192] = "SERBIA";
CountryID[CountryID["SEYCHELLES"] = 193] = "SEYCHELLES";
CountryID[CountryID["SIERRA_LEONE"] = 194] = "SIERRA_LEONE";
CountryID[CountryID["SINGAPORE"] = 195] = "SINGAPORE";
CountryID[CountryID["SLOVAKIA"] = 196] = "SLOVAKIA";
CountryID[CountryID["SLOVENIA"] = 197] = "SLOVENIA";
CountryID[CountryID["SOLOMON_ISLANDS"] = 198] = "SOLOMON_ISLANDS";
CountryID[CountryID["SOMALIA"] = 199] = "SOMALIA";
CountryID[CountryID["SOUTH_AFRICA"] = 200] = "SOUTH_AFRICA";
CountryID[CountryID["SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS"] = 201] = "SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS";
CountryID[CountryID["SOUTH_GEORGIA"] = 201] = "SOUTH_GEORGIA";
CountryID[CountryID["SOUTH_SANDWICH_ISLANDS"] = 201] = "SOUTH_SANDWICH_ISLANDS";
CountryID[CountryID["SOUTH_KOREA"] = 202] = "SOUTH_KOREA";
CountryID[CountryID["KOREA_SOUTH"] = 202] = "KOREA_SOUTH";
CountryID[CountryID["SPAIN"] = 203] = "SPAIN";
CountryID[CountryID["SPRATLY_ISLANDS"] = 204] = "SPRATLY_ISLANDS";
CountryID[CountryID["SRI_LANKA"] = 205] = "SRI_LANKA";
CountryID[CountryID["ST_MARTIN"] = 254] = "ST_MARTIN";
CountryID[CountryID["SAINT_MARTIN"] = 254] = "SAINT_MARTIN";
CountryID[CountryID["ST_HELENA"] = 206] = "ST_HELENA";
CountryID[CountryID["ST_KITTS_AND_NEVIS"] = 207] = "ST_KITTS_AND_NEVIS";
CountryID[CountryID["ST_LUCIA"] = 208] = "ST_LUCIA";
CountryID[CountryID["ST_PIERRE_AND_MIQUELON"] = 209] = "ST_PIERRE_AND_MIQUELON";
CountryID[CountryID["ST_VINCENT_AND_THE_GRENADINES"] = 210] = "ST_VINCENT_AND_THE_GRENADINES";
CountryID[CountryID["SUDAN"] = 211] = "SUDAN";
CountryID[CountryID["SURINAME"] = 212] = "SURINAME";
CountryID[CountryID["SVALBARD"] = 213] = "SVALBARD";
CountryID[CountryID["SWAZILAND"] = 214] = "SWAZILAND";
CountryID[CountryID["SWEDEN"] = 215] = "SWEDEN";
CountryID[CountryID["SWITZERLAND"] = 216] = "SWITZERLAND";
CountryID[CountryID["SYRIA"] = 217] = "SYRIA";
CountryID[CountryID["TAIWAN"] = 218] = "TAIWAN";
CountryID[CountryID["TAJIKISTAN"] = 219] = "TAJIKISTAN";
CountryID[CountryID["TANZANIA"] = 220] = "TANZANIA";
CountryID[CountryID["THAILAND"] = 221] = "THAILAND";
CountryID[CountryID["TOGO"] = 222] = "TOGO";
CountryID[CountryID["TOKELAU"] = 223] = "TOKELAU";
CountryID[CountryID["TONGA"] = 224] = "TONGA";
CountryID[CountryID["TRINIDAD_AND_TOBAGO"] = 225] = "TRINIDAD_AND_TOBAGO";
CountryID[CountryID["TUNISIA"] = 226] = "TUNISIA";
CountryID[CountryID["TURKEY"] = 227] = "TURKEY";
CountryID[CountryID["TURKMENISTAN"] = 228] = "TURKMENISTAN";
CountryID[CountryID["TURKS_AND_CAICOS_ISLANDS"] = 229] = "TURKS_AND_CAICOS_ISLANDS";
CountryID[CountryID["TUVALU"] = 230] = "TUVALU";
CountryID[CountryID["UGANDA"] = 231] = "UGANDA";
CountryID[CountryID["UKRAINE"] = 232] = "UKRAINE";
CountryID[CountryID["UNITED_ARAB_EMIRATES"] = 233] = "UNITED_ARAB_EMIRATES";
CountryID[CountryID["UNITED_KINGDOM"] = 234] = "UNITED_KINGDOM";
CountryID[CountryID["UK"] = 234] = "UK";
CountryID[CountryID["GREAT_BRITAIN"] = 234] = "GREAT_BRITAIN";
CountryID[CountryID["UNITED_STATES"] = 235] = "UNITED_STATES";
CountryID[CountryID["USA"] = 235] = "USA";
CountryID[CountryID["UNITED_STATES_OF_AMERICA"] = 235] = "UNITED_STATES_OF_AMERICA";
CountryID[CountryID["URUGUAY"] = 236] = "URUGUAY";
CountryID[CountryID["UZBEKISTAN"] = 237] = "UZBEKISTAN";
CountryID[CountryID["VANUATU"] = 238] = "VANUATU";
CountryID[CountryID["VENEZUELA"] = 239] = "VENEZUELA";
CountryID[CountryID["VIETNAM"] = 240] = "VIETNAM";
CountryID[CountryID["US_VIRGIN_ISLANDS"] = 241] = "US_VIRGIN_ISLANDS";
CountryID[CountryID["WAKE_ISLAND"] = 242] = "WAKE_ISLAND";
CountryID[CountryID["WALLIS_AND_FUTUNA"] = 243] = "WALLIS_AND_FUTUNA";
CountryID[CountryID["WESTERN_SAHARA"] = 245] = "WESTERN_SAHARA";
CountryID[CountryID["SAMOA"] = 246] = "SAMOA";
CountryID[CountryID["YEMEN"] = 247] = "YEMEN";
CountryID[CountryID["DEMOCRATIC_REPUBLIC_OF_THE_CONGO"] = 248] = "DEMOCRATIC_REPUBLIC_OF_THE_CONGO";
CountryID[CountryID["DRC"] = 248] = "DRC";
CountryID[CountryID["ZAMBIA"] = 249] = "ZAMBIA";
CountryID[CountryID["ZIMBABWE"] = 250] = "ZIMBABWE";
CountryID[CountryID["FINLAND"] = 251] = "FINLAND";
CountryID[CountryID["CURACAO"] = 252] = "CURACAO";
CountryID[CountryID["BONAIRE_SINT_EUSTATIUS_SABA_ISLAND"] = 253] = "BONAIRE_SINT_EUSTATIUS_SABA_ISLAND";
CountryID[CountryID["BONAIRE"] = 253] = "BONAIRE";
CountryID[CountryID["SINT_EUSTATIUS"] = 253] = "SINT_EUSTATIUS";
CountryID[CountryID["SABA_ISLAND"] = 253] = "SABA_ISLAND";
CountryID[CountryID["SAINT_BARTHELEMY"] = 255] = "SAINT_BARTHELEMY";
CountryID[CountryID["SAINT_BARTHS"] = 255] = "SAINT_BARTHS";
CountryID[CountryID["SAINT_BARTS"] = 255] = "SAINT_BARTS";
CountryID[CountryID["HONG_KONG"] = 256] = "HONG_KONG";
CountryID[CountryID["SINT_MAARTEN"] = 257] = "SINT_MAARTEN";
CountryID[CountryID["TIMOR_LESTE"] = 258] = "TIMOR_LESTE";
CountryID[CountryID["SOUTH_SUDAN"] = 259] = "SOUTH_SUDAN";
})(CountryID || (CountryID = {}));
const MIN_ZOOM_LEVEL = 14;
let ZoomLevel;
(function (ZoomLevel) {
ZoomLevel[ZoomLevel["ZM0"] = 12] = "ZM0";
ZoomLevel[ZoomLevel["ZM1"] = 13] = "ZM1";
ZoomLevel[ZoomLevel["ZM2"] = 14] = "ZM2";
ZoomLevel[ZoomLevel["ZM3"] = 15] = "ZM3";
ZoomLevel[ZoomLevel["ZM4"] = 16] = "ZM4";
ZoomLevel[ZoomLevel["ZM5"] = 17] = "ZM5";
ZoomLevel[ZoomLevel["ZM6"] = 18] = "ZM6";
ZoomLevel[ZoomLevel["ZM7"] = 19] = "ZM7";
ZoomLevel[ZoomLevel["ZM8"] = 20] = "ZM8";
ZoomLevel[ZoomLevel["ZM9"] = 21] = "ZM9";
ZoomLevel[ZoomLevel["ZM10"] = 22] = "ZM10";
})(ZoomLevel || (ZoomLevel = {}));
const minShieldDisplayLengths = {
15: 150,
16: 90,
17: 80,
18: 70,
19: 60,
20: 50,
21: 40,
22: 30,
};
const RoadAbbr = {
//Canada
40: {
Alberta: {
"^Hwy 1$": 5000, // 5000: National-Trans-Canada Highway
"^Hwy 1A\\b": 5011, // 5011: Alberta - Provincial Hwy
"^Hwy 2\\b": 5011, // 5011: Alberta - Provincial Hwy
"^Hwy 3$": 5015, // 5015: Alberta - Crowsnext Hwy
"^Hwy 3A\\b": 5011, // 5011: Alberta - Provincial Hwy
"^Hwy 16$": 5000, // 5000: National-Trans-Canada Highway
"^Hwy 16A\\b": 5011, // 5011: Alberta - Provincial Hwy
"^Hwy ([4-9]|1[0-57-9]|[2-9]\\d{1}|2\\d{2})\\b": 5011,
"^Hwy ([3-9]\\d{2})\\b": 5012,
},
"British Columbia": {
"^Hwy 1\\b": 5000, // 5000: National-Trans-Canada Highway
"^Hwy 2\\b": 5001, // 5001: BC - Provincial Hwy
"^Hwy 3\\b": 5002, // 5002: BC - Crowsnest Hwy
"^Hwy 16\\b": 5000, // 5000: National-Trans-Canada Highway
"^Hwy 113\\b": 5004, // 5004: BC - Nisga'a Hwy
"^Hwy\\s+([4-9]|[1-9][0-57-9]|10\\d|11[0-24-9]|1[2-9]\\d|[2-9]\\d{1,2})[a-zA-Z]*\\b": 5001, // 5001: BC - Provincial Hwy
},
Saskatchewan: {
"^Hwy 1\\b": 5000, // 5000: National - Trans-Canada Hwy
"^Hwy 16\\b": 5000, // 5000: National - Trans-Canada Hwy
"^Hwy ([2-9]|1[0-57-9]|[2-9]\\d|[1-3]\\d{2})\\b": 5030, // 5030: Saskatchewan - Provincial Hwy
"^Hwy (9\\d{2})\\b": 5031, // 5031: Saskatchewan - Northern Secondary Hwy
"^Hwy ([6-7]\\d{2})\\b": 5032, // 5032: Saskatchewan - Municipal Road
},
Manitoba: {
"^Hwy 1\\b": 5000, // 5000: National - Trans-Canada Hwy
"^Hwy 16\\b": 5000, // 5000: National - Trans-Canada Hwy
"^Hwy ([2-9]|1[0-57-9]|[2-9]\\d|1\\d{2})\\b": 5038, // 5038: Manitoba - Provincial Trunk Highway
"^Hwy ([2-9]\\d{2})\\b": 5039, // 5039: Manitoba - Provincial Rd
},
Ontario: {
"^QEW\\b": 5058, // 5058: Ontario QEW
"(^Hwy 17\\b|Hwy 17$)": new Set([5000, 5057]), // 5000: National - Trans-Canada Hwy
"^Hwy 407\\b": new Set([5207, 5206]), // 5060: Ontario ETR
"^Hwy 412\\b": 5059, // 5059: Ontario Toll Hwy
"^Hwy 418\\b": new Set([5059, 5057]), // 5059: Ontario Toll Hwy
// "Hwy [1-9]\\d{0,2}\\b": 5057, // 5057: Ontario King's Hwy 1-16
// "Hwy (1[89]|[2-9]d|[1-3]d{2}|40[0-6])\\b": 5057, // 5057: Ontario King's Hwy 18-406
// "Hwy (40[89]|41[01])\\b": 5057, // 5057: Ontario King's Hwy 408-411
// "Hwy (41[3-7])\\b": 5057, // 5057: Ontario King's Hwy 413-417
"^CR-[1-9]\\d{0,2}\\b": 5063,
"^Hwy\\s+([1-9]|[1-68-9]\\d|[1-3]\\d{2}|40[0-68-9]|41[0-13-79]|4[2-9]\\d|[7-9]\\d{2})[A-Z]*\\b": 5057,
"^Hwy\\s+[5-6]\\d{2}\\b": 5061, // 5061: Ontario Secondary Hwy 500-699
// "Hwy (80d|8[1-9]d)\\b": 5057, // 5057: Ontario Tertiary Hwy
"^(Muskoka|Wellington|Winchester|Regional) (Road|Rd) [1-9]\\d{0,2}\\b": new Set([
5065, 5063, 5077,
]), // Ontario Regional
},
Quebec: {
"Rte Transcanadienne": 5093, // 5093: Quebec: Route Transcanadienne
"^Aut [1-9]\\d{1,2}\\b": 5090, // 5090: Quebec Autoroute 1-999
"^Rte [1-9]\\d{0,2}\\b": 5091, // 5091: Quebec Route 100-399
"R (10d|1[1-9]d|[2-9]d{2}|1[0-4]d{2}|15[0-5]d)\b": 5092, // 5092: Quebec Route 100-1559
},
"New Brunswick": {
"^Rte 2\\b": 5000, // 5000: Trans-Canada Hwy
"^Rte 16\\b": 5000, // 5000: Trans-Canada Hwy
"^Rte 1\\b": 5112, // 5112: NB Arterial Highway 1
"^Rte ([3-9]|1[0-57-9]|[2-9]\\d)\\b": 5112, // 5112: NB Arterial Highway 17-99
"^Rte (10\\d|11[02-9]|1[2-9]\\d)\\b": 5113, // 5113: NB Collector Highway 100-199
"^Rte (111|[2-9]\\d{2})\\b": 5114, // 5114: NB Local Highway 200-999
},
"Nova Scotia": {
"^Hwy ([1-9]\\d{0,1})\\b": 5116, // 5116: NS Trunk Hwy 1-99
"^Hwy 104\\b": new Set([5115, 5000]), // In NS 104 has 2 different shields
"^Hwy (10[5-6])\\b": 5000, // 5000: National Trans Canada Highway 105-106
"^Hwy (10[0-37-9]|1[1-9]\\d)\\b": 5115, // 5115: NS Aterial Hwy 107-199
"^Hwy ([2-3]\\d{2})\\b": 5117, // 5117: NS Collector Hwy 200-399
},
"Newfoundland and Labrador": {
"^Hwy 1": 5000, // 5000: National - Trans-Canada Hwy 1
"^Rte ([2-9]|[1-9]\\d|[1-5]\\d{2})\\b": 5129, // NLR: Newfoundland Labrador Route 2-599
},
"Prince Edward Island": {
"^Rte 1$": 5000, // 5000: National Trans-Canada Hwy
"^Rte ([2-9]|[1-9]\\d{1,2})\\b": 5144, // 5144: PEI - Provincial Highway
},
"Yukon Territory": {
"^Hwy 1\\b": 5146, // 5145: Yukon - Territorial Hwy - Orange
"Hwy 2": 5146, // 5146: Yukon - Territorial Hwy - Amber
"Hwy 3": 5147, // 5147: Yukon - Territorial Hwy - Maroon
"Hwy 4": 5148, // 5148: Yukon - Territorial Hwy - Brown
"Hwy 5": 5149, // 5149: Yukon - Territorial Hwy - Blue
"Hwy 6": 5150, // 5150: Yukon - Territorial Hwy - Teal
"Hwy 7": 5147, // 5147: Yukon - Territorial Hwy - Maroon
"Hwy 8": 5148, // 5148: Yukon - Territorial Hwy - Brown
"Hwy 9": 5151, // 5151: Yukon - Territorial Hwy - Black
"Hwy 10": 5151, // 5151: Yukon - Territorial Hwy - Black
"Hwy 11": 5149, // 5149: Yukon - Territorial Hwy - Blue
"Hwy 37": 5147, // 5147: Yukon - Territorial Hwy - Maroon
},
"Northwest Territories": {
"Hwy ([1-9]|10)\b": 5152, // 5152: NWT - Territorial Hwy 1-10
},
},
// France
73: {
"": {
"D\\d+[^:]*": 1092,
"N\\d+[^:]*": 1072,
"A\\d+[^:]*": 1072,
"M\\d+[^:]*": 1067,
"C\\d+[^:]*": 3333,
"T\\d+[^:]*": 3037,
},
},
// Germany
81: { "": { "(A\\d{1,3})": 1012, "(B\\d{1,3})": 1094 } },
// Mexico
145: {
"*": { "^MEX-[1-9]\\d{0,2}[A-Z]*\\b": new Set([1107, 1106]) },
"Quintana Roo": { "Q.ROO-[1-9]\\d{0,2}\\b": 1000 },
Yucatán: { "YUC-[1-9]\\d{0,2}\\b": 1000 },
Campeche: { "CAM-[1-9]\\d{0,2}\\b": 1000 },
},
// Ukraine
232: {
"": {
"(E\\d{2,3})": 1048,
"(М-\\d{2})": 1071,
"(Н-\\d{2})": 1071,
"(Р-\\d{2})": 1008,
"(Т-\\d{2}-\\d{2,3})": 1008,
"(О\\d{6,7})": 1085,
"(С\\d{6,7})": 1085,
},
},
// US
235: {
"*": {
"^I-[1-9]\\d{0,2}(?!\s+(?:W|E|East|West))\\b": 5,
"^I-[1-9]\\d{0,2}\\s{1,}\\b(?:Bus|BUS|Business|BUSINESS)\\b": 2003,
"^US-[1-9]\\d{0,2}[A-Z]*\\b": 6,
},
Alabama: { "^CR-[1-9]\\d{0,2}\\b": 2002, "^SR-[1-9]\\d{0,2}\\b": 2019 },
Alaska: {
"CR-[1-9]\\d{0,2}": 2002,
"SR-[1-9]\\d{0,2}": 2017,
"AK-[1-9]\\d{0,2}": 2017,
"A-[1-9]\\d{0,2}": 2017,
},
Arizona: { "CR-[1-9]\\d{0,2}": 2002, "SR-[1-9]\\d{0,2}": 2022 },
Arkansas: { "^CR-[1-9]\\d{0,2}\\b": 2002, "^AR-[1-9]\\d{0,2}\\b": 2020, "^AR-$1 SPUR\\b": 2020 },
California: { "^CR-[1-9]\\d{0,2}\\b": 2002, "^SH-[1-9]\\d{0,2}\\b": 1082, "^SR-[1-9]\\d{0,2}\\b": 1082 },
Colorado: {
"^CR-[1-9]\\d{0,2}[a-zA-Z]*\\b": 2002,
"^SH-[1-9]\\d{0,2}[a-zA-Z]*\\b": 2025,
"^SR-[1-9]\\d{0,2}\\b": 2025,
},
Connecticut: {
"^CR-[1-9]\\d{0,2}": 2002,
"^SH-[1-9]\\d{0,2}": 2027,
"^SR-[1-9]\\d{0,2}": 2027,
"\\b(?:Wilbur Cross(?: Parkway| Pkwy))\\b": 2027,
},
Delaware: { "^CR-[1-9]\\d{0,2}\\b": 2002, "^SH-[1-9]\\d{0,2}\\b": 7, "^SR-[1-9]\\d{0,2}\\b": 7 },
"District of Columbia": { "DC-[1-9]\\d{0,2}": 7 },
Florida: {
"^CR-[1-9]\\d{0,2}": 2002,
"^SH-[1-9]\\d{0,2}": 2030,
"^SR-[1-9]\\d{0,2}": 2030,
"^Florida.* (Turnpike|Tpk|Tpke)\\b": 2033,
},
Georgia: { "^CR-[1-9]\\d{0,2}\\b": 2002, "^SH-[1-9]\\d{0,2}\\b": 2036, "^SR-[1-9]\\d{0,2}\\b": 2036 },
Hawaii: {
"H-[1-9]\\d{0,2}": 5,
"CR-[1-9]\\d{0,2}": 2002,
"SH-[1-9]\\d{0,2}": 2041,
"SR-[1-9]\\d{0,2}": 2041,
},
Idaho: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2043,
"^SR-[1-9]\\d{0,2}\\b": 2043,
"^ID-[1-9]\\d{0,2}\\b": 2043,
},
Illinois: {
"^CH-[1-9]\\d{0,2}": 2002,
"^CR-[1-9]\\d{0,3}": 2002,
"^SH-[1-9]\\d{0,2}": 2044,
"^SR-[1-9]\\d{0,2}": 2044,
},
Indiana: {
"^CH-[1-9]\\d{0,2}": 2002,
"^CR-[1-9]\\d{0,2}": 2002,
"^SH-[1-9]\\d{0,2}": 2045,
"^SR-[1-9]\\d{0,2}": 2045,
"^IN-[1-9]\\d{0,2}": 2045,
},
Iowa: {
"CH-[1-9]\\d{0,2}": 2002,
"CR-[1-9]\\d{0,2}": 2002,
"SH-[1-9]\\d{0,2}": 7,
"SR-[1-9]\\d{0,2}": 7,
"IA-[1-9]\\d{0,2}": 7,
},
Kansas: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2046,
"^SR-[1-9]\\d{0,2}\\b": 2046,
"^K-[1-9]\\d{0,2}\\b": 2046,
},
Kentucky: {
"^US-[1-9]\\d{0,2}\\s+(?:BUS|Bus|Business)\\b": 2005,
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 7,
"^SR-[1-9]\\d{0,2}\\b": 7,
"^KY-[1-9]\\d{0,3}\\b": 7,
"^AA (Highway|Hwy)\\b": 2050,
},
Louisiana: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 1117,
"^SR-[1-9]\\d{0,3}\\b": 1117,
"^LA-[1-9]\\d{0,3}\\b": new Set([1117, 1115]),
},
Maine: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2051,
"^SR-[1-9]\\d{0,2}(?!\\s*(?:BUS|Bus|Business))\\b": 2051,
"^SR-[1-9]\\d{0,2}\\s+(?:BUS|Bus|Business)\\b": 2052,
},
Maryland: {
"^CH-[1-9]\\d{0,2}": 2002,
"^CR-[1-9]\\d{0,2}": 2002,
"^SH-[1-9]\\d{0,2}": 2053,
"^SR-[1-9]\\d{0,2}": 2053,
"^MD-[1-9]\\d{0,2}": 2053,
},
Massachusetts: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2055,
"^SR-[1-9]\\d{0,2}[a-zA-Z]*\\b": 2055,
},
Michigan: { "^CR-[1-9]\\d{0,2}\\b": 2056, "^M-[1-9]\\d{0,2}\\b": 2056, "^SR-[1-9]\\d{0,2}\\b": 2056 },
Minnesota: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2180,
"^SH-[1-9]\\d{0,2}\\b": 2060,
"^SR-[1-9]\\d{0,2}\\b": 2060,
"^MN-[1-9]\\d{0,2}\\b": 2060,
},
Mississippi: { "^SH-[1-9]\\d{0,2}\\b": 7, "^SR-[1-9]\\d{0,2}\\b": 7, "^MS-[1-9]\\d{0,2}\\b": 7 },
Missouri: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2061,
"^SH-[A-Z]\\w{0,2}\\b": 2062,
"^SR-[1-9]\\d{0,2}\\b": 2061,
"^MO-[1-9]\\d{0,2}\\b": 2061,
},
Montana: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2063,
"^SR-[1-9]\\d{0,2}\\b": 2063,
"^MT-[1-9]\\d{0,2}\\b": 2063,
},
Nebraska: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 7,
"^SR-[1-9]\\d{0,2}\\b": 7,
"^L-[1-9]\\d{0,2}\\b": 7,
"^N-[1-9]\\d{0,2}\\b": 2072,
"^S-[1-9]\\d{0,2}\\b": 7,
},
Nevada: {
"^US-[1-9]\\d{0,2}\\s+(?:ALT|Alt)\\b": 2004,
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2086,
"^SR-[1-9]\\d{0,2}\\b": 2086,
"^NV-[1-9]\\d{0,2}\\b": 2086,
},
"New Hampshire": {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2076,
"^SR-[1-9]\\d{0,2}[a-zA-Z]*\\b": 2076,
},
"New Jersey": {
"^CH-[1-9]\\d{0,2}": 2002,
"^CR-[1-9]\\d{0,2}": 2083,
"^SH-[1-9]\\d{0,2}": 7,
"^SR-[1-9]\\d{0,2}": 7,
"^NJ-[1-9]\\d{0,2}": 7,
"^Garden State (Parkway|Pkwy)": 2079,
"^Palisades Interstate (Parkway|Pkwy)": 2082,
"^Atlantic City (Expressway|Expy|Expwy)": 2000,
},
"New Mexico": {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2085,
"^SR-[1-9]\\d{0,2}\\b": 2085,
},
"New York": {
"^CH-[1-9]\\d{0,2}": 2002,
"^CR-[1-9]\\d{0,2}[A-Z]*\\b": 2002,
"^SH-[1-9]\\d{0,2}": 2087,
"^SR-[1-9]\\d{0,2}": 2087,
"^NY-[1-9]\\d{0,2}": 2087,
"\\bPalisades Interstate (Parkway|Pkwy)\\b": 2082,
"\\b(?:Saw Mill River(?: Parkway| Pkwy)|SMP)\\b": 2092,
"\\b(?:Taconic State(?: Parkway| Pkwy)|TSP)\\b": 2092,
"\\b(?:Bear Mountain State(?: Parkway| Pkwy)|BMP)\\b": 2092,
"\\b(?:Cross County(?: Parkway| Pkwy)|CCP)\\b": 2092,
"\\b(?:Hutchinson River(?: Parkway| Pkwy)|HRP)\\b": 2092,
"\\b(?:Korean War Veterans(?: Parkway| Pkwy)|KWVP)\\b": 2092,
"\\b(?:Pelham(?: Parkway| Pkwy)|PP)\\b": 2092,
"\\b(?:Sprain Brook(?: Parkway| Pkwy)|SBP)\\b": 2092,
"\\b(?:Belt(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Cross Island(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Grand Central(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Jackie Robinson(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Bronx River(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Hutchison River(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Mosholu(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Northern State(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Harlem River(?: Drive| Dr))\\b": 2090,
"\\b(?:Robert Moses(?: Causeway| Cswy))\\b": 2090,
"\\b(?:Sagtikos State(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Southern State(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Sunken Meadow State(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Wantagh State(?: Parkway| Pkwy))\\b": 2090,
"\\b(?:Loop(?: Parkway| Dr))\\b": 2091,
"\\b(?:Bethpage State(?: Parkway| Pkwy))\\b": 2091,
"\\b(?:Meadowbrook State(?: Parkway| Pkwy))\\b": 2091,
"\\b(?:Lake Ontario State(?: Parkway| Pkwy))\\b": 2093,
"\\b(?:Niagara Scenic(?: Parkway| Pkwy))\\b": 2094,
},
"North Carolina": {
"^US-[1-9]\\d{0,2}\\s+(?:BUS|Bus|Business)\\b": 2005,
"^US-[1-9]\\d{0,2}\\s+(?:BYP|Byp|Bypass)\\b": 2006,
"^US-[1-9]\\d{0,2}\\s+(?:CONN|Conn|Connector)\\b": 2007,
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2065,
"^SR-[1-9]\\d{0,2}\\b": 2065,
"^NC-[1-9]\\d{0,2}\\b": 2065,
},
"North Dakota": {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2070,
"^SR-[1-9]\\d{0,2}\\b": 2070,
"^ND-[1-9]\\d{0,3}\\b": 2070,
},
Ohio: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,3}\\b": 2181,
"^SH-[1-9]\\d{0,2}\\b": 2095,
"^SR-[1-9]\\d{0,2}\\b": 2095,
},
Oklahoma: { "^SH-[1-9]\\d{0,2}\\b": 2097, "^SR-[1-9]\\d{0,2}\\b": 2097 },
Oregon: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2099,
"^SR-[1-9]\\d{0,2}\\b": 2099,
"^OR-[1-9]\\d{0,2}\\b": 2099,
},
Pennsylvania: {
"^US-[1-9]\\d{0,2}\\s+(?:BUS|Bus|Business)\\b": 2005,
"^CH-[1-9]\\d{0,2}": 2002,
"^CR-[1-9]\\d{0,2}": 2002,
"^SH-[1-9]\\d{0,2}": 2101,
"^PA-[1-9]\\d{0,2}\\b": 2101,
"^Hwy\\s[1-9]\\d{0,2}\\b": 2101,
"^SR-[1-9]\\d{0,2}\\s+(?:BUS|Bus|Business)\\b": 2104,
"^SR-[1-9]\\d{0,2}(?!\\s*(?:BUS|Bus|Business))\\b": 2101,
},
"Rhode Island": {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2108,
"^SR-[1-9]\\d{0,2}\\b": 2108,
"^RI-[1-9]\\d{0,2}\\b": 2108,
},
"South Carolina": {
"^CH-[1-9]\\d{0,2}": 2002,
"^CR-[1-9]\\d{0,2}": 2002,
"^SH-[1-9]\\d{0,2}": 2109,
"^SR-[1-9]\\d{0,2}": 2109,
"^SC-[1-9]\\d{0,2}": 2109,
},
"South Dakota": {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9A-Z]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2114,
"^SR-[1-9]\\d{0,2}\\b": 2114,
"^SD-[1-9]\\d{0,3}\\b": 2114,
},
Tennessee: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2115,
"^TN-[1-9]\\d{0,2}\\b": 2115,
"^SR-[1-9]\\d{0,2}\\b": 2116,
},
Texas: {
"^I-[1-9]\\d{0,2}[A-Z]+\\s": new Set([5, 2206]),
"^SH-[1-9]\\d{0,3}": new Set([2117, 2123]),
"^[Ss][Pp][Uu][Rr] [1-9]\\d{0,3}\\b": 2126,
"\\b[Ll][Oo][Oo][Pp] [1-9]\\d{0,3}\\b": 2122,
"^SR-[1-9]\\d{0,3}": 2117,
"^FM-[1-9]\\d{0,3}": 2121,
"^Beltway [1-9]\\d{0,3}\\b": 2119,
"^Sam Houston (Tollway|Tlwy|Parkway|Pkwy)\\b": 2198,
"^President George Bush (Turnpike|Tpke|Tpk)\\b": 2123,
"^Park (Road|Rd)\\b": 2144,
"^Westpark (Tollway|Tlwy)\\b": 2199,
"^Fort Bend (Tollway|Tlwy|Parkway|Pkwy)\\b": 2196,
},
Utah: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2127,
"^SR-[1-9]\\d{0,2}\\b": 2127,
},
Vermont: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2131,
"^SR-[1-9]\\d{0,2}\\b": 2131,
"^VT-[1-9]\\d{0,2}\\b": 2131,
},
Virginia: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}]\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2128,
"^SR-[1-9]\\d{0,2}\\b": 2128,
"^Blue Ridge Pkwy\\b": 2069,
},
Washington: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2133,
"^SR-[1-9]\\d{0,2}(?!\\s*(?:Spur|SPUR|BUS|Bus|Business))\\b": 2133,
"^SR-[1-9]\\d{0,2}\\s+(?:Spur|SPUR|BUS|Bus|Business)": 2134,
"^FS-[1-9]\\d{0,3}\\b": 2011,
},
"West Virginia": {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2138,
"^SR-[1-9]\\d{0,2}\\b": 2138,
"^WV-[1-9]\\d{0,2}\\b": 2138,
},
Wisconsin: {
"^CH-[A-Z]+\\b": 2137,
"^CR-[1-9]\\d{0,2}": 2137,
"^SH-[1-9]\\d{0,2}": 2135,
"^SR-[1-9]\\d{0,2}": 2135,
"^WIS-[1-9]\\d{0,2}\\b": 2135,
"^WIS SPUR": 2135,
},
Wyoming: {
"^CH-[1-9]\\d{0,2}\\b": 2002,
"^CR-[1-9]\\d{0,2}\\b": 2002,
"^SH-[1-9]\\d{0,2}\\b": 2143,
"^SR-[1-9]\\d{0,2}\\b": 2143,
"^WY-[1-9]\\d{0,2}\\b": 2143,
},
},
// Uruguay
236: { "": { Ruta: 1111 } },
// Réunion
262: { "": { "D\\d+[^:]*": 1092, "N\\d+[^:]*": 1072 } },
// Guadeloupe
590: { "": { "D\\d+[^:]*": 1092, "N\\d+[^:]*": 1072 } },
// French Guyana
594: { "": { "D\\d+[^:]*": 1092, "N\\d+[^:]*": 1072 } },
// Martinique
596: { "": { "D\\d+[^:]*": 1092, "N\\d+[^:]*": 1072 } },
// Wallis and Futuna
681: { "": { "D\\d+[^:]*": 1092, "N\\d+[^:]*": 1072 } },
// French Polynesia
689: { "": { "D\\d+[^:]*": 1092, "N\\d+[^:]*": 1072 } },
};
const iconsAllowingNoText = new Set([
2000, // Atlantic City Expy
2079, // Garden State Parkway
2033, // Florida's Turnpike
2082, // Palisades Pkwy
2093, // Ontario State Pkwy
2094, // Niagara Scenic Pkwy
2199, // Westpark Tollway,
2198, // Sam Houston Parkway,
2196, // Fort Bend
2050, // AA Hwy,
2069, // Blue Ridge Pkwy
5058, // QEW
]);
const Strings = {
en: {
enableScript: "Script enabled",
HighSegShields: "Segments with Shields",
HighSegShieldsClr: "Segments with Shields",
ShowSegShields: "Show Segment Shields on Map",
SegShieldMissing: "Segments that might be missing shields",
SegShieldMissingClr: "Segments that might be missing shields",
SegShieldError: "Segments that have shields but maybe shouldn't",
SegShieldErrorClr: "Segments that have shields but maybe shouldn't",
HighNodeShields: "Nodes with Shields (TG)",
HighNodeShieldsClr: "Nodes with Shields (TG)",
ShowNodeShields: "Show Node Shield Info",
ShowExitShields: "Has Exit Signs",
ShowTurnTTS: "Has TIO",
AlertTurnTTS: "Alert if TTS is different from default",
NodeShieldMissing: "Nodes that might be missing shields",
NodeShieldMissingClr: "Nodes that might be missing shields",
resetSettings: "Reset Settings",
disabledFeat: "(Feature not configured for this country)",
ShowTowards: "Has Towards",
ShowVisualInst: "Has Visual Instruction",
SegHasDir: "Segment Shields with direction",
SegHasDirClr: "Segment Shields with direction",
SegInvDir: "Segment Shields without direction",
SegInvDirClr: "Segment Shields without direction",
IconHead: "Map Icons",
HighlightHead: "Highlights",
HighlightColors: "Highlight Colors",
ShowRamps: "Include Ramps",
Experimental: "Experimental Features (Use at Your own Risk)",
AlternativeShields: "Alternative Name Shields",
AlternativePrimaryCity: "Alternative Street with Primary City",
AlternativeNoCity: "Alternative Street with No City",
mHPlus: "Only show on minor highways or greater",
titleCase: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseClr: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseSftClr: "Direction in free text might not be in large-and-small-caps format",
checkTWD: "Include Towards field",
checkTTS: "Include TTS field",
checkVI: "Include Visual Instruction field",
},
"en-us": {
enableScript: "Script enabled",
HighSegShields: "Segments with Shields",
HighSegShieldsClr: "Segments with Shields",
ShowSegShields: "Show Segment Shields on Map",
SegShieldMissing: "Segments that might be missing shields",
SegShieldMissingClr: "Segments that might be missing shields",
SegShieldError: "Segments that have shields but maybe shouldn't",
SegShieldErrorClr: "Segments that have shields but maybe shouldn't",
HighNodeShields: "Nodes with Shields (TG)",
HighNodeShieldsClr: "Nodes with Shields (TG)",
ShowNodeShields: "Show Node Shield Info",
ShowExitShields: "Has Exit Signs",
ShowTurnTTS: "Has TIO",
AlertTurnTTS: "Alert if TTS is different from default",
NodeShieldMissing: "Nodes that might be missing shields",
NodeShieldMissingClr: "Nodes that might be missing shields",
resetSettings: "Reset Settings",
disabledFeat: "(Feature not configured for this country)",
ShowTowards: "Has Towards",
ShowVisualInst: "Has Visual Instruction",
SegHasDir: "Segment Shields with direction",
SegHasDirClr: "Segment Shields with direction",
SegInvDir: "Segment Shields without direction",
SegInvDirClr: "Segment Shields without direction",
IconHead: "Map Icons",
HighlightHead: "Highlights",
HighlightColors: "Highlight Colors",
ShowRamps: "Include Ramps",
Experimental: "Experimental Features (Unstable use at Your own Risk)",
AlternativeShields: "Alternative Name Shields",
AlternativePrimaryCity: "Alternative Street with Primary City",
AlternativeNoCity: "Alternative Street with No City",
mHPlus: "Only show on minor highways or greater",
titleCase: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseClr: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseSftClr: "Direction in free text might not be in large-and-small-caps format",
checkTWD: "Include Towards field",
checkTTS: "Include TTS field",
checkVI: "Include Visual Instruction field",
},
"es-419": {
enableScript: "Script habilitado",
HighSegShields: "Segmentos con escudos",
HighSegShieldsClr: "Segmentos con escudos",
ShowSegShields: "Mostrar escudos de segmentos en el mapa",
SegShieldMissing: "Segmentos a los que les pueden faltar escudos",
SegShieldMissingClr: "Segmentos a los que les pueden faltar escudos",
SegShieldError: "Segmentos que tienen escudos y quizá no deberían",
SegShieldErrorClr: "Segmentos que tienen escudos y quizá no deberían",
HighNodeShields: "Nodos con escudos (TG)",
HighNodeShieldsClr: "Nodos con escudos (TG)",
ShowNodeShields: "Mostrar Info de Escudo en Nodo",
ShowExitShields: "Incluir iconos de giro (si existen)",
ShowTurnTTS: "Incuir TTS",
AlertTurnTTS: "Alertar si TTS fue modificado",
NodeShieldMissing: "Nodos a los que les pueden faltar escudos",
NodeShieldMissingClr: "Nodos a los que les pueden faltar escudos",
resetSettings: "Reiniciar ajustes",
disabledFeat: "(Funcionalidad no configurada para ese país)",
ShowTowards: "Incluir dirección (si existe)",
ShowVisualInst: "Incluir instrucción visual",
SegHasDir: "Escudos con dirección",
SegHasDirClr: "Escudos con dirección",
SegInvDir: "Escudos sin dirección",
SegInvDirClr: "Escudos sin dirección",
IconHead: "Iconos en mapa",
HighlightHead: "Destacar",
HighlightColors: "Reseña de Colores",
ShowRamps: "Incluir Rampas",
Experimental: "Experimental Features",
AlternativeShields: "Alternative Name Shields",
AlternativePrimaryCity: "Alternative Street with Primary City",
AlternativeNoCity: "Alternative Street with No City",
mHPlus: "Only show on minor highways or greater",
titleCase: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseClr: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseSftClr: "Direction in free text might not be in large-and-small-caps format",
checkTWD: "Include Towards field",
checkTTS: "Include TTS field",
checkVI: "Include Visual Instruction field",
},
uk: {
enableScript: "Скріпт вимкнено",
HighSegShields: "Сегменти з шильдами",
HighSegShieldsClr: "Сегменти з шильдами",
ShowSegShields: "Показувати шильди на мапі",
SegShieldMissing: "Сегменти, яким можливо потрібні шильди",
SegShieldMissingClr: "Сегменти, яким можливо потрібні шильди",
SegShieldError: "Сегменти, які мають шильди, але можливо вони непотрібні",
SegShieldErrorClr: "Сегменти, які мають шильди, але можливо вони непотрібні",
HighNodeShields: "Вузли з шильдами (TG)",
HighNodeShieldsClr: "Вузли з шильдами (TG)",
ShowNodeShields: "Показувати деталі шильда на вузлі ",
ShowExitShields: "Включити іконку повороту (якщо вони є)",
ShowTurnTTS: "Вимкнути TTS",
AlertTurnTTS: "Сповіщати, якщо TTS відрізняється від типового",
NodeShieldMissing: "Вузли, на яких можуть бути відсутні щити",
NodeShieldMissingClr: "Вузли, на яких можуть бути відсутні щити",
resetSettings: "Скинути налаштування",
disabledFeat: "Відсутні налаштування для цієї страни",
ShowTowards: "Включаючи Towards (якщо існує)",
ShowVisualInst: "Включаючи візуальні інструкції",
SegHasDir: "Шильди з напрямками",
SegHasDirClr: "Шильди з напрямками",
SegInvDir: "Шильди без напрямків",
SegInvDirClr: "Шильди без напрямків",
IconHead: "Іконки на мапі",
HighlightHead: "Підсвічувати",
HighlightColors: "Кольори підсвічування",
ShowRamps: "Включаючи рампи",
Experimental: "Экспериментальні засобливості",
AlternativeShields: "Шильди альтернатівних назв",
AlternativePrimaryCity: "Альтернативна назва с основним містом",
AlternativeNoCity: "Альтернативна назва без міста",
mHPlus: "Only show on minor highways or greater",
titleCase: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseClr: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseSftClr: "Direction in free text might not be in large-and-small-caps format",
checkTWD: "Include Towards field",
checkTTS: "Include TTS field",
checkVI: "Include Visual Instruction field",
},
fr: {
enableScript: "Script activé",
HighSegShields: "Segments avec cartouche",
HighSegShieldsClr: "Segments avec cartouche",
ShowSegShields: "Afficher les cartouches sur la carte",
SegShieldMissing: "Segments dont le cartouche pourrait manquer",
SegShieldMissingClr: "Segments dont le cartouche pourrait manquer",
SegShieldError: "Segments ayant un cartouche mais ne devraient peut-être pas",
SegShieldErrorClr: "Segments ayant un cartouche mais ne devraient peut-être pas",
HighNodeShields: "Noeuds avec cartouche (TG)",
HighNodeShieldsClr: "Noeuds avec cartouche (TG)",
ShowNodeShields: "Afficher les infos des cartouches de noeuds",
ShowExitShields: "As des panneaux de sortie",
ShowTurnTTS: "Has TIO",
AlertTurnTTS: "Alert if TTS is different from default",
NodeShieldMissing: "Noeud dont le cartouche pourrait manquer",
NodeShieldMissingClr: "Noeud dont le cartouche pourrait manquer",
resetSettings: "Réinitialiser les paramètres",
disabledFeat: "Feature not configured for this country",
ShowTowards: 'As "En direction de"',
ShowVisualInst: "As des instructions visuelles",
SegHasDir: "Cartouche de segment avec direction",
SegHasDirClr: "Cartouche de segment avec direction",
SegInvDir: "Cartouche de segment sans direction",
SegInvDirClr: "Cartouche de segment sans direction",
IconHead: "Icônes de carte",
HighlightHead: "Surlignages",
HighlightColors: "Couleurs de surlignage",
ShowRamps: "Inclure les bretelles",
mHPlus: "Only show on minor highways or greater",
Experimental: "Experimental Features",
AlternativeShields: "Alternative Name Shields",
AlternativePrimaryCity: "Alternative Street with Primary City",
AlternativeNoCity: "Alternative Street with No City",
titleCase: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseClr: "Segments/nodes with direction not in large-and-small-caps format",
TitleCaseSftClr: "Direction in free text might not be in large-and-small-caps format",
checkTWD: 'Inclure le champ "en direction de"',
checkTTS: "Inclure le champ TTS",
checkVI: "Inclure le champ d'instruction visuel",
},
};
const CheckAltName = new Set([
// France
73,
]);
let BadNames = [];
let rsaSettings = {
lastSaveAction: 0,
enableScript: true,
HighSegShields: false,
ShowSegShields: true,
SegShieldMissing: false,
SegShieldError: false,
SegHasDir: false,
SegInvDir: false,
HighNodeShields: true,
ShowNodeShields: false,
ShowExitShields: false,
ShowTurnTTS: false,
AlertTurnTTS: false,
ShowTowards: false,
ShowVisualInst: false,
NodeShieldMissing: false,
HighSegClr: "#0066ff",
MissSegClr: "#00ff00",
ErrSegClr: "#cc00ff",
HighNodeClr: "#ff00bf",
MissNodeClr: "#ff0000",
SegHasDirClr: "#ffff00",
SegInvDirClr: "#66ffff",
TitleCaseClr: "#ff9933",
TitleCaseSftClr: "#ffff66",
ShowRamps: true,
AlternativeShields: false,
mHPlus: false,
titleCase: false,
checkTWD: false,
checkTTS: false,
checkVI: false,
mapLayerVisible: false,
iconLayerVisible: false,
};
let UpdateObj;
let SetTurn;
const rsaMapLayer = { layerName: "RSA Map Layer", zIndexing: false };
const rsaIconLayer = { layerName: "RSA Icon Layer", zIndexing: false };
let LANG;
let alternativeType;
const styleConfig = {
styleContext: {
highNodeColor: (context) => {
return context?.feature?.properties?.style?.strokeColor;
},
labelExternalGraphic: (context) => {
const style = context?.feature?.properties?.style;
if (!style || !style?.sign || !style?.txt)
return "";
return `https://renderer-am.waze.com/renderer/v1/signs/${style.sign}?text=${style.txt}`;
},
labelGraphicHeight: (context) => {
return context?.feature?.properties?.style?.height;
},
labelGraphicWidth: (context) => {
return context?.feature?.properties?.style?.width;
},
shieldExternalGraphic: (context) => {
return context?.feature?.properties?.style?.externalGraphic;
},
shieldGraphicWidth: (context) => {
return context?.feature?.properties?.style?.graphicWidth;
},
shieldGraphicHeight: (context) => {
return context?.feature?.properties?.style?.graphicHeight;
},
shieldLabel: (context) => {
return context?.feature?.properties?.style?.label;
},
nodeStyleStrokeColor: (context) => {
return context?.feature?.properties?.style?.strokeColor;
},
nodeStyleStrokeOpacity: (context) => {
return context?.feature?.properties?.style?.strokeOpacity;
},
nodeStyleStrokeWidth: (context) => {
return context?.feature?.properties?.style?.strokeWidth;
},
nodeStyleFillOpacity: (context) => {
return context?.feature?.properties?.style?.fillOpacity;
},
nodeStylePointRadius: (context) => {
return context?.feature?.properties?.style?.pointRadius;
},
segHighlightStrokeOpacity: (context) => {
return context?.feature?.properties?.style?.strokeOpacity;
},
segHighlightStrokeColor: (context) => {
return context?.feature?.properties?.style?.strokeColor;
},
segHighlightStrokeWidth: (context) => {
return context?.feature?.properties?.style?.strokeWidth;
},
segHighlightFillColor: (context) => {
return context?.feature?.properties?.style?.fillColor;
},
segHighlightFillOpacity: (context) => {
return context?.feature?.properties?.style?.fillOpacity;
},
shieldLabelYOffset: (context) => {
return context?.feature?.properties?.style?.labelYOffset;
},
},
styleRules: [
{
predicate: applyPointLabel,
style: {
strokeColor: "${highNodeColor}",
strokeOpacity: 0.75,
strokeWidth: 4,
fillColor: "${highNodeColor}",
fillOpacity: 0.75,
pointRadius: 3,
},
},
{
predicate: applyShield,
style: {
externalGraphic: "${shieldExternalGraphic}",
graphicWidth: "${shieldGraphicWidth}",
graphicHeight: "${shieldGraphicHeight}",
graphicXOffset: -20,
graphicYOffset: -20,
style: "opacity: 1",
fillOpacity: 1,
fill: "black",
stroke: "black",
fontColor: "green",
labelOutlineColor: "white",
labelOutlineWidth: 1,
fontSize: 12,
display: "grid",
label: "${shieldLabel}",
labelYOffset: "${shieldLabelYOffset}",
},
},
{
predicate: applySegHighlight,
style: {
strokeColor: "${segHighlightStrokeColor}",
strokeOpacity: "${segHighlightStrokeOpacity}",
strokeWidth: "${segHighlightStrokeWidth}",
fillColor: "${segHighlightFillColor}",
fillOpacity: "${segHighlightFillOpacity}",
},
},
{
predicate: applyStyleNode,
style: {
strokeColor: "${nodeStyleStrokeColor}",
strokeOpacity: "${nodeStyleStrokeOpacity}",
strokeWidth: "${nodeStyleStrokeWidth}",
fillColor: "${nodeStyleFillColor}",
fillOpacity: "${nodeStyleFillOpacity}",
pointRadius: "${nodeStylePointRadius}",
},
},
{
predicate: applyStyleLabel,
style: {
externalGraphic: "${labelExternalGraphic}",
graphicHeight: "${labelGraphicHeight}",
graphicWidth: "${labelGraphicWidth}",
fillOpacity: "${nodeStyleFillOpacity}",
fontSize: 12,
graphicZIndex: 2432,
},
},
],
};
console.debug(`SDK v. ${sdk.getSDKVersion()} on ${sdk.getWMEVersion()} initialized`);
// function rsaBootstrap() {
// // if (!document.getElementById('edit-panel') || !sdk.DataModel.Countries.getTopCountry() || !WazeWrap.Ready) {
// // setTimeout(rsaBootstrap, 200);
// // }
// if (sdk.State.isReady()) {
// initRSA();
// } else {
// sdk.Events.once({eventName: "wme-ready"}).then(initRSA);
// }
// }
function initRSA() {
const locale = sdk.Settings.getLocale();
LANG = locale.localeCode.toLowerCase();
console.log("RSA: Initializing...");
// let UpdateObj = sdk.DataModel. require('Waze/Action/UpdateObject');
// let SetTurn = require('Waze/Model/Graph/Actions/SetTurn');
const rsaCss = [
'.rsa-wrapper {position:relative;width:100%;font-size:12px;font-family:"Rubik", "Boing-light", sans-serif;user-select:none;}',
".rsa-section-wrapper {display:block;width:100%;padding:4px;}",
".rsa-section-wrapper.border {border-bottom:1px solid grey;margin-bottom:5px;}",
".rsa-header {font-weight:bold;}",
".rsa-option-container {padding:3px;}",
".rsa-option-container.no-display {display:none;}",
".rsa-option-container.sub {margin-left:20px;}",
'input[type="checkbox"].rsa-checkbox {display:inline-block;position:relative;top:3px;vertical-align:top;margin:0;}',
'input[type="color"].rsa-color-input {display:inline-block;position:relative;width:20px;padding:0px 1px;border:0px;vertical-align:top;cursor:pointer;}',
'input[type="color"].rsa-color-input:focus {outline-width:0;}',
"label.rsa-label {display:inline-block;position:relative;max-width:80%;vertical-align:top;font-weight:normal;padding-left:5px;word-wrap:break-word;}",
".group-title.toolbar-top-level-item-title.rsa:hover {cursor:pointer;}",
].join(" ");
const $rsaTab = $("<div>");
$rsaTab.html = [
`<div class='rsa-wrapper' id='rsa-tab-wrapper'>
<div style='margin-bottom:5px;border-bottom:1px solid black;'>
<span style='font-weight:bold;'>
<a href='https://www.waze.com/forum/viewtopic.php?f=1851&t=315748' target='_blank' style='text-decoration:none;'>Road Shield Assistant</a>
</span> - v${GM_info.script.version}
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-enableScript' />
<label class='rsa-label' for='rsa-enableScript'><span id='rsa-text-enableScript'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-ShowRamps' />
<label class='rsa-label' for='rsa-ShowRamps'><span id='rsa-text-ShowRamps'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-mHPlus' />
<label class='rsa-label' for='rsa-mHPlus'><span id='rsa-text-mHPlus'></span></label>
</div>
<span id='rsa-text-IconHead' class='rsa-header'></span>
<div style='border-top:2px solid black;'>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-ShowSegShields' />
<label class='rsa-label' for='rsa-ShowSegShields'><span id='rsa-text-ShowSegShields'></span></label>
</div>
<div class='rsa-option-container no-display'>
<input type=checkbox class='rsa-checkbox' id='rsa-NodeShieldMissing' />
<label class='rsa-label' for='rsa-NodeShieldMissing'><span id='rsa-text-NodeShieldMissing'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-ShowNodeShields' />
<label class='rsa-label' for='rsa-ShowNodeShields'><span id='rsa-text-ShowNodeShields'></span></label>
</div>
<div class='rsa-option-container sub'>
<input type=checkbox class='rsa-checkbox' id='rsa-ShowExitShields' />
<label class='rsa-label' for='rsa-ShowExitShields'><span id='rsa-text-ShowExitShields'></span></label>
</div>
<div class='rsa-option-container sub'>
<input type=checkbox class='rsa-checkbox' id='rsa-ShowTurnTTS' />
<label class='rsa-label' for='rsa-ShowTurnTTS'><span id='rsa-text-ShowTurnTTS'></span></label>
</div>
<div class='rsa-option-container sub'>
<input type=checkbox class='rsa-checkbox' id='rsa-ShowTowards' />
<label class='rsa-label' for='rsa-ShowTowards'><span id='rsa-text-ShowTowards'></span></label>
</div>
<div class='rsa-option-container sub'>
<input type=checkbox class='rsa-checkbox' id='rsa-ShowVisualInst' />
<label class='rsa-label' for='rsa-ShowVisualInst'><span id='rsa-text-ShowVisualInst'></span></label>
</div>
<div class='rsa-option-container sub' style='display:none;'>
<input type=checkbox class='rsa-checkbox' id='rsa-AlertTurnTTS' />
<label class='rsa-label' for='rsa-AlertTurnTTS'><span id='rsa-text-AlertTurnTTS'></span></label>
</div>
</div>
<span id='rsa-text-HighlightHead' class='rsa-header'></span>
<div style='border-top:2px solid black;'>
<div class='rsa-option-container' style='display:none;'>
<input type=checkbox class='rsa-checkbox' id='rsa-HighNodeShields' />
<label class='rsa-label' for='rsa-HighNodeShields'><span id='rsa-text-HighNodeShields'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-HighSegShields' />
<label class='rsa-label' for='rsa-HighSegShields'><span id='rsa-text-HighSegShields'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-SegHasDir' />
<label class='rsa-label' for='rsa-SegHasDir'><span id='rsa-text-SegHasDir'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-SegInvDir' />
<label class='rsa-label' for='rsa-SegInvDir'><span id='rsa-text-SegInvDir'></span></label>
</div>
<div class='rsa-option-container' id='rsa-container-titleCase'>
<input type=checkbox class='rsa-checkbox' id='rsa-titleCase' />
<label class='rsa-label' for='rsa-titleCase'><span id='rsa-text-titleCase'></span></label>
</div>
<div class='rsa-option-container sub' id='rsa-container-checkTWD'>
<input type=checkbox class='rsa-checkbox' id='rsa-checkTWD' />
<label class='rsa-label' for='rsa-checkTWD'><span id='rsa-text-checkTWD'></span></label>
</div>
<div class='rsa-option-container sub' id='rsa-container-checkTTS'>
<input type=checkbox class='rsa-checkbox' id='rsa-checkTTS' />
<label class='rsa-label' for='rsa-checkTTS'><span id='rsa-text-checkTTS'></span></label>
</div>
<div class='rsa-option-container sub' id='rsa-container-checkVI'>
<input type=checkbox class='rsa-checkbox' id='rsa-checkVI' />
<label class='rsa-label' for='rsa-checkVI'><span id='rsa-text-checkVI'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-SegShieldMissing' />
<label class='rsa-label' for='rsa-SegShieldMissing'><span id='rsa-text-SegShieldMissing'></span></label>
</div>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-SegShieldError' />
<label class='rsa-label' for='rsa-SegShieldError'><span id='rsa-text-SegShieldError'></span></label>
</div>
</div>
<span id='rsa-text-HighlightColors' class='rsa-header'></span>
<div style='border-top:2px solid black;'>
<div class='rsa-option-container'>
<input type=color class='rsa-color-input' id='rsa-HighSegClr' />
<label class='rsa-label' for='rsa-HighSegClr'><span id='rsa-text-HighSegShieldsClr'></span></label>
</div>
<div class='rsa-option-container'>
<input type=color class='rsa-color-input' id='rsa-SegHasDirClr' />
<label class='rsa-label' for='rsa-SegHasDirClr'><span id='rsa-text-SegHasDirClr'></span></label>
</div>
<div class='rsa-option-container'>
<input type=color class='rsa-color-input' id='rsa-SegInvDirClr' />
<label class='rsa-label' for='rsa-SegInvDirClr'><span id='rsa-text-SegInvDirClr'></span></label>
</div>
<div class='rsa-option-container'>
<input type=color class='rsa-color-input' id='rsa-MissSegClr' />
<label class='rsa-label' for='rsa-MissSegClr'><span id='rsa-text-SegShieldMissingClr'></span></label>
</div>
<div class='rsa-option-container'>
<input type=color class='rsa-color-input' id='rsa-ErrSegClr' />
<label class='rsa-label' for='rsa-ErrSegClr'><span id='rsa-text-SegShieldErrorClr'></span></label>
</div>
<div class='rsa-option-container'>
<input type=color class='rsa-color-input' id='rsa-HighNodeClr' />
<label class='rsa-label' for='rsa-HighNodeClr'><span id='rsa-text-HighNodeShieldsClr'></span></label>
</div>
<div class='rsa-option-container no-display'>
<input type=color class='rsa-color-input' id='rsa-MissNodeClr' />
<label class='rsa-label' for='rsa-MissNodeClr'><span id='rsa-text-NodeShieldMissingClr'></span></label>
</div>
<div class='rsa-option-container' id='rsa-container-TitleCaseClr'>
<input type=color class='rsa-color-input' id='rsa-TitleCaseClr' />
<label class='rsa-label' for='rsa-TitleCaseClr'><span id='rsa-text-TitleCaseClr'></span></label>
</div>
<div class='rsa-option-container' id='rsa-container-TitleCaseSftClr'>
<input type=color class='rsa-color-input' id='rsa-TitleCaseSftClr' />
<label class='rsa-label' for='rsa-TitleCaseSftClr'><span id='rsa-text-TitleCaseSftClr'></span></label>
</div>
</div>
<span id='rsa-text-Experimental' class='rsa-header'></span>
<div style='border-top:2px solid black;'>
<div class='rsa-option-container'>
<input type=checkbox class='rsa-checkbox' id='rsa-AlternativeShields' />
<label class='rsa-label' for='rsa-AlternativeShields'><span id='rsa-text-AlternativeShields'></span></label>
</div>
<div class='rsa-option-container sub'>
<input type=radio class='rsa-checkbox' value='AlternativePrimaryCity' name='AlternativeShields' id='rsa-AlternativePrimaryCity' checked/>
<label class='rsa-label' for='rsa-AlternativePrimaryCity'><span id='rsa-text-AlternativePrimaryCity'></span></label>
</div>
<div class='rsa-option-container sub'>
<input type=radio class='rsa-checkbox' value='AlternativeNoCity' name='AlternativeShields' id='rsa-AlternativeNoCity' />
<label class='rsa-label' for='rsa-AlternativeNoCity'><span id='rsa-text-AlternativeNoCity'></span></label>
</div>
</div>
<div style='border-top:2px solid black;'>
<div class='rsa-option-container'>
<input type=button id='rsa-resetSettings' />
</div>
</div>
</div>`,
].join(" ");
const $rsaFixWrapper = $('<div id="rsa-autoWrapper" class="toolbar-button ItemInactive" style="display:none;margin-right:5px;">');
const $rsaFixInner = $('<div class="group-title toolbar-top-level-item-title rsa" style="margin:5px 0 0 15px;font-size:12px;">RSA Fix</div>');
// WazeWrap.Interface.Tab('RSA', $rsaTab.html, setupOptions, 'RSA');
sdk.Sidebar.registerScriptTab().then((r) => {
r.tabLabel.innerHTML = "RSA";
r.tabPane.innerHTML = $rsaTab.html;
setupOptions();
});
$(`<style type="text/css">${rsaCss}</style>`).appendTo("head");
// $($rsaFixInner).appendTo($rsaFixWrapper);
// $($rsaFixWrapper).appendTo($('#primary-toolbar > div'));
WazeWrap.Interface.ShowScriptUpdate(GM_info.script.name, GM_info.script.version, RSA_UPDATE_NOTES, GF_LINK, FORUM_LINK);
console.log("RSA: loaded");
}
function processAlternativeSettings() {
if (rsaSettings.AlternativeShields) {
const alt_primary = $("#rsa-AlternativePrimaryCity");
alt_primary.prop("disabled", false);
const alt_nocity = $("#rsa-AlternativeNoCity");
alt_nocity.prop("disabled", false);
const primaryCityButton = alt_primary[0];
const noCityButton = alt_primary[0];
if (primaryCityButton.checked) {
alternativeType = primaryCityButton.value;
}
if (noCityButton.checked) {
alternativeType = noCityButton.value;
}
}
toggleAlternativeShields();
}
function getId(ele) {
return document.getElementById(ele);
}
function setChecked(ele, status) {
$(`#${ele}`).prop("checked", status);
}
function setValue(ele, value) {
const inputElem = $(`#${ele}`);
inputElem.attr("value", value);
// inputElem.css('border', `1px solid ${value}`);
}
function toggleAlternativeShields() {
if (!rsaSettings.AlternativeShields) {
$("#rsa-AlternativePrimaryCity").prop("disabled", true);
$("#rsa-AlternativeNoCity").prop("disabled", true);
}
}
function applyPointLabel(properties) {
return properties.styleName === "pointLabelStyle";
}
function applyShield(properties) {
return properties.styleName === "shield";
}
function applySegHighlight(properties) {
return properties.styleName === "segHighlight";
}
function applyStyleNode(properties) {
return properties.styleName === "styleNode";
}
function applyStyleLabel(properties) {
return properties.styleName === "styleLabel";
}
function updateMap() {
removeAutoFixButton();
tryScan();
checkOptions();
}
async function setupOptions() {
await loadSettings();
// Create OL layer for display
sdk.Map.addLayer({
layerName: rsaMapLayer.layerName,
styleRules: styleConfig.styleRules,
styleContext: styleConfig.styleContext,
});
sdk.LayerSwitcher.addLayerCheckbox({ name: rsaMapLayer.layerName });
sdk.LayerSwitcher.setLayerCheckboxChecked({
name: rsaMapLayer.layerName,
isChecked: rsaSettings.mapLayerVisible,
});
sdk.Map.setLayerVisibility({ layerName: rsaMapLayer.layerName, visibility: rsaSettings.mapLayerVisible });
sdk.Map.addLayer({
layerName: rsaIconLayer.layerName,
styleRules: styleConfig.styleRules,
styleContext: styleConfig.styleContext,
});
sdk.LayerSwitcher.addLayerCheckbox({ name: rsaIconLayer.layerName });
sdk.Map.setLayerVisibility({ layerName: rsaIconLayer.layerName, visibility: rsaSettings.iconLayerVisible });
sdk.LayerSwitcher.setLayerCheckboxChecked({
name: rsaIconLayer.layerName,
isChecked: rsaSettings.iconLayerVisible,
});
sdk.Events.on({
eventName: "wme-layer-checkbox-toggled",
eventHandler: (payload) => {
sdk.Map.setLayerVisibility({ layerName: payload.name, visibility: payload.checked });
if (payload.name === rsaMapLayer.layerName) {
rsaSettings.mapLayerVisible = payload.checked;
}
else if (payload.name === rsaIconLayer.layerName) {
rsaSettings.iconLayerVisible = payload.checked;
}
if (payload.checked)
tryScan();
saveSettings();
},
});
// Set user options
function setEleStatus() {
setChecked("rsa-enableScript", rsaSettings.enableScript);
setChecked("rsa-HighSegShields", rsaSettings.HighSegShields);
setChecked("rsa-ShowSegShields", rsaSettings.ShowSegShields);
setChecked("rsa-SegShieldMissing", rsaSettings.SegShieldMissing);
setChecked("rsa-SegShieldError", rsaSettings.SegShieldError);
setChecked("rsa-HighNodeShields", rsaSettings.HighNodeShields);
setChecked("rsa-ShowNodeShields", rsaSettings.ShowNodeShields);
setChecked("rsa-ShowExitShields", rsaSettings.ShowExitShields);
setChecked("rsa-ShowTurnTTS", rsaSettings.ShowTurnTTS);
setChecked("rsa-AlertTurnTTS", rsaSettings.AlertTurnTTS);
setChecked("rsa-ShowTowards", rsaSettings.ShowTowards);
setChecked("rsa-ShowVisualInst", rsaSettings.ShowVisualInst);
setChecked("rsa-NodeShieldMissing", rsaSettings.NodeShieldMissing);
setChecked("rsa-SegHasDir", rsaSettings.SegHasDir);
setChecked("rsa-SegInvDir", rsaSettings.SegInvDir);
setChecked("rsa-ShowRamps", rsaSettings.ShowRamps);
setChecked("rsa-mHPlus", rsaSettings.mHPlus);
setChecked("rsa-titleCase", rsaSettings.titleCase);
setChecked("rsa-checkTWD", rsaSettings.checkTWD);
setChecked("rsa-checkTTS", rsaSettings.checkTTS);
setChecked("rsa-checkVI", rsaSettings.checkVI);
setChecked("rsa-AlternativeShields", rsaSettings.AlternativeShields);
setValue("rsa-HighSegClr", rsaSettings.HighSegClr);
setValue("rsa-MissSegClr", rsaSettings.MissSegClr);
setValue("rsa-ErrSegClr", rsaSettings.ErrSegClr);
setValue("rsa-HighNodeClr", rsaSettings.HighNodeClr);
setValue("rsa-MissNodeClr", rsaSettings.MissNodeClr);
setValue("rsa-SegHasDirClr", rsaSettings.SegHasDirClr);
setValue("rsa-SegInvDirClr", rsaSettings.SegInvDirClr);
setValue("rsa-TitleCaseClr", rsaSettings.TitleCaseClr);
setValue("rsa-TitleCaseSftClr", rsaSettings.TitleCaseSftClr);
$("#rsa-AlternativeShields").on("change", (e) => {
processAlternativeSettings();
});
if (rsaSettings.titleCase && sdk.DataModel.Countries.getTopCountry()?.id === 235) {
$("#rsa-container-checkTWD").css("display", "block");
$("#rsa-container-checkTTS").css("display", "block");
$("#rsa-container-checkVI").css("display", "block");
}
else {
$("#rsa-container-checkTWD").css("display", "none");
$("#rsa-container-checkTTS").css("display", "none");
$("#rsa-container-checkVI").css("display", "none");
}
toggleAlternativeShields();
}
// Register event listeners
// WazeWrap.Events.register('selectionchanged', null, removeAutoFixButton);
sdk.Events.on({ eventName: "wme-selection-changed", eventHandler: removeAutoFixButton });
// WazeWrap.Events.register('selectionchanged', null, tryScan);
sdk.Events.on({ eventName: "wme-map-move-end", eventHandler: updateMap });
sdk.Events.on({ eventName: "wme-map-zoom-changed", eventHandler: updateMap });
sdk.Shortcuts.createShortcut({
callback: addShieldClick,
description: "Activates the Add Shield Button",
shortcutId: "addShield",
shortcutKeys: "A+83",
});
// new WazeWrap.Interface.Shortcut('addShield',
// 'Activates the Add Shield Button',
// 'wmersa',
// 'Road Shield Assistant',
// rsaSettings.addShield,
// addShieldClick, null).add();
setEleStatus();
$("input[type=radio][name=AlternativeShields]").on("change", () => {
processAlternativeSettings();
saveSettings();
removeHighlights();
tryScan();
});
$(".rsa-checkbox").on("change", function () {
const settingName = $(this)[0].id.substring(4);
rsaSettings[settingName] = this.checked;
// Check to ensure highlight nodes and show node shields don't overlap each other
// if (settingName = 'ShowNodeShields') {
// if (this.checked) {
// $('rsa-HighNodeShields').prop('checked', false);
// rsaSettings.HighNodeShields = false;
// }
// } else if (settingName = 'HighNodeShields') {
// if (this.checked) {
// $('rsa-ShowNodeShields').prop('checked', false);
// rsaSettings.ShowNodeShields = false;
// }
// }
if (settingName === "AlternativeShields")
processAlternativeSettings();
saveSettings();
removeHighlights();
tryScan();
});
$(".rsa-color-input").on("change", function () {
const settingName = $(this)[0].id.substring(4);
rsaSettings[settingName] = this.value;
saveSettings();
setEleStatus();
removeHighlights();
tryScan();
});
$("#rsa-titleCase").trigger("click", () => {
const titleCase = getId("rsa-titleCase");
if (titleCase?.checked) {
$("#rsa-container-checkTWD").css("display", "block");
$("#rsa-container-checkTTS").css("display", "block");
$("#rsa-container-checkVI").css("display", "block");
}
else {
$("#rsa-container-checkTWD").css("display", "none");
$("#rsa-container-checkTTS").css("display", "none");
$("#rsa-container-checkVI").css("display", "none");
}
});
// $('#rsa-ShowNodeShields').click(function() {
// if (!getId('rsa-ShowNodeShields').checked) $('.rsa-option-container.sub').hide();
// else $('.rsa-option-container.sub').show();
// });
$("#rsa-resetSettings").on("click", () => {
const defaultSettings = {
lastSaveAction: 0,
enableScript: true,
HighSegShields: false,
ShowSegShields: true,
SegShieldMissing: false,
SegShieldError: false,
SegHasDir: false,
SegInvDir: false,
HighNodeShields: true,
ShowNodeShields: false,
ShowExitShields: false,
ShowTurnTTS: false,
AlertTurnTTS: false,
ShowTowards: false,
ShowVisualInst: false,
NodeShieldMissing: false,
HighSegClr: "#0066ff",
MissSegClr: "#00ff00",
ErrSegClr: "#cc00ff",
HighNodeClr: "#ff00bf",
MissNodeClr: "#ff0000",
SegHasDirClr: "#ffff00",
SegInvDirClr: "#66ffff",
TitleCaseClr: "#ff9933",
TitleCaseSftClr: "#ffff66",
ShowRamps: true,
AlternativeShields: false,
mHPlus: false,
titleCase: false,
checkTWD: false,
checkTTS: false,
checkVI: false,
mapLayerVisible: false,
iconLayerVisible: false,
};
rsaSettings = defaultSettings;
saveSettings();
setEleStatus();
});
// Add translated UI text
if (!Strings[LANG])
LANG = "en";
const messageKeys = Object.keys(Strings[LANG]);
for (let i = 0; i < messageKeys.length; i++) {
const key = messageKeys[i];
$(`#rsa-text-${key}`).text(Strings[LANG][key]);
}
$("#rsa-resetSettings").attr("value", Strings[LANG].resetSettings);
checkOptions();
}
async function loadSettings() {
const localSettings = JSON.parse(localStorage.getItem("RSA_Settings"));
const serverSettings = await WazeWrap.Remote.RetrieveSettings("RSA_Settings");
if (!serverSettings) {
console.error("RSA: Error communicating with WW settings server");
}
const defaultSettings = {
lastSaveAction: 0,
enableScript: true,
HighSegShields: false,
ShowSegShields: true,
SegShieldMissing: false,
SegShieldError: false,
SegHasDir: false,
SegInvDir: false,
HighNodeShields: true,
ShowNodeShields: false,
ShowExitShields: false,
ShowTurnTTS: false,
AlertTurnTTS: false,
ShowTowards: false,
ShowVisualInst: false,
NodeShieldMissing: false,
HighSegClr: "#0066ff",
MissSegClr: "#00ff00",
ErrSegClr: "#cc00ff",
HighNodeClr: "#ff00bf",
MissNodeClr: "#ff0000",
SegHasDirClr: "#ffff00",
SegInvDirClr: "#66ffff",
TitleCaseClr: "#ff9933",
TitleCaseSftClr: "#ffff66",
ShowRamps: true,
AlternativeShields: false,
mHPlus: false,
titleCase: false,
checkTWD: false,
checkTTS: false,
checkVI: false,
mapLayerVisible: false,
iconLayerVisible: false,
};
rsaSettings = $.extend({}, defaultSettings, localSettings);
if (serverSettings && serverSettings.lastSaveAction > rsaSettings.lastSaveAction) {
$.extend(rsaSettings, serverSettings);
// console.log('RSA: server settings used');
}
else {
// console.log('RSA: local settings used');
}
}
async function saveSettings() {
const { enableScript, HighSegShields, ShowSegShields, SegShieldMissing, SegShieldError, HighNodeShields, ShowNodeShields, ShowExitShields, SegHasDir, SegInvDir, ShowTurnTTS, AlertTurnTTS, ShowTowards, ShowVisualInst, NodeShieldMissing, HighSegClr, MissSegClr, ErrSegClr, HighNodeClr, MissNodeClr, SegHasDirClr, SegInvDirClr, TitleCaseClr, TitleCaseSftClr, ShowRamps, AlternativeShields, mHPlus, titleCase, checkTWD, checkTTS, checkVI, mapLayerVisible, iconLayerVisible, } = rsaSettings;
const localSettings = {
lastSaveAction: Date.now(),
enableScript,
HighSegShields,
ShowSegShields,
SegShieldMissing,
SegShieldError,
HighNodeShields,
ShowNodeShields,
ShowExitShields,
SegHasDir,
SegInvDir,
ShowTurnTTS,
AlertTurnTTS,
ShowTowards,
ShowVisualInst,
NodeShieldMissing,
HighSegClr,
MissSegClr,
ErrSegClr,
HighNodeClr,
MissNodeClr,
SegHasDirClr,
SegInvDirClr,
TitleCaseClr,
TitleCaseSftClr,
ShowRamps,
AlternativeShields,
mHPlus,
titleCase,
checkTWD,
checkTTS,
checkVI,
mapLayerVisible,
iconLayerVisible,
};
// Grab keyboard shortcuts and store them for saving
// for (const name in W.accelerators.Actions) {
// const {shortcut, group} = W.accelerators.Actions[name];
// if (group === 'wmersa') {
// let TempKeys = '';
// if (shortcut) {
// if (shortcut.altKey === true) {
// TempKeys += 'A';
// }
// if (shortcut.shiftKey === true) {
// TempKeys += 'S';
// }
// if (shortcut.ctrlKey === true) {
// TempKeys += 'C';
// }
// if (TempKeys !== '') {
// TempKeys += '+';
// }
// if (shortcut.keyCode) {
// TempKeys += shortcut.keyCode;
// }
// } else {
// TempKeys = '-1';
// }
// localSettings[name as keyof typeof localSettings] = TempKeys;
// }
// }
// Required for the instant update of changes to the keyboard shortcuts on the UI
rsaSettings = localSettings;
if (localStorage) {
localStorage.setItem("RSA_Settings", JSON.stringify(localSettings));
}
const serverSave = await WazeWrap.Remote.SaveSettings("RSA_Settings", localSettings);
if (serverSave === null) {
console.warn("RSA: User PIN not set in WazeWrap tab");
}
else {
if (serverSave === false) {
console.error("RSA: Unable to save settings to server");
}
}
}
function checkOptions() {
const countries = sdk.DataModel.Countries.getAll();
// const countries = W.model.countries.getObjectArray();
if (countries.length < 1) {
setTimeout(() => {
checkOptions();
}, 500);
return;
}
let allowFeat = false;
for (let i = 0; i < countries.length; i++) {
if (RoadAbbr[countries[i].id])
allowFeat = true;
}
const segShieldMissing = $("#rsa-SegShieldMissing");
const segShieldError = $("#rsa-SegShieldError");
const nodeShieldMissing = $("#rsa-NodeShieldMissing");
const textSegShieldMissing = $("#rsa-text-SegShieldMissing");
const textSegShieldError = $("#rsa-text-SegShieldError");
const textNodeShieldMissing = $("#rsa-text-NodeShieldMissing");
if (!allowFeat) {
textSegShieldMissing.prop("checked", false);
textSegShieldError.prop("checked", false);
textNodeShieldMissing.prop("checked", false);
textSegShieldMissing.text(`${Strings[LANG].SegShieldMissing} ${Strings[LANG].disabledFeat}`);
textSegShieldError.text(`${Strings[LANG].SegShieldError} ${Strings[LANG].disabledFeat}`);
textNodeShieldMissing.text(`${Strings[LANG].NodeShieldMissing} ${Strings[LANG].disabledFeat}`);
segShieldMissing.prop("disabled", true);
segShieldError.prop("disabled", true);
nodeShieldMissing.prop("disabled", true);
rsaSettings.SegShieldMissing = false;
rsaSettings.SegShieldError = false;
rsaSettings.NodeShieldMissing = false;
saveSettings();
}
else {
textSegShieldMissing.prop("checked", rsaSettings.SegShieldMissing);
textSegShieldError.prop("checked", rsaSettings.SegShieldError);
textNodeShieldMissing.prop("checked", rsaSettings.NodeShieldMissing);
textSegShieldMissing.text(Strings[LANG].SegShieldMissing);
textSegShieldError.text(Strings[LANG].SegShieldError);
textNodeShieldMissing.text(Strings[LANG].NodeShieldMissing);
segShieldMissing.prop("disabled", false);
segShieldError.prop("disabled", false);
nodeShieldMissing.prop("disabled", false);
}
const topCountry = sdk.DataModel.Countries.getTopCountry();
if (topCountry === null || topCountry.id !== 235) {
$("#rsa-container-titleCase").css("display", "none");
$("#rsa-container-TitleCaseClr").css("display", "none");
$("#rsa-container-TitleCaseSftClr").css("display", "none");
}
else {
$("#rsa-container-titleCase").css("display", "block");
$("#rsa-container-TitleCaseClr").css("display", "block");
$("#rsa-container-TitleCaseSftClr").css("display", "block");
}
}
function autoFixButton() {
$("#rsa-autoWrapper").css("display", "inline-block");
$("#rsa-autoWrapper > div").off();
// console.log(BadNames);
// Create function to fix case types when button clicked
$("#rsa-autoWrapper > div").on("click", () => {
// const turnGraph = W.model.getTurnGraph();
const turnGraph = sdk.DataModel.Turns.getAll();
for (let i = 0; i < BadNames.length; i++) {
// Check if street or turn
if (BadNames[i]) {
const strt = BadNames[i];
let dir = strt.direction;
if (dir !== null) {
if (dir.match(/\b(north)\b/i) != null)
dir = "Nᴏʀᴛʜ";
if (dir.match(/\b(south)\b/i) != null)
dir = "Sᴏᴜᴛʜ";
if (dir.match(/\b(east)\b/i) != null)
dir = "Eᴀꜱᴛ";
if (dir.match(/\b(west)\b/i) != null)
dir = "Wᴇꜱᴛ";
W.model.actionManager.add(new UpdateObj(strt, { direction: dir }));
}
}
else {
function fixName(name) {
let temp = name;
temp = temp.replace(/\b(north)\b/gi, "Nᴏʀᴛʜ");
temp = temp.replace(/\b(south)\b/gi, "Sᴏᴜᴛʜ");
temp = temp.replace(/\b(east)\b/gi, "Eᴀꜱᴛ");
temp = temp.replace(/\b(west)\b/gi, "Wᴇꜱᴛ");
temp = temp.replace(/\b(TO)\b/gi, "ᴛᴏ");
temp = temp.replace(/\b(VIA)\b/gi, "ᴠɪᴀ");
temp = temp.replace(/\b(JCT)\b/gi, "ᴊᴄᴛ");
return temp;
}
const turn = BadNames[i];
let turnDat = turn.getTurnData();
const turnGuid = turnDat.getTurnGuidance();
// let newGuid = turnGuid;
console.log(turn);
for (const s in turnGuid.roadShields) {
turnGuid.roadShields[s].direction = fixName(turnGuid.roadShields[s].direction);
}
if (rsaSettings.checkTWD && turnGuid.towards)
turnGuid.towards = fixName(turnGuid.towards);
if (rsaSettings.checkTTS && turnGuid.tts)
turnGuid.tts = fixName(turnGuid.tts);
if (rsaSettings.checkVI && turnGuid.visualInstruction)
turnGuid.visualInstruction = fixName(turnGuid.visualInstruction);
console.log(turnGuid);
turnDat = turnDat.withTurnGuidance(turnGuid);
W.model.actionManager.add(new SetTurn(turnGraph, turn.withTurnData(turnDat)));
}
}
});
}
function removeAutoFixButton() {
$("#rsa-autoWrapper > div").off();
$("#rsa-autoWrapper").css("display", "none");
}
function addShieldClick() {
// const selFea = W.selectionManager.getSelectedFeatures();
const selFea = sdk.Editing.getSelection();
if (selFea && selFea.objectType === "segment") {
$(".add-new-road-shield").trigger("click");
}
else {
WazeWrap.Alerts.error(GM_info.script.name, "You must have only 1 segment selected to use the shield editing menu");
}
}
function tryScan() {
if (!rsaSettings.enableScript)
return;
// Reset the array of objects that need names fixed
BadNames = [];
removeHighlights();
if (sdk.Map.getZoomLevel() <= MIN_ZOOM_LEVEL)
return;
// let selFea = W.selectionManager.getSelectedFeatures();
// Scan all segments on screen
if (rsaSettings.ShowSegShields ||
rsaSettings.SegShieldMissing ||
rsaSettings.SegShieldError ||
rsaSettings.HighSegShields ||
rsaSettings.titleCase) {
// _.each(W.model.segments.getObjectArray(), s => {
// scanSeg(s);
// }
for (const s of sdk.DataModel.Segments.getAll()) {
processSeg(s);
}
}
// Scan all nodes on screen
if (rsaSettings.HighNodeShields || rsaSettings.ShowNodeShields || rsaSettings.titleCase) {
const nodeSet = new Set(sdk.DataModel.Nodes.getAll());
for (const n of nodeSet) {
processNode(n);
}
}
}
const majorRoads = new Set([3, 4, 5, 6]);
function processSeg(seg) {
if ((!rsaSettings.ShowRamps && seg.roadType === 4) ||
(rsaSettings.mHPlus && !majorRoads.has(seg.roadType)))
return;
// let segAtt = seg.attributes;
// let streetID = segAtt.primaryStreetID;
// const streetID: number | null = seg.primaryStreetId;
// if (streetID === null) return;
// // let oldStreet = W.model.streets.getObjectById(streetID).attributes;
// let street: Street | null = sdk.DataModel.Streets.getById({ streetId: streetID });
// if (street === null || street.cityId === null) return;
// const city: City | null = sdk.DataModel.Cities.getById({ cityId: street.cityId });
// if (city === null) return;
// const stateID = city.stateId;
let address = sdk.DataModel.Segments.getAddress({ segmentId: seg.id });
if (rsaSettings.AlternativeShields) {
for (const altAddress of address.altStreets) {
// let oldAltStreet = W.model.streets.getObjectById(segAtt.streetIDs[i]).attributes;
if (alternativeType === "AlternativePrimaryCity") {
if (altAddress.city !== null) {
address = altAddress;
break;
}
}
if (alternativeType === "AlternativeNoCity") {
if (altAddress.city?.name === "") {
address = altAddress;
break;
}
}
}
}
// let oldStateName = W.model.states.getObjectById(cityID.stateID).attributes.name;
const stateName = address.state === null ? "" : address.state.name;
const countryID = address.country?.id;
const candidate = isSegmentCandidate(address, stateName, countryID);
// Display shield on map
function checkDeclutterSettings(seg) {
let result = false;
const zoomLevel = sdk.Map.getZoomLevel();
if (zoomLevel > MIN_ZOOM_LEVEL) {
if (seg.length > minShieldDisplayLengths[zoomLevel]) {
result = true;
}
}
return result;
}
if (address.street !== null && address.street.signType !== null) {
if (rsaSettings.ShowSegShields && checkDeclutterSettings(seg)) {
displaySegShields(seg, address.street.signType, address.street.signText, address.street.direction);
}
// If candidate and has shield
if (rsaSettings.HighSegShields && candidate.isCandidate) {
if (isValidShield(seg, candidate.iconID)) {
createHighlight(seg, rsaSettings.HighSegClr);
}
else {
createHighlight(seg, rsaSettings.ErrSegClr);
}
}
// If not candidate and has shield
if (rsaSettings.SegShieldError && !candidate.isCandidate)
createHighlight(seg, rsaSettings.ErrSegClr);
if (rsaSettings.SegHasDir && address.street?.direction)
createHighlight(seg, rsaSettings.SegHasDirClr);
// Highlight seg shields with direction
if (rsaSettings.SegInvDir && !address.street?.direction)
createHighlight(seg, rsaSettings.SegInvDirClr);
}
// If candidate and missing shield
if (rsaSettings.SegShieldMissing && candidate.isCandidate && address.street !== null && address.street.signType === null)
createHighlight(seg, rsaSettings.MissSegClr);
// Streets without capitalized letters
if (rsaSettings.titleCase) {
const badName = matchTitleCase(address.street);
if (badName) {
createHighlight(seg, rsaSettings.TitleCaseClr, true);
// autoFixButton();
}
}
}
function processNode(node) {
if (node === null)
return;
const guidance = {
tts: false,
visual: false,
exit: false,
shield: false,
towards: false,
};
const turns = sdk.DataModel.Turns.getTurnsThroughNode({ nodeId: node.id });
for (const turn of turns) {
if (!turn.isAllowed)
continue;
// let oldTurn = W.model.getTurnGraph().getTurnThroughNode(node,turn.fromSegmentId,turn.toSegmentId);
guidance.tts = guidance.tts || turn.hasCustomTTS;
guidance.shield = guidance.shield || turn.hasShieldsPopulated;
guidance.towards = guidance.towards || turn.hasTowardsGuidance;
guidance.visual = guidance.visual || turn.hasVisualInstruction;
if (rsaSettings.titleCase) {
const badName = matchTitleCaseThroughNode(turn);
if (badName.isBad) {
const color = badName.softIssue ? rsaSettings.TitleCaseSftClr : rsaSettings.TitleCaseClr;
createHighlight(node, color, true);
// autoFixButton();
}
}
}
if (rsaSettings.ShowNodeShields &&
sdk.Map.getZoomLevel() > ZoomLevel.ZM2 &&
(guidance.exit || guidance.tts || guidance.shield || guidance.visual || guidance.towards))
displayNodeIcons(node, guidance);
}
// Function written by kpouer to accommodate French conventions of shields being based on alt names
function isSegmentCandidate(address, stateName, countryId) {
let candidate = isStreetCandidate(address.street, stateName, countryId);
if (!candidate.isCandidate && address.country !== null && address.country?.id !== undefined && CheckAltName.has(address.country.id)) {
for (const altAddress of address.altStreets) {
candidate = isStreetCandidate(altAddress.street, stateName, countryId);
if (candidate.isCandidate) {
return candidate;
}
}
}
return candidate;
}
function isStreetCandidate(street, stateName, countryId) {
const info = { isCandidate: false, iconID: null };
if (street === null || countryId === null || countryId === undefined || !RoadAbbr[countryId]) {
return info;
}
// if (stateName === null) stateName = "";
//Check to see if the country has states configured in RSA by looking for a key with nothing in it
if (street.name) {
const noStates = "" in RoadAbbr[countryId];
const abbrvs = noStates
? RoadAbbr[countryId][""]
: { ...RoadAbbr[countryId][stateName], ...RoadAbbr[countryId]["*"] };
const abbreviationKeys = Object.keys(abbrvs);
for (let i = 0; i < abbreviationKeys.length; i++) {
const abrKey = abbreviationKeys[i];
const abbr = new RegExp(abrKey, "g");
const isMatch = street.name.match(abbr);
if (isMatch && street.name.includes(isMatch[0])) {
info.isCandidate = true;
info.iconID = abbrvs[abrKey];
break;
}
}
}
return info;
}
function iconTextValidation(signType, signText, iconId) {
let result = true;
if (signType === null ||
typeof signType === "undefined" ||
typeof signText === "undefined" ||
(iconId instanceof Set && !iconId.has(signType)) ||
(!(iconId instanceof Set) && signType !== iconId)) {
result = false;
}
if (signType !== null &&
!iconsAllowingNoText.has(signType) &&
(signText === null || typeof signText === "undefined" || signText === "")) {
result = false;
}
return result;
}
function isValidShield(seg, iconID) {
// let primaryStreet = W.model.streets.getObjectById(segAtt.primaryStreetID);
if (seg === null || seg.primaryStreetId === null)
return false;
const primaryStreet = sdk.DataModel.Streets.getById({ streetId: seg.primaryStreetId });
if (primaryStreet === null ||
primaryStreet.signText === null ||
!iconTextValidation(primaryStreet.signType, primaryStreet.signText, iconID))
return false;
if (primaryStreet.name?.includes(primaryStreet.signText)) {
return true;
}
for (let i = 0; i < seg.alternateStreetIds.length; i++) {
const street = sdk.DataModel.Streets.getById({ streetId: seg.alternateStreetIds[i] });
if (street?.name?.includes(primaryStreet.signText)) {
return true;
}
}
return false;
}
function matchTitleCase(street) {
if (!street)
return;
const dir = street.direction;
let isBad = false;
if (dir !== "" && dir !== null) {
// console.log(dir);
if (dir.match(/\\b(north|south|east|west)\\b/i) !== null)
isBad = true;
if (dir.match(/([ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘʀꜱᴛᴜᴠᴡʏᴢ][a-z]|[a-z][ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘʀꜱᴛᴜᴠᴡʏᴢ])/) !== null)
isBad = true;
if (isBad) {
if (BadNames.length === 0) {
BadNames.push(street);
}
else {
let isDuplicate = false;
for (let i = 0; i < BadNames.length; i++) {
// if (BadNames[i].type) console.log(BadNames[i].id === street.id);
if (typeof BadNames[i] && BadNames[i].id === street.id)
isDuplicate = true;
}
if (!isDuplicate)
BadNames.push(street);
}
}
}
return isBad;
}
function matchTitleCaseThroughNode(turn) {
const info = { isBad: false, softIssue: false };
return info;
const turnGuid = turnData.getTurnGuidance();
const shields = turnGuid.getRoadShields();
const twd = turnGuid.getTowards();
const tts = turnGuid.getTTS();
const VI = turnGuid.getVisualInstruction();
function checkText(txt, isSoft = false) {
if (txt !== "" && txt !== null) {
if (txt.match(/\b(north|south|east|west)\b/i) != null) {
info.isBad = true;
if (isSoft)
info.softIssue = true;
}
if (txt.match(/\b(TO|VIA|JCT)\b/i) != null) {
info.isBad = true;
if (isSoft)
info.softIssue = true;
}
if (txt.match(/([ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘʀꜱᴛᴜᴠᴡʏᴢ][a-z]|[a-z][ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘʀꜱᴛᴜᴠᴡʏᴢ])/) != null) {
info.isBad = true;
if (isSoft)
info.softIssue = true;
}
}
}
function checkTTStext(txt, isSoft = false) {
if (txt !== "" && txt !== null) {
if (txt.match(/(Nᴏʀᴛʜ|Sᴏᴜᴛʜ|Eᴀꜱᴛ|Wᴇꜱᴛ)/) != null) {
info.isBad = true;
if (isSoft)
info.softIssue = true;
}
if (txt.match(/(ᴛᴏ|ᴠɪᴀ|ᴊᴄᴛ)/) != null) {
info.isBad = true;
if (isSoft)
info.softIssue = true;
}
if (txt.match(/([ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘʀꜱᴛᴜᴠᴡʏᴢ][a-z]|[a-z][ᴀʙᴄᴅᴇꜰɢʜɪᴊᴋʟᴍɴᴏᴘʀꜱᴛᴜᴠᴡʏᴢ])/) != null) {
info.isBad = true;
if (isSoft)
info.softIssue = true;
}
}
}
if (shields) {
_.each(shields, (s) => {
checkText(s.direction);
});
}
if (twd && twd !== "" && rsaSettings.checkTWD)
checkText(twd, true);
if (tts && tts !== "" && rsaSettings.checkTTS)
checkTTStext(tts, true);
if (VI && VI !== "" && rsaSettings.checkVI)
checkText(VI, true);
if (info.isBad)
BadNames.push(turn);
return info;
}
function displayNodeIcons(node, guidance) {
const GUIDANCE = {
shields: {
setting: "ShowNodeShields",
exists: guidance.shield,
color: "",
width: 30,
height: 30,
sign: "6",
txt: "TG",
},
exitsign: {
setting: "ShowExitShields",
exists: guidance.exit,
color: "",
width: 30,
height: 20,
sign: "2159",
txt: "EX",
},
tts: {
setting: "ShowTurnTTS",
exists: guidance.tts,
color: "",
width: 30,
height: 30,
sign: "7",
txt: "TIO",
},
towards: {
setting: "ShowTowards",
exists: guidance.towards,
color: "",
width: 30,
height: 30,
sign: "7",
txt: "TW",
},
visualIn: {
setting: "ShowVisualInst",
exists: guidance.visual,
color: "",
width: 30,
height: 30,
sign: "7",
txt: "VI",
},
};
let count = 0;
const pixelPos = proj4("EPSG:4326", "EPSG:3857", node.geometry.coordinates);
const startPoint = { x: pixelPos[0], y: pixelPos[1] };
const lblStart = { x: startPoint.x - labelDistance().label, y: startPoint.y + labelDistance().label };
// Array of points for line connecting node to icons
const points = [];
const pointCoordinates = [];
// Point coords
// let pointNode = new OpenLayers.Geometry.Point(startPoint.x, startPoint.y);
const pointNode = turf.point(node.geometry.coordinates, {
styleName: "styleNode",
style: {
strokeColor: rsaSettings.HighNodeClr,
strokeOpacity: 0.75,
strokeWidth: 4,
fillColor: rsaSettings.HighNodeClr,
fillOpacity: 0.75,
pointRadius: 3,
},
}, { id: `node_${startPoint.x} ${startPoint.y}` });
points.push(pointNode);
pointCoordinates.push(node.geometry.coordinates);
// Label coords
// var pointLabel = new OpenLayers.Geometry.Point(lblStart.x, lblStart.y);
const nodeLabelCoordinates = proj4("EPSG:3857", "EPSG:4326", [lblStart.x, lblStart.y]);
const nodeLabel = turf.point(nodeLabelCoordinates, {
styleName: "styleNode",
style: {
strokeColor: rsaSettings.HighNodeClr,
strokeOpacity: 0.75,
strokeWidth: 4,
fillColor: rsaSettings.HighNodeClr,
fillOpacity: 0.75,
pointRadius: 3,
},
}, { id: `pointNode_${startPoint.x} ${startPoint.y}` });
points.push(nodeLabel);
pointCoordinates.push(nodeLabelCoordinates);
sdk.Map.addFeaturesToLayer({ features: points, layerName: rsaMapLayer.layerName });
const newLine = turf.lineString(pointCoordinates, {
styleName: "styleNode",
style: {
strokeColor: rsaSettings.HighNodeClr,
strokeOpacity: 0.75,
strokeWidth: 4,
fillColor: rsaSettings.HighNodeClr,
fillOpacity: 0.75,
pointRadius: 3,
},
}, { id: `line_${points[0].toString()}` });
sdk.Map.addFeatureToLayer({ feature: newLine, layerName: rsaIconLayer.layerName });
_.each(GUIDANCE, (q) => {
if (q.exists && rsaSettings[q.setting]) {
// console.log(q);
let xpoint = lblStart.x;
let ypoint = lblStart.y;
const lblDis = labelDistance();
switch (count) {
case 1:
xpoint = lblStart.x + lblDis.icon;
ypoint = lblStart.y;
break;
case 2:
xpoint = lblStart.x;
ypoint = lblStart.y - lblDis.icon;
break;
case 3:
xpoint = lblStart.x + lblDis.icon;
ypoint = lblStart.y - lblDis.icon;
break;
case 4:
xpoint = lblStart.x + lblDis.icon * 2;
ypoint = lblStart.y;
break;
default:
break;
}
// Label coords
// let pointLabel = new OpenLayers.Geometry.Point(xpoint, ypoint);
// labelFeat = new OpenLayers.Feature.Vector(pointLabel, null, styleLabel);
const pointLabelFeature = turf.point(proj4("EPSG:3857", "EPSG:4326", [xpoint, ypoint]), {
styleName: "styleLabel",
style: { sign: q.sign, txt: q.txt, height: q.height, width: q.width, fillOpacity: 1 },
}, { id: `pointLabel_${xpoint.toString()}_${ypoint.toString()}` });
sdk.Map.addFeatureToLayer({ feature: pointLabelFeature, layerName: rsaIconLayer.layerName });
count++;
}
});
}
function displaySegShields(segment, shieldID, shieldText, shieldDir) {
const iconURL = `https://renderer-am.waze.com/renderer/v1/signs/${shieldID}?text=${shieldText}`;
// let SegmentPoints = [];
const oldparam = { x: null, y: null };
const labelDis = labelDistance();
let width = 37;
let height = 37;
if (shieldText !== null) {
if (shieldText.length > 4 && shieldText.length < 7) {
width = 50;
height = 40;
}
else if (shieldText.length > 6 && shieldText.length < 9) {
width = 80;
height = 45;
}
else if (shieldText.length > 8 && shieldText.length < 13) {
width = 100;
height = 50;
}
}
// oldparam.x = null;
// oldparam.y = null;
let AtLeastOne = false;
$.each(segment.geometry.coordinates, (idx, param) => {
const pointParam = proj4("EPSG:4326", "EPSG:3857", param);
// Build a new segment with same geometry
// SegmentPoints.push(new OpenLayers.Geometry.Point(param[0], param[1]));
// let newPoint = {
// type: "Feature",
// geometry: {
// type: "Point",
// coordinates: [param[0], param[1]],
// },
// id: "point_" + param[0].toString() + " " + param[1].toString(),
// };
// SegmentPoints.push(newPoint);
// let shieldWithLabelStyle = {
// externalGraphic: iconURL,
// graphicWidth: width,
// graphicHeight: height,
// graphicYOffset: -20,
// // graphicZIndex: 6000,
// style: "opacity: 1",
// fillOpacity: 1,
// fill: "black",
// stroke: "black",
// label: shieldDir !== null ? shieldDir : "",
// fontColor: "green",
// labelOutlineColor: "white",
// labelOutlineWidth: 1,
// fontSize: 12,
// display: "grid",
// labelYOffset: 0,
// };
if (oldparam.x && oldparam.y && oldparam.x !== null && oldparam.y !== null) {
if (Math.abs(oldparam.x - pointParam[0]) > labelDis.space ||
Math.abs(oldparam.y - pointParam[1]) > labelDis.space ||
!AtLeastOne) {
const centerparam = { x: undefined, y: undefined };
centerparam.x = (oldparam.x + pointParam[0]) / 2;
centerparam.y = (oldparam.y + pointParam[1]) / 2;
if ((centerparam.x && Math.abs(centerparam.x - pointParam[0]) > labelDis.space) ||
(centerparam.y && Math.abs(centerparam.y - pointParam[1]) > labelDis.space) ||
!AtLeastOne) {
// let LabelPoint = new OpenLayers.Geometry.Point(centerparam.x, centerparam.y);
// const pointFeature = new OpenLayers.Feature.Vector(LabelPoint, null, style);
const coordCenterPoint = proj4("EPSG:3857", "EPSG:4326", [centerparam.x, centerparam.y]);
const shieldFeature = turf.point(coordCenterPoint, {
styleName: "shield",
style: {
externalGraphic: iconURL,
graphicWidth: width,
graphicHeight: height,
label: shieldDir !== null ? shieldDir : "",
labelYOffset: shieldDir !== null ? -20 : 0,
},
}, { id: `shield_${centerparam.x.toString()}_${centerparam.y.toString()}` });
// Shield icon style
// shieldWithLabelStyle.labelYOffset = -1 * labelDis.label;
sdk.Map.addFeatureToLayer({ feature: shieldFeature, layerName: rsaIconLayer.layerName });
AtLeastOne = true;
}
}
}
oldparam.x = pointParam[0];
oldparam.y = pointParam[1];
});
}
function createHighlight(obj, color, overSized = false) {
// const geo = obj.getOLGeometry().clone();
const geo = structuredClone(obj.geometry);
const isNode = obj instanceof Node;
if (isNode) {
// Point coords
// let pointNode = new OpenLayers.Geometry.Point(geo.x, geo.y);
const pointFeature = turf.point(geo.coordinates, {
styleName: "styleNode",
style: {
strokeColor: color,
strokeOpacity: overSized ? 1 : 0.75,
strokeWidth: 4,
fillColor: color,
fillOpacity: 0.75,
pointRadius: overSized ? 7 : 3,
},
}, { id: `point_${geo.coordinates[0]}_${geo.coordinates[1]}` });
sdk.Map.addFeatureToLayer({ feature: pointFeature, layerName: rsaIconLayer.layerName });
}
else {
// console.log('seg highlight')
// Object.assign(styleRules.segHighlight.style, {
// strokeColor: color,
// strokeOpacity: overSized ? 1 : 0.75,
// strokeWidth: overSized ? 7 : 4,
// fillColor: color,
// fillOpacity: 0.75,
// });
// const newFeat = new OpenLayers.Geometry.LineString(geo.components, {});
// const newVector = new OpenLayers.Feature.Vector(newFeat, null, style);
// rsaMapLayer.addFeatures([newVector]);
const newLineFeature = turf.lineString(geo.coordinates, {
styleName: "segHighlight",
style: {
strokeColor: color,
strokeOpacity: overSized ? 1 : 0.75,
strokeWidth: overSized ? 7 : 4,
fillColor: color,
fillOpacity: 0.75,
},
}, { id: `line_${geo}` });
sdk.Map.addFeatureToLayer({ feature: newLineFeature, layerName: rsaMapLayer.layerName });
}
}
function removeHighlights() {
sdk.Map.removeAllFeaturesFromLayer(rsaMapLayer);
sdk.Map.removeAllFeaturesFromLayer(rsaIconLayer);
}
function labelDistance() {
// Return object with two variables - label is the distance used to place the direction below the icon,
// space is the space between geo points needed to render another icon
const label_distance = { icon: 0, label: 0, space: 0 };
switch (sdk.Map.getZoomLevel()) {
case ZoomLevel.ZM10:
label_distance.label = 2;
label_distance.space = 30;
label_distance.icon = 1.1;
break;
case ZoomLevel.ZM9:
label_distance.label = 4;
label_distance.space = 30;
label_distance.icon = 2.2;
break;
case ZoomLevel.ZM8:
label_distance.label = 8;
label_distance.space = 30;
label_distance.icon = 4.5;
break;
case ZoomLevel.ZM7:
label_distance.label = 14;
label_distance.space = 30;
label_distance.icon = 8.3;
break;
case ZoomLevel.ZM6:
label_distance.label = 28;
label_distance.space = 30;
label_distance.icon = 17;
break;
case ZoomLevel.ZM5:
label_distance.label = 50;
label_distance.space = 30;
label_distance.icon = 34;
break;
case ZoomLevel.ZM4:
label_distance.label = 100;
label_distance.space = 40;
label_distance.icon = 68;
break;
case ZoomLevel.ZM3:
label_distance.label = 300;
label_distance.space = 70;
label_distance.icon = 140;
break;
case ZoomLevel.ZM2:
label_distance.label = 300;
label_distance.space = 200;
label_distance.icon = 140;
break;
case ZoomLevel.ZM1:
label_distance.label = 300;
label_distance.space = 250;
label_distance.icon = 140;
break;
}
return label_distance;
}
initRSA();
}