WME LevelReset +

Fork of the original script. The WME LevelReset tool, to make re-locking segments and POI to their appropriate lock level easy & quick. Supports major road types and custom locking rules for specific cities.

当前为 2025-05-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME LevelReset +
  3. // @version 2025.05.02.001
  4. // @description Fork of the original script. The WME LevelReset tool, to make re-locking segments and POI to their appropriate lock level easy & quick. Supports major road types and custom locking rules for specific cities.
  5. // @author Broos Gert '2015, madnut
  6. // @match https://beta.waze.com/*editor*
  7. // @match https://www.waze.com/*editor*
  8. // @exclude https://www.waze.com/*user/*editor/*
  9. // @namespace https://greasyfork.org/uk/users/160654-waze-ukraine
  10. // @connect google.com
  11. // @connect script.googleusercontent.com
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM_addStyle
  14. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAA+VBMVEX///93PgHX19fTgQfFZgLLcwTrxYDDgA3nqBj5+fmwr6+Yl5f8/PzExMTl5eX114vv7+/e3t68vLzOzs6saRKARQSLTgeioqK2tbX72XfU1NT515fxz4b54b3RmySYWAv31aTpwIHgrn9/f3/75qPZsEvuuC/utx3psVP13KizbhXuuVj745bfoEzzwzDxwDXTjknpxqDPfhzWih7PhUaObErowqDJchrmqCfprRjbmUvblCLZjAv71WnhnyTfmA7hrmbjsm7qxpPv06vYljj305776MvLkD3XkjFwcHCMi4v6zk/6z1P2wVDYqzr3y3j2xWnrrl761X3u0VhGAAABv0lEQVQ4jZWTXXuaMBiGY7bZQUhIoBaKsIK0KkVqtd+2tJ2gnVJs9f//mAW78uHYwe6TXE+em/flJAD8D0RVdF3HTKqvGcaMAiAQVYd1vaEASikhhFKA1ZoeA8Iwct2lCAnAxl/zdcAMbeGipbtwMQM62xFEFUJtoWEIsbh0CVTF3QGqqrjax2cq4kkkFQFjTJD2eYeXBoa4uoEoBOU/RhBUWHWHJukUCZ9JQFCnWkVAQJRQniREyvGPANA/YzazRhBKwjSOg+DZmdoRZ+r8XAfxr5eo1AfzuW1HljXfYkX2zJ5b8TQXXtbWzPff38x2hvn27qf+zFrHubC39tppGoabjczZHIZpmra9/jgXTn2vnSTJaxgecsLwNRkmsueflgV5eLZarU4y+Lk6G9YIg8HxB4PBYEfY3woZQ0529rjQ3y+Evid3ez9K9LpmWTjqe2b3Ti5xlwlHhRDYzdvvFW5NOyiEAy48Pu2VeHps2sFBIUwi5/6hWeLh3okmhdCajJyLLxUunNGktS0lgdLW+agz/lZh3Bmdt6ggZS/NUBqX152brxVuOteXDZVRafsUrxq1XGHIBb6CwHoY4Tt+A1eiQ8S/AAv7AAAAAElFTkSuQmCC
  15. // ==/UserScript==
  16.  
  17. /* jshint esversion: 11 */
  18. /* global W */
  19. /* global $ */
  20. /* global require */
  21.  
  22. // initialize LevelReset and do some checks
  23. function LevelReset_bootstrap() {
  24. if (W?.userscripts?.state.isReady) {
  25. LevelReset_init();
  26. } else {
  27. document.addEventListener("wme-ready", LevelReset_init, {
  28. once: true
  29. });
  30. }
  31. }
  32.  
  33. function LevelReset_init() {
  34. // Setting up global variables
  35. const lrStyle = [
  36. '.tg { border-collapse: collapse; border-spacing: 0; margin: 0px auto; }',
  37. '.tg td { border-color: black; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 2px; word-break: normal; }',
  38. '.tg .tg-value { text-align: center; vertical-align: top }',
  39. '.tg .tg-header { background-color: #ecf4ff; border-color: #000000; font-weight: bold; text-align: center; vertical-align: top }',
  40. '.tg .tg-type { text-align: left; vertical-align: top }',
  41. ''];
  42. GM_addStyle(lrStyle.join('\n'));
  43.  
  44. const UpdateObject = require("Waze/Action/UpdateObject");
  45. const VERSION = GM_info.script.version;
  46. const loader = 'data:image/gif;base64,R0lGODlhEAAQAPQAAP///wAAAPj4+Dg4OISEhAYGBiYmJtbW1qioqBYWFnZ2dmZmZuTk5JiYmMbGxkhISFZWVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAAFUCAgjmRpnqUwFGwhKoRgqq2YFMaRGjWA8AbZiIBbjQQ8AmmFUJEQhQGJhaKOrCksgEla+KIkYvC6SJKQOISoNSYdeIk1ayA8ExTyeR3F749CACH5BAAKAAEALAAAAAAQABAAAAVoICCKR9KMaCoaxeCoqEAkRX3AwMHWxQIIjJSAZWgUEgzBwCBAEQpMwIDwY1FHgwJCtOW2UDWYIDyqNVVkUbYr6CK+o2eUMKgWrqKhj0FrEM8jQQALPFA3MAc8CQSAMA5ZBjgqDQmHIyEAIfkEAAoAAgAsAAAAABAAEAAABWAgII4j85Ao2hRIKgrEUBQJLaSHMe8zgQo6Q8sxS7RIhILhBkgumCTZsXkACBC+0cwF2GoLLoFXREDcDlkAojBICRaFLDCOQtQKjmsQSubtDFU/NXcDBHwkaw1cKQ8MiyEAIfkEAAoAAwAsAAAAABAAEAAABVIgII5kaZ6AIJQCMRTFQKiDQx4GrBfGa4uCnAEhQuRgPwCBtwK+kCNFgjh6QlFYgGO7baJ2CxIioSDpwqNggWCGDVVGphly3BkOpXDrKfNm/4AhACH5BAAKAAQALAAAAAAQABAAAAVgICCOZGmeqEAMRTEQwskYbV0Yx7kYSIzQhtgoBxCKBDQCIOcoLBimRiFhSABYU5gIgW01pLUBYkRItAYAqrlhYiwKjiWAcDMWY8QjsCf4DewiBzQ2N1AmKlgvgCiMjSQhACH5BAAKAAUALAAAAAAQABAAAAVfICCOZGmeqEgUxUAIpkA0AMKyxkEiSZEIsJqhYAg+boUFSTAkiBiNHks3sg1ILAfBiS10gyqCg0UaFBCkwy3RYKiIYMAC+RAxiQgYsJdAjw5DN2gILzEEZgVcKYuMJiEAOwAAAAAAAAAAAA==';
  47.  
  48. const defaultLocks = {
  49. Street: 1,
  50. Primary: 1,
  51. Minor: 2,
  52. Major: 3,
  53. Ramp: 4,
  54. Freeway: 4,
  55. POI: 1,
  56. Railroad: 1,
  57. Private: 1,
  58. Parking: 1,
  59. Offroad: 1,
  60. Narrow: 1,
  61. Boardwalk: 1,
  62. Trail: 1,
  63. Stairway: 1
  64. };
  65. const streets = {
  66. // fake element to show POI's locks
  67. 90000: {
  68. typeName: "POI",
  69. scan: true
  70. },
  71. // normal streets
  72. 17: {
  73. typeName: "Private",
  74. scan: true
  75. },
  76. 20: {
  77. typeName: "Parking",
  78. scan: true
  79. },
  80. 8: {
  81. typeName: "Offroad",
  82. scan: true
  83. },
  84. 1: {
  85. typeName: "Street",
  86. scan: true
  87. },
  88. 2: {
  89. typeName: "Primary",
  90. scan: true
  91. },
  92. 7: {
  93. typeName: "Minor",
  94. scan: true
  95. },
  96. 6: {
  97. typeName: "Major",
  98. scan: true
  99. },
  100. 4: {
  101. typeName: "Ramp",
  102. scan: true
  103. },
  104. 3: {
  105. typeName: "Freeway",
  106. scan: true
  107. },
  108. 18: {
  109. typeName: "Railroad",
  110. scan: true
  111. },
  112. 22: {
  113. typeName: "Narrow",
  114. scan: true
  115. },
  116. 10: {
  117. typeName: "Boardwalk",
  118. scan: true
  119. },
  120. 5: {
  121. typeName: "Trail",
  122. scan: true
  123. },
  124. 16: {
  125. typeName: "Stairway",
  126. scan: true
  127. }
  128. };
  129. let relockObject = {};
  130. const userlevel = W.loginManager.getUserRank() + 1;
  131. //const userlevel = 6; // for testing purposes (NOTE: this does not enable you to lock higher!)
  132.  
  133. const requestsTimeout = 20000; // in ms
  134. const rulesHash = "AKfycbzKgUQL7cY6XMBlykq0JzJAPc1B26sKEAnG1RJokA9Wpgf_W0oZJwMKcrhA13LrUbvj";
  135. let rulesDB = {};
  136.  
  137. // Some functions
  138. function onScreen(obj) {
  139. if (obj && typeof obj.getOLGeometry === 'function') {
  140. return (W.map.getOLMap().getExtent().intersectsBounds(obj.getOLGeometry().getBounds()));
  141. }
  142. return (false);
  143. }
  144.  
  145. function hasPendingUR(poi) {
  146. return (poi.attributes.venueUpdateRequests.length > 0);
  147. }
  148.  
  149. function displayHtmlPage(res) {
  150. if (res.responseText.match(/Authorization needed/) || res.responseText.match(/ServiceLogin/)) {
  151. alert("LevelReset:\n" +
  152. "Authorization is required for using this script. This is one time action.\n" +
  153. "Now you will be redirected to the authorization page, where you'll need to approve request.\n" +
  154. "After confirmation, please close the page and reload WME.");
  155. }
  156. let w = window.open();
  157. w.document.open();
  158. w.document.write(res.responseText);
  159. w.document.close();
  160. w.location = res.finalUrl;
  161. }
  162.  
  163. function sendHTTPRequest(url, callback) {
  164. GM_xmlhttpRequest({
  165. url: url,
  166. method: 'GET',
  167. timeout: requestsTimeout,
  168. onload: function (res) {
  169. callback(res);
  170. },
  171. onreadystatechange: function (res) {
  172. // fill if needed
  173. },
  174. ontimeout: function (res) {
  175. alert("LevelReset: Sorry, request timeout!");
  176. },
  177. onerror: function (res) {
  178. alert("LevelReset: Sorry, request error!");
  179. }
  180. });
  181. }
  182.  
  183. function validateHTTPResponse(res) {
  184. let result = false,
  185. displayError = true;
  186. if (res) {
  187. switch (res.status) {
  188. case 200:
  189. displayError = false;
  190. if (res.responseHeaders.match(/content-type:\s*application\/json/i)) {
  191. result = true;
  192. } else if (res.responseHeaders.match(/content-type:\s*text\/html/i)) {
  193. displayHtmlPage(res);
  194. }
  195. break;
  196. default:
  197. displayError = false;
  198. alert("LevelReset Error: unsupported status code - " + res.status);
  199. console.log("LevelReset: " + res.responseHeaders);
  200. console.log("LevelReset: " + res.responseText);
  201. break;
  202. }
  203. } else {
  204. displayError = false;
  205. alert("LevelReset error: Response is empty!");
  206. }
  207.  
  208. if (displayError) {
  209. alert("LevelReset: Error processing request. Response: " + res.responseText);
  210. }
  211. return result;
  212. }
  213.  
  214. function getAllLockRules() {
  215. function requestCallback(res) {
  216. if (validateHTTPResponse(res)) {
  217. let out = JSON.parse(res.responseText);
  218. if (out.result == "success") {
  219. initUI(out.rules);
  220. } else {
  221. alert("LevelReset: Error getting locking rules!");
  222. }
  223. } else {
  224. console.warning("LevelReset: can't get locking rules, invalid response!");
  225. }
  226. }
  227.  
  228. const url = 'https://script.google.com/macros/s/' + rulesHash + '/exec?func=getAllLockRules';
  229. sendHTTPRequest(url, requestCallback);
  230. }
  231.  
  232. function initUI(rules) {
  233. let relockContent = document.createElement('div'),
  234. relockTitle = document.createElement('wz-overline'),
  235. relockSubTitle = document.createElement('wz-label'),
  236. rulesSubTitle = document.createElement('wz-label'),
  237. relockAllbutton = document.createElement('input'),
  238. relockSub = document.createElement('p'),
  239. versionTitle = document.createElement('wz-label'),
  240. resultsCntr = document.createElement('div'),
  241. rulesCntr = document.createElement('div'),
  242. alertCntr = document.createElement('div'),
  243. hidebutton = document.createElement('div'),
  244. dotscntr = document.createElement('div'),
  245. inputDiv1 = document.createElement('div'),
  246. inputDiv2 = document.createElement('div'),
  247. includeAllSegments = document.createElement('input'),
  248. includeAllSegmentsLabel = document.createElement('label'),
  249. respectRouting = document.createElement('input'),
  250. respectRoutingLabel = document.createElement('label'),
  251. percentageLoader = document.createElement('div');
  252.  
  253. rulesDB = rules;
  254.  
  255. // Begin building
  256. relockTitle.appendChild(document.createTextNode('Re-lock Segments & POI'));
  257.  
  258. // fill tab
  259. relockSub.innerHTML = 'Your on-screen area is automatically scanned when you load or pan around. Pressing the lock behind each type will relock only those results, or you can choose to relock all.<br/><br/>You can only relock segments lower or equal to your current editor level. Segments locked higher than normal are left alone.';
  260. relockSub.style.cssText = 'font-size:85%;padding:15px;border:1px solid red;border-radius:5px;position:relative';
  261. relockSub.id = 'sub';
  262. hidebutton.style.cssText = 'cursor:pointer;width:16px;height:16px;position:absolute;right:3px;top:3px;background-image:url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAAWdEVYdENyZWF0aW9uIFRpbWUAMTEvMjAvMTVnsXrkAAADTUlEQVQ4jW2TW0xbZQCAv3ODnpYWegEGo1wKwzBcxAs6dONSjGMm3kjmnBqjYqLREE2WLDFTIBmbmmxRpzHy4NPi4zRLfNBlZjjtnCEaOwYDJUDcVqC3UzpWTkt7fp80hvk9f/nePkkIwWb+gA5jMXLQjK50Zc2cuKVp4wlX2UevtAYubnal/waWoTI1N38keu7ck2uTl335ZFJCkpE8XlGob4ibgeZvMl7P8MtdO6/dFohDe/Sn0LdzJ457MuHfUYqLkYtsSIqMJASyIiNv30Gm6+G1zNbqvpf6gqF/AwaUXx+/MDdz6KArH4ujVVRAbgPVroMsQz6P6nJiGUnUGj/pR/tTyx2dtW+11t2UAa5Pz34w//GHLitpsG1wkODp0xQ11GOZJpgmzq5uqo8ew76zAxFPUDJxscwzFR4BkGfh/tj58/3Zq9OoFZU0PHsAd00NnWNj6IEApd3duA48g2nXKenpQSl1oceWsUeuPfdp+M9GZf/zA5+lz3x9lxRbAUli+dIlKnt7Ud1uCk1NJH0+VnMmq6EQfw0NUzCSULBQfT4HVf4iNRO50VlIGSi6jup0sj5zlTO7d9N48iRLa2vkCwWsyTArbx/GAaSBm/MLyLm85OjZs0c2zawQsoRmt5NeXCRyeRLh9rBkGBSEwF6i09h+L96GemyAx2bDK4ENkGRJkbM2fVy4PRhT08RmZvH09VE29C6ixEFuahL3hklLby9PhEKUt7VRZln4kHD669Bqtl6Q7W07jqWL9FQiEkHTdUoGBsgXF5EPh0m8M8Tc62/CSoLSqmqaR4ZxaRpenxfbgw8lCy2Nx5Uv3xuNXEll7shO/HI38Rjr09NImkriyCgOy0JZTZM4+x3C7SY+epTaLZWsdwXJPNV/6jF/9ReSEIKzmcKWpbHPF9OHDxUr6xksoAiQJAmnpuEWAqeq4G9uRr7nPpZeeDG10NqybV+5Ly4DPGJXlsv79u51v38iK22/EwmwACEEIpdD2tjApmncan8A49XX4qtNgeC+cl/8tpm+jxoBY+K3N7I/jj+dvxKuIhZV7KpKWV295dy1K6YEg1/NO2wj+/210f+98R9+hub0wo1BOZnslRVV16orf0hVeD55HH7d7P4N0V1gY9/zcaEAAAAASUVORK5CYII=\');';
  263. hidebutton.onclick = function () {
  264. localStorage.msgHide = 1;
  265. $('#sub').hide('slow');
  266. };
  267. dotscntr.style.cssText = 'width:16px;height:16px;margin-left:5px;background:url("' + loader + '");vertical-align:text-top;display:none';
  268. dotscntr.id = 'dotscntr';
  269. relockSubTitle.innerHTML = 'Results';
  270. relockSubTitle.id = 'reshdr';
  271. rulesSubTitle.innerHTML = 'Active rules';
  272. versionTitle.innerHTML = 'Version ' + VERSION;
  273. relockAllbutton.id = 'rlkall';
  274. relockAllbutton.type = 'button';
  275. relockAllbutton.value = 'Relock All';
  276. relockAllbutton.style.cssText = 'margin: 10px 3px 0 0';
  277. relockAllbutton.onclick = function () {
  278. relockAll();
  279. };
  280.  
  281. // Also reset higher locked segments?
  282. includeAllSegments.type = 'checkbox';
  283. includeAllSegments.name = "name";
  284. includeAllSegments.value = "value";
  285. includeAllSegments.checked = (localStorage.getItem('Relock_allSegments') == 'true');
  286. includeAllSegments.id = "_allSegments";
  287. includeAllSegments.onclick = function () {
  288. localStorage.setItem('Relock_allSegments', includeAllSegments.checked.toString());
  289. scanArea();
  290. relockShowAlert();
  291. };
  292. includeAllSegmentsLabel.htmlFor = "_allSegments";
  293. includeAllSegmentsLabel.innerHTML = 'Also reset higher locked objects';
  294. includeAllSegmentsLabel.style.cssText = 'font-size:95%;margin-left:5px;vertical-align:middle';
  295.  
  296. // Respect routing road type
  297. respectRouting.type = 'checkbox';
  298. respectRouting.name = "name";
  299. respectRouting.value = "value";
  300. respectRouting.checked = (localStorage.getItem('Relock_respectRouting') == 'true');
  301. respectRouting.id = "_respectRouting";
  302. respectRouting.onclick = function () {
  303. localStorage.setItem('Relock_respectRouting', respectRouting.checked.toString());
  304. scanArea();
  305. };
  306. respectRoutingLabel.htmlFor = "_respectRouting";
  307. respectRoutingLabel.innerHTML = 'Respect routing road type';
  308. respectRoutingLabel.style.cssText = 'font-size:95%;margin-left:5px;vertical-align:middle';
  309.  
  310. resultsCntr.style.cssText = 'margin-right:5px;';
  311.  
  312. // add results empty list
  313. $.each(streets, function (key, value) {
  314. let __cntr = document.createElement('div'),
  315. __keyLeft = document.createElement('div'),
  316. __prntRight = document.createElement('div'),
  317. __cntRight = document.createElement('div'),
  318. __cleardiv = document.createElement("div"),
  319. __chkLeft = document.createElement('input'),
  320. __lblLeft = document.createElement('label');
  321. let idPrefix = 'Relock_' + value.typeName + '_';
  322.  
  323. // Begin building
  324. __keyLeft.style.cssText = 'float:left';
  325.  
  326. __chkLeft.type = 'checkbox';
  327. __chkLeft.checked = (localStorage.getItem(idPrefix + 'chk') == 'true');
  328. __chkLeft.id = idPrefix + 'chk';
  329. __chkLeft.onclick = function () {
  330. localStorage.setItem(idPrefix + 'chk', __chkLeft.checked.toString());
  331. scanArea();
  332. };
  333. __lblLeft.htmlFor = idPrefix + 'chk';
  334. __lblLeft.innerHTML = value.typeName;
  335. __lblLeft.style.cssText = 'margin-bottom:0px;font-weight:normal;';
  336.  
  337. __keyLeft.appendChild(__chkLeft);
  338. __keyLeft.appendChild(__lblLeft);
  339.  
  340. __cntRight.style.cssText = 'float:right';
  341. __cntRight.innerHTML = '-';
  342.  
  343. __prntRight.id = idPrefix + 'value';
  344. __prntRight.style.cssText = 'float:right';
  345. __prntRight.appendChild(__cntRight);
  346.  
  347. __cleardiv.style.cssText = 'clear:both;';
  348.  
  349. // Add to stage
  350. __cntr.appendChild(__keyLeft);
  351. __cntr.appendChild(__prntRight);
  352. __cntr.appendChild(__cleardiv);
  353. resultsCntr.appendChild(__cntr);
  354. });
  355.  
  356. // Alert box
  357. alertCntr.id = "alertCntr";
  358. alertCntr.style.cssText = 'border:1px solid #EBCCD1;background-color:#F2DEDE;color:#AC4947;font-weight:bold;font-size:90%;border-radius:5px;padding:10px;margin:5px 5px;display:none';
  359. alertCntr.innerHTML = 'Watch out for map exceptions, some higher locks are there for a reason!';
  360.  
  361. // Rules table
  362. let rowElm;
  363. let colElm;
  364.  
  365. let tableElm = document.createElement('table');
  366. tableElm.className = 'tg';
  367.  
  368. let bodyElm = document.createElement('tbody');
  369.  
  370. const topCountry = W.model.getTopCountry();
  371. const countryRules = rulesDB[topCountry.attributes.abbr];
  372. if (countryRules) {
  373. $.each(countryRules, function (key, value) {
  374. if (key == "CountryName") return false;
  375.  
  376. rowElm = document.createElement('tr');
  377. rowElm.className = "tg-row";
  378. rowElm.dataset.name = parseInt(key) === 0 ? 'country' : value.CityName; // need to hard code 'country' to identify later
  379.  
  380. colElm = document.createElement('td');
  381. colElm.className = "tg-header";
  382. colElm.innerHTML = parseInt(key) === 0 ? countryRules.CountryName : value.CityName;
  383. colElm.colSpan = 6;
  384. rowElm.appendChild(colElm);
  385. tableElm.appendChild(rowElm);
  386.  
  387. const maxCol = 3;
  388. let colIndex = 0;
  389. rowElm = document.createElement('tr');
  390. $.each(value.Locks, function (k, v) {
  391. if (v) {
  392. rowElm.className = "tg-row";
  393. rowElm.dataset.name = parseInt(key) === 0 ? 'country' : value.CityName; // need to hard code 'country' to identify later
  394. if (colIndex < maxCol) {
  395. colElm = document.createElement('td');
  396. colElm.className = "tg-type";
  397. colElm.innerHTML = k;
  398. rowElm.appendChild(colElm);
  399.  
  400. colElm = document.createElement('td');
  401. colElm.className = "tg-value";
  402. colElm.innerHTML = v;
  403. rowElm.appendChild(colElm);
  404.  
  405. colIndex++;
  406. if (colIndex == maxCol) {
  407. colIndex = 0;
  408. tableElm.appendChild(rowElm);
  409. rowElm = document.createElement('tr');
  410. }
  411. }
  412. }
  413. });
  414. tableElm.appendChild(rowElm);
  415. });
  416. }
  417.  
  418. tableElm.appendChild(bodyElm);
  419. rulesCntr.style.cssText = 'font-size:12px';
  420. rulesCntr.appendChild(tableElm);
  421.  
  422. // add to stage
  423. relockContent.appendChild(relockTitle);
  424. relockContent.appendChild(versionTitle);
  425.  
  426. // Loader bar
  427. percentageLoader.id = 'percentageLoader';
  428. percentageLoader.style.cssText = 'width:1px;height:10px;background-color:green;margin-top:10px;border:1px solid:#333333;display:none';
  429.  
  430. // only show if user didn't hide it before
  431. if (localStorage.msgHide != 1) {
  432. relockSub.appendChild(hidebutton);
  433. relockContent.appendChild(relockSub);
  434. }
  435.  
  436. inputDiv1.appendChild(respectRouting);
  437. inputDiv1.appendChild(respectRoutingLabel);
  438. inputDiv2.appendChild(includeAllSegments);
  439. inputDiv2.appendChild(includeAllSegmentsLabel);
  440. relockContent.appendChild(inputDiv1);
  441. relockContent.appendChild(inputDiv2);
  442.  
  443. relockContent.appendChild(alertCntr);
  444. relockContent.appendChild(relockSubTitle);
  445. relockContent.appendChild(resultsCntr);
  446. relockContent.appendChild(relockAllbutton);
  447. relockContent.appendChild(dotscntr);
  448. relockContent.appendChild(percentageLoader);
  449. relockContent.appendChild(rulesSubTitle);
  450. relockContent.appendChild(rulesCntr);
  451.  
  452. const { tabLabel, tabPane } = W.userscripts.registerSidebarTab("sidepanel-relock");
  453.  
  454. tabLabel.innerHTML = 'Re - <span class="fa fa-lock" id="lockcolor" style="color:green"></span>';
  455. tabLabel.title = "Relock segments";
  456.  
  457. tabPane.appendChild(relockContent);
  458. W.userscripts.waitForElementConnected(tabPane).then(() => {
  459. // Do a default scan once at startup
  460. relockShowAlert();
  461. scanArea();
  462. });
  463. }
  464.  
  465. function relock(obj, key) {
  466. let objects = obj[key];
  467. let _i = 0;
  468.  
  469. // update GUI
  470. function RunLocal() {
  471. W.model.actionManager.add(objects[_i]);
  472. _i++;
  473.  
  474. if (_i < objects.length) {
  475. setTimeout(RunLocal, 1);
  476. let newWidth = (_i / objects.length) * $('#sidepanel-relockTab').css('width').replace('px', '');
  477. $('#percentageLoader').show();
  478. $('#percentageLoader').css('width', newWidth + 'px');
  479. $('#dotscntr').css('display', 'inline-block');
  480. } else {
  481. $('#dotscntr').css('display', 'none');
  482. $('#percentageLoader').hide();
  483. }
  484. }
  485. RunLocal();
  486. }
  487.  
  488. function relockAll() {
  489. // only lock "all" until the current editors level is reached, then stop...
  490. $('#dotscntr').css('display', 'inline-block');
  491.  
  492. $.each(relockObject, function (key, value) {
  493. if (value.length !== 0) {
  494. // loop trough each segmentType
  495. let _i = 0;
  496. let RunLocal5 = function () {
  497. W.model.actionManager.add(value[_i]);
  498. _i++;
  499.  
  500. // Did not iterate with $.each, so the GUI can update with larger arrays
  501. if (_i < value.length) {
  502. setTimeout(RunLocal5, 1);
  503. let newWidth = (_i / value.length) * $('#sidepanel-relockTab').css('width').replace('px', '');
  504. $('#percentageLoader').show();
  505. $('#percentageLoader').css('width', newWidth + 'px');
  506. $('#dotscntr').css('display', 'inline-block');
  507. } else {
  508. $('#dotscntr').css('display', 'none');
  509. $('#percentageLoader').hide();
  510. }
  511. };
  512. RunLocal5();
  513. }
  514. });
  515. scanArea();
  516. $('#dotscntr').hide('slow');
  517. }
  518.  
  519. function relockShowAlert() {
  520. let includeAllSegments = document.getElementById('_allSegments');
  521. if (includeAllSegments && includeAllSegments.checked)
  522. $('#alertCntr').show("fast");
  523. else
  524. $('#alertCntr').hide("fast");
  525. }
  526.  
  527. function hideInactiveCities() {
  528. $('tr.tg-row').each(function (i) {
  529. let isActive = false;
  530. for (let j in W.model.cities.objects) {
  531. if (W.model.cities.objects[j].attributes.name == $(this).data("name")) {
  532. isActive = true;
  533. break;
  534. }
  535. }
  536. if (isActive || $(this).data("name") == 'country') {
  537. $(this).show("fast");
  538. } else {
  539. $(this).hide("fast");
  540. }
  541. });
  542. }
  543.  
  544. function setLockLevel(v, scanObj, desiredLockLevel) {
  545. let includeAllSegments = document.getElementById('_allSegments');
  546. let allSegmentsInclude = includeAllSegments.checked && userlevel > 4;
  547. if (userlevel > desiredLockLevel) {
  548. if ((v.attributes.lockRank < desiredLockLevel) ||
  549. (v.attributes.lockRank > desiredLockLevel && allSegmentsInclude)) {
  550. relockObject[scanObj].push(new UpdateObject(v, {
  551. lockRank: desiredLockLevel
  552. }));
  553. return true;
  554. }
  555. }
  556. return false;
  557. }
  558.  
  559. function scanArea() {
  560. let respectRouting = document.getElementById('_respectRouting');
  561. let relockSubTitle = document.getElementById('reshdr');
  562. let relockAllbutton = document.getElementById('rlkall');
  563.  
  564. if (!(relockSubTitle && relockAllbutton && respectRouting))
  565. return;
  566.  
  567. hideInactiveCities();
  568.  
  569. // Object with array of road types, to collect each wrongly locked segment, for later use
  570. $.each(defaultLocks, function (k, v) {
  571. relockObject[k] = [];
  572. });
  573.  
  574. let foundBadlocks = false;
  575. let respectRoutingRoadType = respectRouting.checked;
  576. let count = 0;
  577.  
  578. // Choose country lock settings. If country selection fails
  579. // or country isn't in this list, WME default values are used.
  580. let topCountry = W.model.getTopCountry();
  581. let ABBR = rulesDB[topCountry.attributes.abbr] ? rulesDB[topCountry.attributes.abbr][0].Locks : defaultLocks;
  582. console.log("LevelReset: ", ABBR);
  583.  
  584. // Do a count on how many segments are in need of a correct lock (limit to 150 to save CPU)
  585. // Count also depends on the users editor level
  586. const limitCount = 150;
  587. relockSubTitle.innerHTML = 'Results (limit: ' + limitCount + ')';
  588.  
  589. // disable unchecked road types
  590. $.each(streets, function (key, value) {
  591. let idPrefix = 'Relock_' + value.typeName + '_chk';
  592. let chk = document.getElementById(idPrefix);
  593. value.scan = (chk && chk.checked);
  594. });
  595.  
  596. // ============== POI ===========================
  597. if (streets["90000"].scan) {
  598. let scanObj = "POI";
  599. $.each(W.model.venues.objects, function (k, v) {
  600. if (count < limitCount && v.type == "venue" && onScreen(v) && v.isGeometryEditable() && !hasPendingUR(v) /*&& !v.isResidential()*/) {
  601.  
  602. let strt = v.attributes.streetID ? W.model.streets.objects[v.attributes.streetID] : null;
  603. let cityID = strt ? strt.cityID : null;
  604.  
  605. let desiredLockLevel = (cityID && rulesDB[topCountry.attributes.abbr] && rulesDB[topCountry.attributes.abbr][cityID]) ? rulesDB[topCountry.attributes.abbr][cityID].Locks[scanObj] : ABBR[scanObj];
  606. desiredLockLevel--;
  607.  
  608. if (setLockLevel(v, scanObj, desiredLockLevel)) {
  609. foundBadlocks = true;
  610. count++;
  611. }
  612. }
  613. });
  614. }
  615. /*
  616. // ============== Cameras ===========================
  617. if (streets["90001"].scan) {
  618. let scanObj = "Camera";
  619. $.each(W.model.cameras.objects, function (k, v) {
  620. if (count < limitCount && v.type == "camera" && onScreen(v) && v.isGeometryEditable()) {
  621.  
  622. let desiredLockLevel = ABBR[scanObj];
  623. desiredLockLevel--;
  624.  
  625. if (setLockLevel(v, scanObj, desiredLockLevel)) {
  626. foundBadlocks = true;
  627. count++;
  628. }
  629. }
  630. });
  631. }
  632. // ============== Railroad Crossings ===========================
  633. if (streets["90002"].scan) {
  634. let scanObj = "RailroadCrossing";
  635. $.each(W.model.railroadCrossings.objects, function (k, v) {
  636. if (count < limitCount && v.type == "railroadCrossing" && onScreen(v) && v.isGeometryEditable()) {
  637.  
  638. let desiredLockLevel = ABBR[scanObj];
  639. desiredLockLevel--;
  640.  
  641. if (setLockLevel(v, scanObj, desiredLockLevel)) {
  642. foundBadlocks = true;
  643. count++;
  644. }
  645. }
  646. });
  647. }
  648. */
  649. // ============== Segments ===========================
  650. $.each(W.model.segments.objects, function (k, v) {
  651. if (count < limitCount && v.type == "segment" && onScreen(v) && v.isGeometryEditable()) {
  652. let curStreet = streets[v.attributes.roadType];
  653. // for changed routing respect the routing type (if enabled)
  654. if (v.attributes.routingRoadType && respectRoutingRoadType) {
  655. curStreet = streets[v.attributes.routingRoadType];
  656. }
  657. if (curStreet && curStreet.scan) {
  658. let strt = W.model.streets.getObjectById(v.attributes.primaryStreetID);
  659. let cityID = strt ? strt.attributes.cityID : null;
  660.  
  661. let stLocks = (cityID && rulesDB[topCountry.attributes.abbr] && rulesDB[topCountry.attributes.abbr][cityID]) ? rulesDB[topCountry.attributes.abbr][cityID].Locks : ABBR;
  662. let desiredLockLevel = stLocks[curStreet.typeName] - 1;
  663.  
  664. if (setLockLevel(v, curStreet.typeName, desiredLockLevel)) {
  665. foundBadlocks = true;
  666. count++;
  667. }
  668. }
  669. }
  670. });
  671.  
  672. // Build results to users tab panel
  673. $.each(relockObject, function (key, value) {
  674. let __lckRight = document.createElement('div');
  675. let __cntRight = document.createElement('div');
  676. let idPrefix = 'Relock_' + key + '_value';
  677.  
  678. // Begin building
  679. let __prntRight = document.getElementById(idPrefix);
  680. __prntRight.innerHTML = '';
  681.  
  682. __cntRight.style.cssText = 'float:right';
  683. __lckRight.style.cssText = 'width:15px;float:right;padding:2px 0 0 8px;cursor:pointer;';
  684.  
  685. if (value.length !== 0) {
  686. __cntRight.innerHTML = '<b>' + value.length + '</b>';
  687. __lckRight.className = 'fa fa-lock';
  688. __lckRight.style.cssText += 'color:red;';
  689. __lckRight.onclick = function () {
  690. relock(relockObject, key);
  691. };
  692. __prntRight.appendChild(__lckRight);
  693. } else {
  694. __cntRight.innerHTML = '-';
  695. }
  696.  
  697. __prntRight.appendChild(__cntRight);
  698. });
  699.  
  700. // Color the small lock icon red, if errors are found, so people can decide what to do...
  701. if (foundBadlocks) {
  702. relockAllbutton.removeAttribute('disabled');
  703. $('#lockcolor').css('color', 'red');
  704. } else {
  705. relockAllbutton.setAttribute('disabled', true);
  706. $('#lockcolor').css('color', 'green');
  707. }
  708. }
  709.  
  710. getAllLockRules();
  711.  
  712. // Register some event listeners
  713. W.map.events.register("moveend", null, scanArea);
  714. W.model.actionManager.events.register("afteraction", null, scanArea);
  715. W.model.actionManager.events.register("afterundoaction", null, scanArea);
  716. W.model.actionManager.events.register("noActions", null, scanArea);
  717. }
  718.  
  719. LevelReset_bootstrap();