WME Locksmith US

Dynamic locking tool which locks based on State standards

当前为 2019-07-22 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         WME Locksmith US
// @namespace    https://greasyfork.org/en/users/286957-skidooguy
// @version      2019.07.21.02
// @description  Dynamic locking tool which locks based on State standards
// @author       SkiDooGuy / JustinS83 / Blaine "herrchin" Kahle
// @include      /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor\/?.*$/
// @require      https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
// @require      https://apis.google.com/js/api.js
// @grant        none
// @contributionURL https://github.com/WazeDev/Thank-The-Authors
// ==/UserScript==

/* global W */
/* global WazeWrap */
/* global $ */
/* global OL */
/* global _ */
/* global require */

const LOCKSMITH_VERSION = `v${GM_info.script.version}`;
const LS_UPDATE_NOTES = `NEW:<br>
<br>
FIXES:<br>
- Played with some loading times to increase script loading reliability<br>
- Updated a console output that used incorrect script name<br>
- Fixed error preventing correct highlighting of segments locked above or at the editors rank`;
const UpdateObj = require('Waze/Action/UpdateObject');

_allStandardsArray = {};
let _currentStateStandards = {};
let LsSettings = {};
let _currentState = '';
let LocksmithHighlightLayer;
let _editorRank;
let tries = 0;

console.log('Locksmith initializing...');

const css = [
    '.ls-Wrapper {width:100%;height:100%;background-color:white;border:2px solid white;border-radius:6px;font-size:12px;font-family:Poppins, "Helvetica Neue", Helvetica, "Open Sans", sans-serif;user-select:none;}',
    '.ls-Body {display:block;padding:3px;}',
    '.ls-Header-Wrapper {display:block;width:100%;}',
    '.ls-Header-Text-Container {width:100%;padding:0 5px 0 5px;display:inline-block;border-bottom:1px solid grey;}',
    '.ls-Label {display:inline-block;position:relative;padding-right:20px;font-weight:normal;margin:5px 0 0 0;width:auto;cursor:pointer;}',
    '.ls-Label input[type=checkbox] {position:absolute;opacity:0;height:0;width:0;}',
    '.ls-CheckBox {position:absolute;height:13px;width:13px;background-color:#eee;border:1px solid black;border-radius:4px;top:1px;right:0px;}',
    '.ls-Label:hover input ~ .ls-CheckBox {background-color:#ccc;}',
    '.ls-Label input:checked ~ .ls-CheckBox {background-color:rgb(66 184 196);}',
    '.ls-Options-Container {display:inline-block;}',
    '.ls-Options-Menu {position:relative;display:block;width:100%;float:left;padding:3px;border:1px solid black;border-radius:5px;text-align:center;}',
    '.ls-Options-Menu:hover {border:1.5px outset grey;background-color:rgb(224,224,224);}',
    '.ls-Options-Dropdown-Menu {display:none;position:absolute;background-color:#f9f9f9;min-width:160px;top:25px;left:0px;z-index:1;text-align:left;}',
    '.ls-Options-Menu:hover .ls-Options-Dropdown-Menu {display:block;}',
    '.ls-Options-Dropdown-Menu ul {list-style:none;padding-left:0px;border:1px solid grey;border-radius:5px;}',
    '.ls-Options-Dropdown-Menu li {padding:5px;}',
    '.ls-Options-Dropdown-Menu li:hover {background-color:rgb(220,220,220);border:.5px solid lightgrey;border-radius:5px;}',
    '.ls-Section-Container {display:inline-block;width:100%;}',
    '.ls-Section-Header {width:100%;display:block;padding-bottom:2px;border-bottom:1.5px solid grey;margin-bottom:5px;}',
    '.ls-Select {color:#444;box-sizing:border-box;margin-right:5px;outline:none;padding:3px;border:1px solid lightgrey;border-radius:6px;}',
    '.ls-Select:hover  {border:1px solid grey;}',
    '.ls-Select:focus  {border:1px solid black;}',
    '.ls-Lock-Options {display:block;width:100%;max-height:3-px;margin-bottom:3px;}',
    '.ls-Seg-Result {display:inline-block;position:relative;float:right;top:8px;}',
    '.ls-IL-Block {display:inline-block;}',
    '.fa.fa-arrow-circle-up {position:relative;color:lightgrey;padding:0px 5px 0px 5px}',
    '.fa.fa-arrow-circle-down {position:relative;color:lightgrey;padding:0px 5px 0px 5px}',
    '.ls-Seg-Quantity-Low {position:relative;padding:0px 5px 0px 5px;}',
    '.ls-Seg-Quantity-High {position:relative;padding:0px 5px 0px 5px;}',
    '.ls-Seg-Quantity-Low.enabled {}',
    '.ls-Seg-Quantity-High.enabled {}',
    '.ls-Seg-Attributes {display:inline-block;border:1px solid lightgrey;border-radius:5px;padding:2px;margin:4px;background-color:lightgrey;font-size:12px}',
    '.ls-Attr-Label {display:inline-block;position:relative;padding:2px 5px 2px 2px;font-size:12px;font-weight:bold;width:auto;}',
    '.ls-Attr-Label input[type=checkbox] {position:absolute;opacity:0;height:0;width:0;}',
    '.ls-Attr-CheckBox {position:relative;padding:2px;background-color:lightgrey;border:1px solid lightgrey;border-radius:4px;top:1px;right:0px;}',
    '.ls-Attr-Label:hover input ~ .ls-Attr-CheckBox {border:1.2px outset grey;}',
    '.ls-Attr-Label input:checked ~ .ls-Attr-CheckBox {border:1.2px outset black;}',
    '.ls-Button-Container {position:relative;display:inline-block;float:right;padding-top:3px;width:40%;}',
    '.ls-Button {border:1px solid black;border-radius:5px;cursor:pointer;padding:3px;background-color:white;}',
    '.ls-Button:hover {border:1.5px outset grey;background-color:rgb(224,224,224);}',
    '.key-Text {font-weight:bold;font-size:14px;}',
    '#lsConnectionStatus {display:inline;position:relative;height:15px;width:30px;border:1px solid lightgrey;border-radius:4px;font-size:8px;text-align:center;font-weight:bold;top:-2px;left:2px;line-height:1.5;}'
].join(' ');

function Locksmithbootstrap() {
    if (W && W.map && W.model && W.model.states && W.loginManager.user && $ && WazeWrap.Ready) {
        setTimeout(() => { initLocksmith(); }, 200);
    } else if (tries < 500) setTimeout(() => { tries++; Locksmithbootstrap(); }, 200);
    else console.log('Failed to load Locksmith');
}

function initLocksmith() {
    // Checks to ensure WME is in editing mode and not HN or Event mode
    if (W.app.modeController.model.attributes.mode !== 0) {
        return console.log('WME is not in editing mode');
    } console.log('Locksmith loaded');

    _editorRank = W.loginManager.user.getRank();

    const $section = $('<div>');
    // HTML for UI tab
    $section.html([
        '<div class="ls-Wrapper">',
        '<div class="ls-Body">',
        `<div class="ls-Header-Wrapper">
                    <div class="ls-Header-Text-Container">
                        <span class='key-Text'>Locksmith US</span> - <span id='lsVersion' /><a href='https://docs.google.com/spreadsheets/d/1DJEk390OYv5jWXEINl6PF3I1A8y1WrwrdPIsAL7SihI/edit#gid=0' target="_blank" id='lsConnectionStatus' data-original-title="Spreadsheet Connection" />
                    </div>
                    <div class="ls-Options-Container" style="display:block;height:35px;padding:2px 10px 0 10px;width:100%">
                        <div style="display:inline-block;float:left;position:relative;width:60%;">
                            <div class="ls-Options-Container" style="margin:3px 0 0 0;">
                                <div class="ls-Options-Menu">
                                    <div>Options</div>
                                    <div class="ls-Options-Dropdown-Menu">
                                        <ul>
                                            <li>
                                                <label class="ls-Label">Active Scan<input type="checkbox" class="ls-Save-Status" id="lsEnableActiveScan">
                                                <span class="ls-CheckBox" /></label>
                                            </li>
                                            <li>
                                                <label class="ls-Label">Enable Highlights<input type="checkbox" class="ls-Save-Status" id="lsEnableHighlightSeg">
                                                <span class="ls-CheckBox" /></label>
                                            </li>
                                            <li id="ls-Above-Rank-Tooltip" data-original-title="Allows segments that you cannot edit or lock to the standard rank to be highlighted and show in the UI">
                                                <label class="ls-Label">Detect Segs Above My Rank<input type="checkbox" class="ls-Save-Status" id="lsEnableIgnoreRank">
                                                <span class="ls-CheckBox" /></label>
                                            </li>
                                            <li>
                                                <label class="ls-Label">Save Scan Settings<input type="checkbox" class="ls-Save-Status" id="lsEnableSaveSettings">
                                                <span class="ls-CheckBox" /></label>
                                            </li>
                                            <li>
                                                <label class="ls-Label" style="margin:0px;">Manual State Select<input type="checkbox" id="ls-Manual-State-Override">
                                                <span class="ls-CheckBox" /></label>
                                            </li>
                                            <li>
                                                <label class="ls-Label">Disable states popup<input type="checkbox" class="ls-Save-Status" id="lsDisableStatePopup">
                                                <span class="ls-CheckBox" /></label>
                                            </li>
                                            <li id="ls-Higher-Level-Tooltip" data-original-title="Watch out for map exceptions, some higher locks are there for a reason!">
                                                <label class="ls-Label" style="font-weight:bold;">Include Overlocked Segs<input type="checkbox" class="ls-Save-Status" id="lsEnableResetHigher">
                                                <span class="ls-CheckBox" /></label>
                                            </li>
                                        </ul>
                                    </div>
                                </div>
                            </div>
                            <div class="ls-Button-Container" style="width:50%;left:-20px">
                                <input type="button" class="ls-Button" id="ls-Reset-Standards-Display" style="position:relative;" value="Reset" data-original-title="Reset lock values and UI">
                            </div>
                        </div>
                        <div class="ls-Button-Container">
                            <input type="button" class="ls-Button" style="position:relative;left:5px;" id="ls-Maual-Scan-Activate" value="Scan">
                            <input type="button" class="ls-Button" style="float:right;" id="ls-Lock-All-Submit" value="Lock All">
                        </div>
                    </div>
                </div>
                <div class="ls-Section-Container" style="margin-top:0px;">
                    <div class="ls-Section-Container">
                        <span style="float:left;border-bottom:1px solid black;">Lock Standards&nbsp;&nbsp;</span>
                        <span style="float:right;border-bottom:1px solid black;">Lock Status:&nbsp;Low&nbsp;&nbsp;|&nbsp;&nbsp;High&nbsp;&nbsp;|&nbsp;All</span>
                    </div>

                    <div class="ls-Section-Container">
                        <div class="ls-Section-Container" id="ls-Seg-Types-Main">
                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Street-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-LS-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-LS" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-LS-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-LS-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-LS-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-LS-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-LS" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-PS-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-PS-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-PS" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-PS-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-PS-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-PS-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-PS-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-PS" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-minH-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-minH-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-minH" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-minH-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-minH-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-minH-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-minH-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-minH" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-majH-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-majH-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-majH" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-majH-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-majH-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-majH-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-majH-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-majH" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Rmp-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-0">HRCS</option>
                                    <option class="ls-Lock-Option-1">1</option><option class="ls-Lock-Option-2">2</option>
                                    <option class="ls-Lock-Option-3">3</option><option class="ls-Lock-Option-4">4</option>
                                    <option class="ls-Lock-Option-5">5</option><option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Ramp-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Rmp" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Rmp-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Rmp-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Rmp-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Rmp-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Rmp" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-FWY-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-FWY-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Fwy" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Fwy-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Fwy-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Fwy-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Fwy-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Fwy" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="ls-Lock-Options">
                            <div style="display:inline-block;float:left;cursor:pointer;" id="ls-Othr-Seg-Label">Other segment types: </div>
                            <div class="ls-Seg-Result" style="top:5px;" id="rl-Othr-Result-Container">
                                <div class="ls-IL-Block">
                                    <span class="fa fa-arrow-circle-up" id="ls-othr-Lock-Up" />
                                    <span class="ls-Seg-Quantity-Low" id="ls-othr-Low-Quan" />
                                </div>
                                <div class="ls-IL-Block">
                                    <span class="fa fa-arrow-circle-down" id="ls-othr-Lock-Down" />
                                    <span class="ls-Seg-Quantity-High" id="ls-othr-High-Quan" />
                                </div>
                                <span class="fa fa-lock" id="icon-Lock-othr" style="color:lightgrey;padding-left:10px;float:right;" />
                            </div>
                        </div>

                        <div class="ls-Section-Container" id="ls-Seg-Types-Alt" style="display:none;">
                            <div class="ls-Lock-Options" style="margin-top:3px;">
                                <select class="ls-Select" id="ls-lock-Pvt-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Pvt-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Pvt" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Pvt-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Pvt-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Pvt-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Pvt-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Pvt" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Plr-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Plr-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Plr" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Plr-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Plr-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Plr-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Plr-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Plr" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Rail-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Rail-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Rail" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Rail-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Rail-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Rail-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Rail-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Rail" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Fry-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Fry-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Fry" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Fry-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Fry-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Fry-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Fry-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Fry" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Rnwy-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Rnwy-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Rnwy" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Rnwy-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Rnwy-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Rnwy-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Rnwy-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Rnwy" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Ofrd-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Ofrd-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Ofrd" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Ofrd-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Ofrd-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Ofrd-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Ofrd-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Ofrd" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                            <div class="ls-Lock-Options">
                                <select class="ls-Select" id="ls-lock-Nonped-Select">
                                    <option class="ls-Lock-Option-0">Auto</option><option class="ls-Lock-Option-1">1</option>
                                    <option class="ls-Lock-Option-2">2</option><option class="ls-Lock-Option-3">3</option>
                                    <option class="ls-Lock-Option-4">4</option><option class="ls-Lock-Option-5">5</option>
                                    <option class="ls-Lock-Option-6">6</option>
                                </select>
                                <span class="ls-Nonped-Label" />
                                <div class="ls-Seg-Result">
                                    <div id="ls-Seg-Result-Nonped" style="float:right;">
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-up" id="ls-Nonped-Lock-Up" />
                                            <span class="ls-Seg-Quantity-Low" id="ls-Nonped-Low-Quan" />
                                        </div>
                                        <div class="ls-IL-Block">
                                            <span class="fa fa-arrow-circle-down" id="ls-Nonped-Lock-Down" />
                                            <span class="ls-Seg-Quantity-High" id="ls-Nonped-High-Quan" />
                                        </div>
                                        <span class="fa fa-lock" id="icon-Lock-Nonped" style="color:lightgrey;padding-left:10px;float:right;" />
                                    </div>
                                </div>
                            </div>

                        </div>
                    </div>
                </div>
                <div class="ls-Section-Container" style="margin-top:5px;border-top:.5px solid lightgrey;">
                    <div class="ls-Section-Container" style="margin-top:3px;">
                        Current Standards:&nbsp;&nbsp;<span id="ls-Current-State-Display" style="font-weight:bold;" />
                        <div id="ls-State-Select-Container" style="display:none;">
                            <select class="ls-Select" id="ls-State-Selection"></select>
                        </div>
                    </div>
                </div>
                <div class="ls-Section-Container">
                    <div class="ls-Section-Header" style="float:left;margin-top:5px;" id="ls-Add-Att-Info" data-original-title="Colored attributes are available in this state, click to toggle them enabled">Additional Attributes</div>
                    <div class="ls-Locking-Attributes">
                        <label class="ls-Attr-Label">
                            <input type="checkbox" class="ls-Att-Ck-Form" id="ls-Unpaved-Enable"><span class="ls-Attr-CheckBox" id="ls-Unpaved-Status" />
                        </label>
                        <label class="ls-Attr-Label">
                            <input type="checkbox" class="ls-Att-Ck-Form" id="ls-OneWay-Enable"><span class="ls-Attr-CheckBox" id="ls-OneWay-Status" />
                        </label>
                        <label class="ls-Attr-Label">
                            <input type="checkbox" class="ls-Att-Ck-Form" id="ls-HOV-Enable"><span class="ls-Attr-CheckBox" id="ls-HOV-Status" />
                        </label>
                        <label class="ls-Attr-Label">
                            <input type="checkbox" class="ls-Att-Ck-Form" id="ls-Toll-Enable"><span class="ls-Attr-CheckBox" id="ls-Toll-Status" />
                        </label>
                        <label class="ls-Attr-Label">
                            <input type="checkbox" class="ls-Att-Ck-Form" id="ls-WKT-Enable"><span class="ls-Attr-CheckBox" id="ls-WKT-Status" />
                        </label>
                    </div>
               </div>`,
        '</div>',
        '</div>'
    ].join(' '));

    // If editor rank is sufficient the script is initialized and the highlighting layer is created
    if (_editorRank >= 2) {
        new WazeWrap.Interface.Tab('LsUS', $section.html(), initializeSettings);
        WazeWrap.Interface.ShowScriptUpdate(GM_info.script.name, GM_info.script.version, LS_UPDATE_NOTES, 'https://greasyfork.org/en/scripts/386773-wme-locksmith-us', 'https://www.waze.com/forum/viewtopic.php?f=1286&t=285583');
        LocksmithHighlightLayer = new OL.Layer.Vector('LocksmithHighlightLayer', { uniqueName: '__LocksmithHighlightLayer' });
        W.map.addLayer(LocksmithHighlightLayer);
        LocksmithHighlightLayer.setVisibility(true);
        setTimeout(() => { if (_editorRank < 2) WazeWrap.Alerts.warning(GM_info.script.name, `Editor rank below R5, the maximum you'll be able to lock segments is R${_editorRank + 1}`); }, 3000);
    } else return console.log('Locksmith: Editor rank not high enough...');
}

async function initializeSettings() {
    loadSpreadsheet();
    await loadSettings();
    setUserOptions();
    setTimeout(() => { getCurrentState(); }, 300);

    $(`<style type="text/css">${css}</style>`).appendTo('head');

    // Allows WME native tooltip UI
    $('#ls-Add-Att-Info').tooltip();
    $('#lsConnectionStatus').tooltip();
    $('#ls-Above-Rank-Tooltip').tooltip({ placement: 'auto right' });
    $('#ls-Higher-Level-Tooltip').tooltip({ placement: 'auto bottom' });
    $('#ls-Reset-Standards-Display').tooltip({ placement: 'auto bottom' });

    // Create listeners to run functions when buttons are clicked
    $('#ls-Lock-All-Submit').click(() => { relockAll(); });
    $('#ls-Maual-Scan-Activate').click(() => { scanArea(); });
    $('#ls-Reset-Standards-Display').click(() => { setCurrentStandards(_currentState); resetUISegStats(); });
    $('#ls-Othr-Seg-Label').click(() => { $('#ls-Seg-Types-Main').toggle(); $('#ls-Seg-Types-Alt').toggle(); $('#rl-Othr-Result-Container').toggle(); });

    $('#ls-State-Selection').change(function () { _currentState = this.value; setCurrentStandards(_currentState); });
    $('#lsEnableHighlightSeg').change(function () { if (!this.checked) { removeHighlights(); } });
    $("input[type='checkbox'].ls-Att-Ck-Form").change(function () {
        const elementName = $(this).attr('id');

        switch (elementName) {
            case 'ls-Unpaved-Enable':
                if (this.checked) $('#ls-Unpaved-Status').css({ 'background-color': 'rgb(205,133,63)', 'background-image': '' });
                else $('#ls-Unpaved-Status').css({ 'background-color': '', 'background-image': 'repeating-linear-gradient(135deg,lightgrey,rgb(205,133,63) 20%,lightgrey 10%)' });
                break;
            case 'ls-OneWay-Enable':
                if (this.checked) $('#ls-OneWay-Status').css({ 'background-color': 'rgb(236, 249, 31)', 'background-image': '' });
                else $('#ls-OneWay-Status').css({ 'background-color': '', 'background-image': 'repeating-linear-gradient(135deg,rgb(239,251,81),rgb(209,224,6) 6px,black 8px)' });
                break;
            case 'ls-HOV-Enable':
                if (this.checked) $('#ls-HOV-Status').css({ 'background-color': 'rgb(254,151,13)', 'background-image': '' });
                else $('#ls-HOV-Status').css({ 'background-color': '', 'background-image': 'repeating-linear-gradient(135deg,rgb(254,151,13),rgb(247,199,134) 6px,black 8px)' });
                break;
            case 'ls-Toll-Enable':
                if (this.checked) $('#ls-Toll-Status').css({ 'background-color': 'rgb(253,14,202)', 'background-image': '' });
                else $('#ls-Toll-Status').css({ 'background-color': '', 'background-image': 'repeating-linear-gradient(135deg,rgb(253,14,202),rgb(252,156,231) 6px,black 8px)' });
                break;
            case 'ls-WKT-Enable':
                if (this.checked) $('#ls-WKT-Status').css({ 'background-color': 'rgb(9,235,255)', 'background-image': '' });
                else $('#ls-WKT-Status').css({ 'background-color': '', 'background-image': 'repeating-linear-gradient(135deg,rgb(9,235,255),rgb(161,247,255) 6px,black 8px)' });
                break;
            default:
                console.log('LS: Seg Att switch error');
        }
    });
    $('#ls-Manual-State-Override').change(function () {
        if (this.checked) {
            generateStateList();
            $('#ls-State-Select-Container').css('display', 'inline-block');
            $('#ls-Current-State-Display').css('display', 'none');
            setCurrentStandards(_currentState);
        } else {
            $('#ls-State-Select-Container').css('display', 'none');
            $('#ls-Current-State-Display').css('display', 'inline-block');
            _currentState = 'changeME';
            getCurrentState();
        }
    });
    $('#lsEnableActiveScan').change(function () { if (!this.checked) { resetUISegStats(); removeHighlights(); } });

    // Trigger checkbox save status
    $('.ls-Save-Status').change(function () {
        let settingName = $(this)[0].id.substr(2);
        LsSettings[settingName] = this.checked;
        saveSettings();
    });

    // Register WME event listeners
    W.map.events.register('moveend', null, tryScan);
    W.map.events.register('movestart', null, resetUISegStats);
    W.model.actionManager.events.register('afteraction', null, tryScan);
    W.model.actionManager.events.register('afterundoaction', null, tryScan);
    W.model.actionManager.events.register('afterclearactions', null, tryScan);
    W.model.actionManager.events.register('afterclearactions', null, resetUISegStats);

    // Setup UI text
    $('#lsVersion').text(LOCKSMITH_VERSION);
    $('.ls-FWY-Label').text('FWY');
    $('.ls-Ramp-Label').text('Ramp');
    $('.ls-majH-Label').text('MH');
    $('.ls-minH-Label').text('mH');
    $('.ls-PS-Label').text('PS');
    $('.ls-LS-Label').text('LS');
    $('.ls-Pvt-Label').text('PVT');
    $('.ls-Plr-Label').text('PLR');
    $('.ls-Rail-Label').text('Railroad');
    $('.ls-Fry-Label').text('Ferry');
    $('.ls-Ofrd-Label').text('Off-Road');
    $('.ls-Rnwy-Label').text('Runway');
    $('.ls-Nonped-Label').text('NonRout Ped');
    $('.ls-Seg-Quantity-Low').text('--');
    $('.ls-Seg-Quantity-High').text('--');
    $('.fa.fa-arrow-circle-up').css({ color: 'lightgrey', cursor: 'default' });
    $('.fa.fa-arrow-circle-down').css({ color: 'lightgrey', cursor: 'default' });
    $('.fa.fa-arrow-circle-up').attr('disabled', true);
    $('.fa.fa-arrow-circle-down').attr('disabled', true);
    $('#ls-Unpaved-Status').text('Unpaved');
    $('#ls-OneWay-Status').text('One-Way');
    $('#ls-HOV-Status').text('HOV');
    $('#ls-WKT-Status').text('WKT');
    $('#ls-Toll-Status').text('Toll');

    function setUserOptions() {
        // Checks editors rank and hides lock options above them
        verifyOptionEnable('.ls-Lock-Option-3', 2);
        verifyOptionEnable('.ls-Lock-Option-4', 3);
        verifyOptionEnable('.ls-Lock-Option-5', 4);
        verifyOptionEnable('.ls-Lock-Option-6', 5);
        // Set check boxes based on last use
        setChecked('lsEnableActiveScan', LsSettings.EnableActiveScan);
        setChecked('lsEnableHighlightSeg', LsSettings.EnableHighlightSeg);
        setChecked('lsEnableResetHigher', LsSettings.EnableResetHigher);
        setChecked('lsEnableSaveSettings', LsSettings.EnableSaveSettings);
        setChecked('lsDisableStatePopup', LsSettings.DisableStatePopup);
        setChecked('lsEnableIgnoreRank', LsSettings.EnableIgnoreRank);

        // Enable rank select drop downs appropriate for editors rank
        function verifyOptionEnable(className, rankRequired) {
            if (_editorRank < rankRequired) $(className).hide();
        }
        function setChecked(checkboxId, checked) {
            $(`#${checkboxId}`).prop('checked', checked);
        }
    }
}

async function saveSettings() {
    const localsettings = {
        lastSaveAction: Date.now(),
        EnableActiveScan: LsSettings.EnableActiveScan,
        EnableHighlightSeg: LsSettings.EnableHighlightSeg,
        EnableResetHigher: LsSettings.EnableResetHigher,
        DisableStatePopup: LsSettings.DisableStatePopup,
        EnableIgnoreRank: LsSettings.EnableIgnoreRank,
        EnableSaveSettings: LsSettings.EnableSaveSettings
    };

    if (localStorage) { localStorage.setItem('LsUS_Settings', JSON.stringify(localsettings)); }
    // Attempt to connect to the WazeWrap setting store server
    const serverSave = await WazeWrap.Remote.SaveSettings('LsUS_Settings', localsettings);

    if (serverSave === null) console.log('LsUS: User PIN not set in WazeWrap tab');
    else if (serverSave === false) console.log('LsUS: Unable to save settings to server');
}

async function loadSettings() {
    const localSettings = $.parseJSON(localStorage.getItem('LsUS_Settings'));
    // Attempt connection to WazeWrap setting server to retrieve settings
    const serverSettings = await WazeWrap.Remote.RetrieveSettings('LsUS_Settings');
    if (!serverSettings) console.log('LsUS: Error communicating with WW settings server');
    // Default checkbox settings
    const defaultsettings = {
        lastSaveAction: null,
        EnableActiveScan: false,
        EnableHighlightSeg: false,
        EnableResetHigher: false,
        DisableStatePopup: false,
        EnableIgnoreRank: false,
        EnableSaveSettings: false
    };

    LsSettings = $.extend({}, defaultsettings, localSettings);
    if (serverSettings && serverSettings.lastSaveAction > LsSettings.lastSaveAction) {
        $.extend(LsSettings, serverSettings);
        console.log('Locksmith server settings used');
    }
    if (LsSettings.EnableSaveSettings === false) LsSettings = defaultsettings;
}

function changeUI(eleID, status, type, inText) {
    if (type === 'lock' && status === 1) {
        $(eleID).attr('disabled', false);
        if (inText === 'high') $(eleID).css({ color: 'cyan', cursor: 'pointer' });
        if (inText === 'low') $(eleID).css({ color: 'red', cursor: 'pointer' });
        if (inText === 'both') $(eleID).css({ color: 'orange', cursor: 'pointer' });
    }
    if (type === 'text' && status === 1) {
        $(eleID).text(inText);
    }
    if (type === 'lock' && status === 0) {
        $(eleID).css({ color: 'lightgrey', cursor: 'default' });
        $(eleID).attr('disabled', true);
        $(eleID).off('click');
    }
}

function resetUISegStats() {
    changeUI('.fa.fa-arrow-circle-up', 0, 'lock', null);
    changeUI('.fa.fa-arrow-circle-down', 0, 'lock', null);
    changeUI('.ls-Seg-Quantity-Low', 1, 'text', '--');
    changeUI('.ls-Seg-Quantity-High', 1, 'text', '--');
    changeUI('#icon-Lock-LS', 0, 'lock', null);
    changeUI('#icon-Lock-PS', 0, 'lock', null);
    changeUI('#icon-Lock-minH', 0, 'lock', null);
    changeUI('#icon-Lock-majH', 0, 'lock', null);
    changeUI('#icon-Lock-Rmp', 0, 'lock', null);
    changeUI('#icon-Lock-Fwy', 0, 'lock', null);
    changeUI('#icon-Lock-othr', 0, 'lock', null);
    changeUI('#icon-Lock-Pvt', 0, 'lock', null);
    changeUI('#icon-Lock-Plr', 0, 'lock', null);
    changeUI('#icon-Lock-Rail', 0, 'lock', null);
    changeUI('#icon-Lock-Rnwy', 0, 'lock', null);
    changeUI('#icon-Lock-Fry', 0, 'lock', null);
    changeUI('#icon-Lock-Ofrd', 0, 'lock', null);
    changeUI('#icon-Lock-Nonped', 0, 'lock', null);
    removeHighlights();
    $("a[href$='#sidepanel-lsus']").css('background-color', '#e9e9e9');
}

function WKT_to_LinearRing(wkt) {
    const lines = wkt.split(',');
    const ringPts = [];

    for (let i = 0; i < lines.length; i++) {
        const coords = lines[i].trim().match(/(-?\d*(?:\.\d*)?)\s(-?\d*(?:\.\d*))/);
        const pt = WazeWrap.Geometry.ConvertTo900913(coords[1], coords[2]);
        ringPts.push(new OL.Geometry.Point(pt.lon, pt.lat));
    }
    return new OL.Geometry.LinearRing(ringPts);
}

async function loadSpreadsheet() {
    let connectionEstablished = false;
    const apiKey = 'AIzaSyDZjmkSx5xWc-86hsAIzedgDgRgy8vB7BQ';
    const rawSheetData = await $.getJSON(`https://sheets.googleapis.com/v4/spreadsheets/1DJEk390OYv5jWXEINl6PF3I1A8y1WrwrdPIsAL7SihI/values/Sheet1!A2:C?key=${apiKey}`);
    if (rawSheetData.values.length > 0) {
        _.each(rawSheetData.values, v => {
            if (!_allStandardsArray[v[1]]) _allStandardsArray[v[1]] = JSON.parse(v[0]);
            else {
                if (!_allStandardsArray[v[1]].Areas) _allStandardsArray[v[1]].Areas = {};
                _allStandardsArray[v[1]].Areas[v[2]] = JSON.parse(v[0]);
                if (v[2].startsWith('POLYGON')) _allStandardsArray[v[1]].Areas[v[2]].Polygon = new OL.Geometry.Polygon(WKT_to_LinearRing(v[2]));
            }
        });
        connectionEstablished = true;
    }
    if (connectionEstablished) {
        $('#lsConnectionStatus').text('Good');
        $('#lsConnectionStatus').css('backgroundColor', 'lime');
    } else {
        $('#lsConnectionStatus').text('Error');
        $('#lsConnectionStatus').css('backgroundColor', 'red');
    }

    // Process state standards for later use
    _.each(_allStandardsArray, stateKey => {
        for (const k in stateKey) {
            if (stateKey.hasOwnProperty(k)) {
                // Check if strings are numbers and convert to numbers if so
                let keyValue = stateKey[k];
                // convert "" values to null
                if (keyValue == '') keyValue = null;
                // If lock is 1 then change to Auto to prevent excessive 1 locks
                let tempKey = parseInt(keyValue);
                if (!isNaN(tempKey)) {
                    if (keyValue == 1) tempKey = 'Auto';
                    keyValue = tempKey;
                }
                stateKey[k] = keyValue;
            }
        }

        if (stateKey.Areas) {
            _.each(stateKey.Areas, polyArea => {
                for (const k in polyArea) {
                    if (polyArea.hasOwnProperty(k)) {
                        // Check if strings are numbers and convert to numbers if so
                        let keyValue = polyArea[k];
                        // convert "" values to null
                        if (keyValue == '') keyValue = null;
                        // If lock is 1 then change to Auto to prevent excessive 1 locks
                        let tempKey = parseInt(keyValue);
                        if (!isNaN(tempKey)) {
                            if (keyValue == 1) tempKey = 'Auto';
                            keyValue = tempKey;
                        }
                        polyArea[k] = keyValue;
                    }
                }
            });
        }
    });
}

function getCurrentState() {
    const overrideEnable = getId('ls-Manual-State-Override').checked;
    const disablePopup = getId('lsDisableStatePopup').checked;
    const statesAvailable = W.model.states.getObjectArray();
    let statusOk = false;
    let attempts = 0;

    function stateModelStatus() {
        if (statesAvailable) {
            // Verify the number of states currently available and either prompt for manual selection or set standards based on that state
            if (statesAvailable.length > 1) {
                if (!overrideEnable) {
                    if (!disablePopup) WazeWrap.Alerts.info(GM_info.script.name, 'Multiple States available, please manually set the correct state or zoom in to reset the States layer');
                    $('#ls-Current-State-Display').text('Multiple');
                } else statusOk = true;
            } else if (statesAvailable.length === 1 && !overrideEnable) {
                if (statesAvailable[0].name !== _currentState) {
                    _currentState = statesAvailable[0].name;
                    $('#ls-Current-State-Display').text(_currentState);
                    setCurrentStandards(_currentState);
                    statusOk = true;
                } else statusOk = true;
            } else statusOk = true;
        } else if (attempts < 500) setTimeout(() => { stateModelStatus(attempts++); }, 500);
        else WazeWrap.Alerts.warning(GM_info.script.name, 'Error loading state array');
    }
    stateModelStatus();
    return statusOk;
}

function generateStateList() {
    const stateSelector = getId('ls-State-Selection');
    const currOptionsLength = stateSelector.childNodes.length;
    const statesAvailable = W.model.states.getObjectArray();

    // Removes any options currently attached to the select
    if (currOptionsLength > 0) {
        for (let i = 0; i < currOptionsLength; i++) {
            stateSelector.removeChild(stateSelector.firstChild);
        }
    }

    // Adds available states to the user select
    for (let i = 0; i < statesAvailable.length; i++) {
        const currStateName = statesAvailable[i].name;
        const newStateOption = document.createElement('option');
        const stateNameText = document.createTextNode(currStateName);
        if (i === 0) {
            newStateOption.setAttribute('selected', true);
            _currentState = currStateName;
        }
        newStateOption.appendChild(stateNameText);
        stateSelector.appendChild(newStateOption);
    }
}

function setCurrentStandards(stateName) {
    // Sets the locking standards based on the state and updates relevent UI components
    _currentStateStandards = _allStandardsArray[stateName];

    $('#ls-lock-Street-Select').val(_currentStateStandards.LS);
    $('#ls-lock-PS-Select').val(_currentStateStandards.PS);
    $('#ls-lock-minH-Select').val(_currentStateStandards.mH);
    $('#ls-lock-majH-Select').val(_currentStateStandards.MH);
    $('#ls-lock-Rmp-Select').val(_currentStateStandards.Ramp);
    $('#ls-lock-FWY-Select').val(_currentStateStandards.Fwy);
    $('#ls-lock-Pvt-Select').val(_currentStateStandards.Private);
    $('#ls-lock-Plr-Select').val(_currentStateStandards.PLR);
    $('#ls-lock-Rail-Select').val(_currentStateStandards.Railroad);
    $('#ls-lock-Fry-Select').val(_currentStateStandards.Ferry);
    $('#ls-lock-Rnwy-Select').val(_currentStateStandards.Runway);
    $('#ls-lock-Ofrd-Select').val(_currentStateStandards.Offroad);
    $('#ls-lock-Nonped-Select').val(_currentStateStandards.NonRoutablePedestrian);

    // Setup seg attribute based locks on UI
    if (_currentStateStandards.Unpaved) {
        $('#ls-Unpaved-Enable').attr('disabled', false);
        $('#ls-Unpaved-Enable').prop('checked', true);
        $('#ls-Unpaved-Status').css({ 'background-color': 'rgb(205,133,63)', 'background-image': '' });
    } else {
        $('#ls-Unpaved-Enable').attr('disabled', true);
        $('#ls-Unpaved-Status').css({ 'background-image': 'repeating-linear-gradient(135deg,lightgrey,grey 10px,black 4px)', 'background-color': '' });
    }
    if (_currentStateStandards.LS1Way || _currentStateStandards.PS1Way || _currentStateStandards.mH1Way || _currentStateStandards.MH1Way || _currentStateStandards.Private1Way) {
        $('#ls-OneWay-Enable').attr('disabled', false);
        $('#ls-OneWay-Enable').prop('checked', true);
        $('#ls-OneWay-Status').css({ 'background-color': 'rgb(236,249,31)', 'background-image': '' });
    } else {
        $('#ls-OneWay-Enable').attr('disabled', true);
        $('#ls-OneWay-Status').css({ 'background-image': 'repeating-linear-gradient(135deg,lightgrey,grey 10px,black 4px)', 'background-color': '' });
    }
    if (_currentStateStandards.HOV) {
        $('#ls-HOV-Enable').attr('disabled', false);
        $('#ls-HOV-Enable').prop('checked', true);
        $('#ls-HOV-Status').css({ 'background-color': 'rgb(254,151,13)', 'background-image': '' });
    } else {
        $('#ls-HOV-Enable').attr('disabled', true);
        $('#ls-HOV-Status').css({ 'background-image': 'repeating-linear-gradient(135deg,lightgrey,grey 10px,black 4px)', 'background-color': '' });
    }
    if (_currentStateStandards.Toll) {
        $('#ls-Toll-Enable').attr('disabled', false);
        $('#ls-Toll-Enable').prop('checked', true);
        $('#ls-Toll-Status').css({ 'background-color': 'rgb(253,14,202)', 'background-image': '' });
    } else {
        $('#ls-Toll-Enable').attr('disabled', true);
        $('#ls-Toll-Status').css({ 'background-image': 'repeating-linear-gradient(135deg,lightgrey,grey 10px,black 4px)', 'background-color': '' });
    }
    if (_currentStateStandards.Areas) {
        $('#ls-WKT-Enable').attr('disabled', false);
        $('#ls-WKT-Enable').prop('checked', true);
        $('#ls-WKT-Status').css({ 'background-color': 'rgb(9,235,255)', 'background-image': '' });
    } else {
        $('#ls-WKT-Enable').attr('disabled', true);
        $('#ls-WKT-Status').css({ 'background-image': 'repeating-linear-gradient(135deg,lightgrey,grey 10px,black 4px)', 'background-color': '' });
    }

    console.log(`LS: Lock levels loaded for: ${stateName}`);
}

function getId(iD) {
    return document.getElementById(iD);
}

function onScreen(obj) {
    if (obj.geometry) {
        return (W.map.getExtent().intersectsBounds(obj.geometry.getBounds()));
    }
    return false;
}

function removeHighlights() {
    LocksmithHighlightLayer.removeAllFeatures();
}

function processLocks(seg, currLockRnk, stdLockRnk) {
    // Process lock action
    if (stdLockRnk > _editorRank) stdLockRnk = _editorRank;
    if (((currLockRnk < stdLockRnk) || (currLockRnk == null && stdLockRnk != null)
		|| ((currLockRnk > stdLockRnk) && (currLockRnk <= _editorRank)))
		&& seg.isGeometryEditable() && seg.attributes.hasClosures === false) {
        W.model.actionManager.add(new UpdateObj(seg, { lockRank: stdLockRnk }));
        return true;
    } return false;
}

function getSegmentConditions(seg, conditions) {
    // Determine segment attributes for locking exceptions
    if ((seg.fwdDirection === false && seg.revDirection === true) || (seg.fwdDirection === true && seg.revDirection === false)) conditions.isOneWay = true;
    if (seg.fwdToll === true || seg.revToll === true) conditions.isTollRoad = true;
    if (seg.flags === 16) conditions.isUnpaved = true;
    return conditions;
}

function getHighestLock(segID) {
    const segObj = W.model.segments.getObjectById(segID);
    const segType = segObj.attributes.roadType;
    const checkedSegs = [];
    let forwardLock = null;
    let reverseLock = null;

    function processForNode(forwardID) {
        checkedSegs.push(forwardID);
        const forNode = W.model.segments.getObjectById(forwardID).getToNode();
        const forNodeSegs = [...forNode.attributes.segIDs];

        for (let j = 0; j < forNodeSegs.length; j++) {
            if (forNodeSegs[j] === forwardID) { forNodeSegs.splice(j, 1); }
        }

        for (let i = 0; i < forNodeSegs.length; i++) {
            const conSeg = W.model.segments.getObjectById(forNodeSegs[i]).attributes;

            if (conSeg.roadType !== segType) {
                forwardLock = Math.max(conSeg.lockRank, forwardLock);
            } else {
                for (let k = 0; k < forNodeSegs.length; k++) {
                    if (!checkedSegs.some(segNum => segNum === conSeg.id)) {
                        const tempRank = processForNode(conSeg.id);
                        if (tempRank > forwardLock) forwardLock = tempRank;
                    }
                }
            }
        }
        return forwardLock;
    }

    function processRevNode(reverseID) {
        checkedSegs.push(reverseID);
        const revNode = W.model.segments.getObjectById(reverseID).getFromNode();
        const revNodeSegs = [...revNode.attributes.segIDs];

        for (let j = 0; j < revNodeSegs.length; j++) {
            if (revNodeSegs[j] === reverseID) { revNodeSegs.splice(j, 1); }
        }

        for (let i = 0; i < revNodeSegs.length; i++) {
            const conSeg = W.model.segments.getObjectById(revNodeSegs[i]).attributes;

            if (conSeg.roadType !== segType) {
                reverseLock = Math.max(conSeg.lockRank, reverseLock);
            } else {
                for (let k = 0; k < revNodeSegs.length; k++) {
                    if (!checkedSegs.some(segNum => segNum === conSeg.id)) {
                        const tempRank = processRevNode(conSeg.id);
                        if (tempRank > reverseLock) { reverseLock = tempRank; }
                    }
                }
            }
        }
        return reverseLock;
    }

    return Math.max(processForNode(segID), processRevNode(segID));
}

function processSegment(seg) {
    // Gather primary segment locks from UI in case of user override of standards
    const lsInput = getId('ls-lock-Street-Select').value;
    const psInput = getId('ls-lock-PS-Select').value;
    const minHInput = getId('ls-lock-minH-Select').value;
    const majHInput = getId('ls-lock-majH-Select').value;
    const rmpInput = getId('ls-lock-Rmp-Select').value;
    const fwyInput = getId('ls-lock-FWY-Select').value;
    const pvtInput = getId('ls-lock-Pvt-Select').value;
    const plrInput = getId('ls-lock-Plr-Select').value;
    const railInput = getId('ls-lock-Rail-Select').value;
    const fryInput = getId('ls-lock-Fry-Select').value;
    const ofrdInput = getId('ls-lock-Ofrd-Select').value;
    const rnwyInput = getId('ls-lock-Rnwy-Select').value;
    const NonpedInput = getId('ls-lock-Nonped-Select').value;
    const unpavedChkd = getId('ls-Unpaved-Enable').checked;
    const oneWayChkd = getId('ls-OneWay-Enable').checked;
    const tollChkd = getId('ls-Toll-Enable').checked;
    const wktChkd = getId('ls-WKT-Enable').checked;
    const hovChkd = getId('ls-HOV-Enable').checked;

    const segAtt = seg.attributes;
    const segType = segAtt.roadType;
    let lockUpdateLvl = null;
    let enUpdate = false;
    let tempLocks = _currentStateStandards;
    let possiblePolys = [];

    if (seg.state !== 'Insert') {
        // Gather/verify info attached to segment
        const priSt = W.model.streets.getObjectById(segAtt.primaryStreetID);
        const cityObj = W.model.cities.getObjectById(priSt.cityID);
        const cityName = cityObj.attributes.name;
        const segStateName = W.model.states.getObjectById(cityObj.attributes.stateID).name;
        // Setup object to verify certain segment attributes
        const conditions = {
            isOneWay: false,
            isTollRoad: false,
            isTunnel: false,
            isUnpaved: false,
            hasHeadlights: false
        };

        // Check if segment is in special city/polygon locking standards
        if (wktChkd) {
            _.each(tempLocks.Areas, (v, k) => {
                if (!k.startsWith('POLYGON')) {
                    if (k === cityName) { tempLocks = v; console.log(`using special city${k}`); }
                } else { possiblePolys.push(v); }
            });
            for (let i = 0; i < possiblePolys.length; i++) {
                if (possiblePolys[i].Polygon.intersects(seg.geometry)) {
                    tempLocks = possiblePolys[i];
                    console.log('using poly locks');
                    break;
                }
            }
        }

        const lockLvls = {
            lsLock: lsInput === 'Auto' ? null : lsInput - 1,
            psLock: psInput === 'Auto' ? null : psInput - 1,
            minHLock: minHInput === 'Auto' ? null : minHInput - 1,
            majHLock: majHInput === 'Auto' ? null : majHInput - 1,
            rmpLock: rmpInput >= 0 ? rmpInput - 1 : rmpInput,
            fwyLock: fwyInput === 'Auto' ? null : fwyInput - 1,
            plrLock: plrInput === 'Auto' ? null : plrInput - 1,
            pvtLock: pvtInput === 'Auto' ? null : pvtInput - 1,
            nrpedLock: NonpedInput === 'Auto' ? null : NonpedInput - 1,
            fryLock: fryInput === 'Auto' ? null : fryInput - 1,
            rrLock: railInput === 'Auto' ? null : railInput - 1,
            rnwyLock: rnwyInput === 'Auto' ? null : rnwyInput - 1,
            offRoadLock: ofrdInput === 'Auto' ? null : ofrdInput - 1,
            pvtOneWay: tempLocks.Private1Way != null,
            plrOneWay: tempLocks.PLR1Way != null,
            lsOneWay: tempLocks.LS1Way != null,
            psOneWay: tempLocks.PS1Way != null,
            minOneWay: tempLocks.mH1Way != null,
            majOneWay: tempLocks.MH1Way != null,
            tollLock: tempLocks.Toll != null,
            unpavedLock: tempLocks.Unpaved != null
        };

        if (seg.type === 'segment' && onScreen(seg) && (segStateName === _currentState)) {
            getSegmentConditions(segAtt, conditions);

            // Process local streets
            if (segType === 1) {
                lockUpdateLvl = lockLvls.lsLock;

                if ((conditions.isOneWay && lockLvls.lsOneWay && oneWayChkd)
                    || (conditions.isTollRoad && lockLvls.tollLock && tollChkd)
                    || (conditions.isUnpaved && lockLvls.unpavedLock && unpavedChkd)) {
                    if (lockUpdateLvl === null) lockUpdateLvl = 1;
                    else lockUpdateLvl++;
                }
                enUpdate = true;
            }
            // Process primary streets
            if (segType === 2) {
                lockUpdateLvl = lockLvls.psLock;

                if ((conditions.isOneWay && lockLvls.psOneWay && oneWayChkd)
                    || (conditions.isTollRoad && lockLvls.tollLock && tollChkd)
                    || (conditions.isUnpaved && lockLvls.unpavedLock && unpavedChkd)) {
                    if (lockUpdateLvl === null) lockUpdateLvl = 1;
                    else lockUpdateLvl++;
                }
                enUpdate = true;
            }
            // Process Fwy
            if (segType === 3) {
                lockUpdateLvl = lockLvls.fwyLock;
                enUpdate = true;
            }
            // Process ramps
            if (segType === 4) {
                lockUpdateLvl = lockLvls.rmpLock;
                enUpdate = true;
                if (lockUpdateLvl === 'HRCS') {
                    lockUpdateLvl = getHighestLock(segAtt.id);
                }
            }
            // Process routable ped path
            // if(segType == 5) {
            // lockUpdateLvl = lockLvls.rpedLock;
            // enUpdate = true;
            // }
            // Process MH
            if (segType === 6) {
                lockUpdateLvl = lockLvls.majHLock;

                if ((conditions.isOneWay && lockLvls.majHOneWay && oneWayChkd)
                    || (conditions.isTollRoad && lockLvls.tollLock && tollChkd)
                    || (conditions.isUnpaved && lockLvls.unpavedLock && unpavedChkd)) {
                    if (lockUpdateLvl === null) lockUpdateLvl = 1;
                    else lockUpdateLvl++;
                }
                enUpdate = true;
            }
            // Process minor highways
            if (segType === 7) {
                lockUpdateLvl = lockLvls.minHLock;

                if ((conditions.isOneWay && lockLvls.minHOneWay && oneWayChkd)
                    || (conditions.isTollRoad && lockLvls.tollLock && tollChkd)
                    || (conditions.isUnpaved && lockLvls.unpavedLock && unpavedChkd)) {
                    if (lockUpdateLvl === null) lockUpdateLvl = 1;
                    else lockUpdateLvl++;
                }
                enUpdate = true;
            }
            // Process offroad
            if (segType === 8) {
                lockUpdateLvl = lockLvls.offRoadLock;
                enUpdate = true;
            }
            // Process non-routable ped path
            if (segType === 10) {
                lockUpdateLvl = lockLvls.nrpedLock;
                enUpdate = true;
            }
            // Process Ferry
            if (segType === 15) {
                lockUpdateLvl = lockLvls.fryLock;
                enUpdate = true;
            }
            // Process PVT
            if (segType === 17) {
                lockUpdateLvl = lockLvls.pvtLock;
                if ((conditions.isOneWay && lockLvls.pvtOneWay && oneWayChkd)
                    || (conditions.isTollRoad && lockLvls.tollLock && tollChkd)
                    || (conditions.isUnpaved && lockLvls.unpavedLock && unpavedChkd)) {
                    if (lockUpdateLvl === null) lockUpdateLvl = 1;
                    else lockUpdateLvl++;
                }
                enUpdate = true;
            }
            // Process Railroads
            if (segType === 18) {
                lockUpdateLvl = lockLvls.rrLock;
                enUpdate = true;
            }
            // Process Runways
            if (segType === 19) {
                lockUpdateLvl = lockLvls.rnwyLock;
                enUpdate = true;
            }
            // Process PLR
            if (segType === 20) {
                lockUpdateLvl = lockLvls.plrLock;
                if ((conditions.isOneWay && lockLvls.plrOneWay && oneWayChkd)
                    || (conditions.isTollRoad && lockLvls.tollLock && tollChkd)
                    || (conditions.isUnpaved && lockLvls.unpavedLock && unpavedChkd)) {
                    if (lockUpdateLvl === null) lockUpdateLvl = 1;
                    else lockUpdateLvl++;
                }
                enUpdate = true;
            }

            if (lockUpdateLvl === -1) lockUpdateLvl = 0;
        }
    }

    if (enUpdate) return lockUpdateLvl;
    return false;
}

function relockAll() {
    let count = 0;
    const resetHigher = getId('lsEnableResetHigher').checked;

    if (getCurrentState()) {
        _.each(W.model.segments.getObjectArray(), v => {
            const segAtt = v.attributes;
            const currLockRnk = segAtt.lockRank;
            let updateSuccess;

            const stdLockRank = processSegment(v);

            if (stdLockRank !== false) {
                if (currLockRnk < stdLockRank || (currLockRnk > stdLockRank && resetHigher)) updateSuccess = processLocks(v, currLockRnk, stdLockRank);
            }
            if (updateSuccess) count++;
        });
        resetUISegStats();

        if (count > 0) WazeWrap.Alerts.info(GM_info.script.name, `Locked ${count} segments`);
        else WazeWrap.Alerts.info(GM_info.script.name, 'No segments out of standards');
    }
}

function tryScan() {
    if (getId('lsEnableActiveScan').checked) scanArea();
}

function scanArea() {
    // Start by resetting UI scan elements
    resetUISegStats();
    getCurrentState();

    // Object with array of roadtypes, to collect each wrongly locked segment, for later use
    const badLockSegs = {
        ls: [], ps: [], mih: [], mah: [], rmp: [], fwy: [], plr: [], pvt: [], rail: [], fry: [], rnwy: [], ofrd: [], nrpd: [], othr: []
    };
    let incorrectLocks = false;
    let numWrongLocks = 0;
    const resetHigher = getId('lsEnableResetHigher').checked;
    const ignoreHigher = getId('lsEnableIgnoreRank').checked;

    function editorSufficientRank(segRank, standardRank) {
        if (_editorRank >= segRank && _editorRank >= standardRank) { return true; } return false;
    }

    // Count how many segments need a corrected lock (limit to 150 to save CPU), accounts for the users editor level
    _.each(W.model.segments.getObjectArray(), v => {
        if (numWrongLocks < 150 && v.type === 'segment' && onScreen(v)) {
            const correctLockRank = processSegment(v);

            if (correctLockRank !== false) {
                const segGeo = v.geometry;
                const segType = v.attributes.roadType;
                const segLockRank = v.attributes.lockRank;

                // LS
                if (segType === 1) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.ls.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.ls.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // PS
                if (segType === 2) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.ps.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.ps.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Fwy
                if (segType === 3) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.fwy.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.fwy.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Rmp
                if (segType === 4) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.rmp.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.rmp.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // MH
                if (segType === 6) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.mah.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.mah.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // mH
                if (segType === 7) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.mih.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.mih.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Offroad
                if (segType === 8) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.ofrd.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.ofrd.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Non-Routable Ped
                if (segType === 10) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.nrpd.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.nrpd.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Ferry
                if (segType === 15) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.fry.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.fry.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Pvt
                if (segType === 17) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.pvt.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.pvt.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Railroads
                if (segType === 18) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.rail.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.rail.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // Runway
                if (segType === 19) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.rnwy.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.rnwy.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // PLR
                if (segType === 20) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.plr.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.plr.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
                // All other segment types
                if (segType === 8 || segType === 10 || segType === 15 || segType === 17 || segType === 18 || segType === 19 || segType === 20) {
                    if (resetHigher && segLockRank > correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.othr.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'high'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('high', segGeo);
                    }
                    if (segLockRank < correctLockRank && (editorSufficientRank(segLockRank, correctLockRank) || ignoreHigher)) {
                        badLockSegs.othr.push({
                            segID: v.attributes.id, currLockRnk: segLockRank, stdLockRnk: correctLockRank, lockError: 'low'
                        });
                        incorrectLocks = true;
                        numWrongLocks++;
                        highlightSegments('low', segGeo);
                    }
                }
            }
        }
    });

    function highlightSegments(errorType, segGeo) {
        const enableHighlight = getId('lsEnableHighlightSeg').checked;
        if (enableHighlight) {
            const style = {
                strokeColor: '', strokeLinecap: 'round', strokeWidth: 18, fill: false, strokeOpacity: 0.5
            };
            if (errorType === 'high') { style.strokeColor = 'cyan'; } else { style.strokeColor = 'red'; }

            const geo = segGeo.clone();
            const feature = new OL.Feature.Vector(geo, {}, style);
            LocksmithHighlightLayer.addFeatures([feature]);
        }
    }

    // Enable/configure UI elements if bad segments are found
    let lsLow = 0; let lsHigh = 0;
    let psLow = 0; let psHigh = 0;
    let miLow = 0; let miHigh = 0;
    let maLow = 0; let maHigh = 0;
    let rmpLow = 0; let rmpHigh = 0;
    let fwyLow = 0; let fwyHigh = 0;
    let othrLow = 0; let othrHigh = 0;
    let plrLow = 0; let plrHigh = 0;
    let pvtLow = 0; let pvtHigh = 0;
    let railLow = 0; let railHigh = 0;
    let fryLow = 0; let fryHigh = 0;
    let rnwyLow = 0; let rnwyHigh = 0;
    let ofrdLow = 0; let ofrdHigh = 0;
    let nrpdLow = 0; let nrpdHigh = 0;
    if (incorrectLocks) {
        _.each(badLockSegs, (key, value) => {
            if (value === 'ls') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') lsHigh++;
                    if (key[i].lockError === 'low') lsLow++;
                }
                if (lsHigh > 0 || lsLow > 0) {
                    changeUI('#icon-Lock-LS', 1, 'lock', 'both');
                    $('#icon-Lock-LS').click(() => {
                        for (let i = 0; i < badLockSegs.ls.length; i++) {
                            const aryData = badLockSegs.ls[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-LS', 0, 'lock', null);
                        changeUI('#ls-LS-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-LS-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-LS-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-LS-High-Quan', 1, 'text', '--');
                    });
                    if (lsHigh > 0) {
                        changeUI('#ls-LS-High-Quan', 1, 'text', lsHigh);
                        changeUI('#ls-LS-Lock-Down', 1, 'lock', 'high');

                        $('#ls-LS-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.ls.length; i++) {
                                const aryData = badLockSegs.ls[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-LS-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-LS-High-Quan', 1, 'text', '--');
                            lsHigh = 0;
                            if (lsLow === 0) changeUI('#icon-Lock-LS', 0, 'lock', null);
                        });
                    }
                    if (lsLow > 0) {
                        changeUI('#ls-LS-Low-Quan', 1, 'text', lsLow);
                        changeUI('#ls-LS-Lock-Up', 1, 'lock', 'low');

                        $('#ls-LS-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.ls.length; i++) {
                                const aryData = badLockSegs.ls[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-LS-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-LS-Low-Quan', 1, 'text', '--');
                            lsLow = 0;
                            if (lsHigh === 0) changeUI('#icon-Lock-LS', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'ps') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') psHigh++;
                    if (key[i].lockError === 'low') psLow++;
                }
                if (psHigh > 0 || psLow > 0) {
                    changeUI('#icon-Lock-PS', 1, 'lock', 'both');
                    $('#icon-Lock-PS').click(() => {
                        for (let i = 0; i < badLockSegs.ps.length; i++) {
                            const aryData = badLockSegs.ps[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-PS', 0, 'lock', null);
                        changeUI('#ls-PS-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-PS-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-PS-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-PS-High-Quan', 1, 'text', '--');
                    });
                    if (psHigh > 0) {
                        changeUI('#ls-PS-High-Quan', 1, 'text', psHigh);
                        changeUI('#ls-PS-Lock-Down', 1, 'lock', 'high');

                        $('#ls-PS-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.ps.length; i++) {
                                const aryData = badLockSegs.ps[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-PS-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-PS-High-Quan', 1, 'text', '--');
                            psHigh = 0;
                            if (psLow === 0) changeUI('#icon-Lock-PS', 0, 'lock', null);
                        });
                    }
                    if (psLow > 0) {
                        changeUI('#ls-PS-Low-Quan', 1, 'text', psLow);
                        changeUI('#ls-PS-Lock-Up', 1, 'lock', 'low');

                        $('#ls-PS-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.ps.length; i++) {
                                const aryData = badLockSegs.ps[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-PS-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-PS-Low-Quan', 1, 'text', '--');
                            psLow = 0;
                            if (psHigh === 0) changeUI('#icon-Lock-PS', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'mih') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') miHigh++;
                    if (key[i].lockError === 'low') miLow++;
                }
                if (miHigh > 0 || miLow > 0) {
                    changeUI('#icon-Lock-minH', 1, 'lock', 'both');
                    $('#icon-Lock-minH').click(() => {
                        for (let i = 0; i < badLockSegs.mih.length; i++) {
                            const aryData = badLockSegs.mih[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-minH', 0, 'lock', null);
                        changeUI('#ls-minH-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-minH-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-minH-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-minH-High-Quan', 1, 'text', '--');
                    });
                    if (miHigh > 0) {
                        changeUI('#ls-minH-High-Quan', 1, 'text', miHigh);
                        changeUI('#ls-minH-Lock-Down', 1, 'lock', 'high');

                        $('#ls-minH-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.mih.length; i++) {
                                const aryData = badLockSegs.mih[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-minH-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-minH-High-Quan', 1, 'text', '--');
                            miHigh = 0;
                            if (miLow === 0) changeUI('#icon-Lock-minH', 0, 'lock', null);
                        });
                    }
                    if (miLow > 0) {
                        changeUI('#ls-minH-Low-Quan', 1, 'text', miLow);
                        changeUI('#ls-minH-Lock-Up', 1, 'lock', 'low');

                        $('#ls-minH-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.mih.length; i++) {
                                const aryData = badLockSegs.mih[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-minH-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-minH-Low-Quan', 1, 'text', '--');
                            miLow = 0;
                            if (miHigh === 0) changeUI('#icon-Lock-minH', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'mah') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') maHigh++;
                    if (key[i].lockError === 'low') maLow++;
                }
                if (maHigh > 0 || maLow > 0) {
                    changeUI('#icon-Lock-majH', 1, 'lock', 'both');
                    $('#icon-Lock-majH').click(() => {
                        for (let i = 0; i < badLockSegs.mah.length; i++) {
                            const aryData = badLockSegs.mah[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-majH', 0, 'lock', null);
                        changeUI('#ls-majH-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-majH-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-majH-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-majH-High-Quan', 1, 'text', '--');
                    });
                    if (maHigh > 0) {
                        changeUI('#ls-majH-High-Quan', 1, 'text', maHigh);
                        changeUI('#ls-majH-Lock-Down', 1, 'lock', 'high');

                        $('#ls-majH-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.mah.length; i++) {
                                const aryData = badLockSegs.mah[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-majH-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-majH-High-Quan', 1, 'text', '--');
                            maHigh = 0;
                            if (maLow === 0) changeUI('#icon-Lock-majH', 0, 'lock', null);
                        });
                    }
                    if (maLow > 0) {
                        changeUI('#ls-majH-Low-Quan', 1, 'text', maLow);
                        changeUI('#ls-majH-Lock-Up', 1, 'lock', 'low');

                        $('#ls-majH-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.mah.length; i++) {
                                const aryData = badLockSegs.mah[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-majH-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-majH-Low-Quan', 1, 'text', '--');
                            maLow = 0;
                            if (maHigh === 0) changeUI('#icon-Lock-majH', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'rmp') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') rmpHigh++;
                    if (key[i].lockError === 'low') rmpLow++;
                }
                if (rmpHigh > 0 || rmpLow > 0) {
                    changeUI('#icon-Lock-Rmp', 1, 'lock', 'both');
                    $('#icon-Lock-Rmp').click(() => {
                        for (let i = 0; i < badLockSegs.rmp.length; i++) {
                            const aryData = badLockSegs.rmp[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Rmp', 0, 'lock', null);
                        changeUI('#ls-Rmp-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Rmp-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Rmp-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Rmp-High-Quan', 1, 'text', '--');
                    });
                    if (rmpHigh > 0) {
                        changeUI('#ls-Rmp-High-Quan', 1, 'text', rmpHigh);
                        changeUI('#ls-Rmp-Lock-Down', 1, 'lock', 'high');

                        $('#ls-Rmp-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.rmp.length; i++) {
                                const aryData = badLockSegs.rmp[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Rmp-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Rmp-High-Quan', 1, 'text', '--');
                            rmpHigh = 0;
                            if (rmpLow === 0) changeUI('#icon-Lock-Rmp', 0, 'lock', null);
                        });
                    }
                    if (rmpLow > 0) {
                        changeUI('#ls-Rmp-Low-Quan', 1, 'text', rmpLow);
                        changeUI('#ls-Rmp-Lock-Up', 1, 'lock', 'low');

                        $('#ls-Rmp-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.rmp.length; i++) {
                                const aryData = badLockSegs.rmp[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Rmp-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Rmp-Low-Quan', 1, 'text', '--');
                            rmpLow = 0;
                            if (rmpHigh === 0) changeUI('#icon-Lock-Rmp', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'fwy') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') fwyHigh++;
                    if (key[i].lockError === 'low') fwyLow++;
                }
                if (fwyHigh > 0 || fwyLow > 0) {
                    changeUI('#icon-Lock-Fwy', 1, 'lock', 'both');
                    $('#icon-Lock-Fwy').click(() => {
                        for (let i = 0; i < badLockSegs.fwy.length; i++) {
                            const aryData = badLockSegs.fwy[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Fwy', 0, 'lock', null);
                        changeUI('#ls-Fwy-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Fwy-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Fwy-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Fwy-High-Quan', 1, 'text', '--');
                    });
                    if (fwyHigh > 0) {
                        changeUI('#ls-Fwy-High-Quan', 1, 'text', fwyHigh);
                        changeUI('#ls-Fwy-Lock-Down', 1, 'lock', 'high');

                        $('#ls-Fwy-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.fwy.length; i++) {
                                const aryData = badLockSegs.fwy[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Fwy-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Fwy-High-Quan', 1, 'text', '--');
                            fwyHigh = 0;
                            if (fwyLow === 0) changeUI('#icon-Lock-Fwy', 0, 'lock', null);
                        });
                    }
                    if (fwyLow > 0) {
                        changeUI('#ls-Fwy-Low-Quan', 1, 'text', fwyLow);
                        changeUI('#ls-Fwy-Lock-Up', 1, 'lock', 'low');

                        $('#ls-Fwy-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.fwy.length; i++) {
                                const aryData = badLockSegs.fwy[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Fwy-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Fwy-Low-Quan', 1, 'text', '--');
                            fwyLow = 0;
                            if (fwyHigh === 0) changeUI('#icon-Lock-Fwy', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'othr') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') othrHigh++;
                    if (key[i].lockError === 'low') othrLow++;
                }
                if (othrHigh > 0 || othrLow > 0) {
                    changeUI('#icon-Lock-othr', 1, 'lock', 'both');
                    $('#icon-Lock-othr').click(() => {
                        for (let i = 0; i < badLockSegs.othr.length; i++) {
                            const aryData = badLockSegs.othr[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-othr', 0, 'lock', null);
                        changeUI('#ls-othr-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-othr-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-othr-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-othr-High-Quan', 1, 'text', '--');
                    });
                    if (othrHigh > 0) {
                        changeUI('#ls-othr-High-Quan', 1, 'text', othrHigh);
                        changeUI('#ls-othr-Lock-Down', 1, 'lock', 'high');
                        $('#ls-othr-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.othr.length; i++) {
                                const aryData = badLockSegs.othr[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-othr-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-othr-High-Quan', 1, 'text', '--');
                            othrHigh = 0;
                            if (othrLow === 0) changeUI('#icon-Lock-othr', 0, 'lock', null);
                        });
                    }
                    if (othrLow > 0) {
                        changeUI('#ls-othr-Low-Quan', 1, 'text', othrLow);
                        changeUI('#ls-othr-Lock-Up', 1, 'lock', 'low');
                        $('#ls-othr-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.othr.length; i++) {
                                const aryData = badLockSegs.othr[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-othr-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-othr-Low-Quan', 1, 'text', '--');
                            othrLow = 0;
                            if (othrHigh === 0) changeUI('#icon-Lock-othr', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'plr') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') plrHigh++;
                    if (key[i].lockError === 'low') plrLow++;
                }
                if (plrHigh > 0 || plrLow > 0) {
                    changeUI('#icon-Lock-Plr', 1, 'lock', 'both');
                    $('#icon-Lock-Plr').click(() => {
                        for (let i = 0; i < badLockSegs.plr.length; i++) {
                            const aryData = badLockSegs.plr[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Plr', 0, 'lock', null);
                        changeUI('#ls-Plr-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Plr-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Plr-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Plr-High-Quan', 1, 'text', '--');
                    });
                    if (plrHigh > 0) {
                        changeUI('#ls-Plr-High-Quan', 1, 'text', plrHigh);
                        changeUI('#ls-Plr-Lock-Down', 1, 'lock', 'high');
                        $('#ls-Plr-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.plr.length; i++) {
                                const aryData = badLockSegs.plr[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Plr-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Plr-High-Quan', 1, 'text', '--');
                            plrHigh = 0;
                            if (plrLow === 0) changeUI('#icon-Lock-Plr', 0, 'lock', null);
                        });
                    }
                    if (plrLow > 0) {
                        changeUI('#ls-Plr-Low-Quan', 1, 'text', plrLow);
                        changeUI('#ls-Plr-Lock-Up', 1, 'lock', 'low');
                        $('#ls-Plr-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.plr.length; i++) {
                                const aryData = badLockSegs.plr[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Plr-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Plr-Low-Quan', 1, 'text', '--');
                            plrLow = 0;
                            if (plrHigh === 0) changeUI('#icon-Lock-Plr', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'pvt') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') pvtHigh++;
                    if (key[i].lockError === 'low') pvtLow++;
                }
                if (pvtHigh > 0 || pvtLow > 0) {
                    changeUI('#icon-Lock-Pvt', 1, 'lock', 'both');
                    $('#icon-Lock-Pvt').click(() => {
                        for (let i = 0; i < badLockSegs.pvt.length; i++) {
                            const aryData = badLockSegs.pvt[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Pvt', 0, 'lock', null);
                        changeUI('#ls-Pvt-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Pvt-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Pvt-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Pvt-High-Quan', 1, 'text', '--');
                    });
                    if (pvtHigh > 0) {
                        changeUI('#ls-Pvt-High-Quan', 1, 'text', pvtHigh);
                        changeUI('#ls-Pvt-Lock-Down', 1, 'lock', 'high');
                        $('#ls-Pvt-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.pvt.length; i++) {
                                const aryData = badLockSegs.pvt[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Pvt-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Pvt-High-Quan', 1, 'text', '--');
                            pvtHigh = 0;
                            if (pvtLow === 0) changeUI('#icon-Lock-Pvt', 0, 'lock', null);
                        });
                    }
                    if (pvtLow > 0) {
                        changeUI('#ls-Pvt-Low-Quan', 1, 'text', pvtLow);
                        changeUI('#ls-Pvt-Lock-Up', 1, 'lock', 'low');
                        $('#ls-Pvt-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.pvt.length; i++) {
                                const aryData = badLockSegs.pvt[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Pvt-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Pvt-Low-Quan', 1, 'text', '--');
                            pvtLow = 0;
                            if (pvtHigh === 0) changeUI('#icon-Lock-Pvt', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'rail') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') railHigh++;
                    if (key[i].lockError === 'low') railLow++;
                }
                if (railHigh > 0 || railLow > 0) {
                    changeUI('#icon-Lock-Rail', 1, 'lock', 'both');
                    $('#icon-Lock-Rail').click(() => {
                        for (let i = 0; i < badLockSegs.rail.length; i++) {
                            const aryData = badLockSegs.rail[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Rail', 0, 'lock', null);
                        changeUI('#ls-Rail-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Rail-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Rail-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Rail-High-Quan', 1, 'text', '--');
                    });
                    if (railHigh > 0) {
                        changeUI('#ls-Rail-High-Quan', 1, 'text', railHigh);
                        changeUI('#ls-Rail-Lock-Down', 1, 'lock', 'high');
                        $('#ls-Rail-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.rail.length; i++) {
                                const aryData = badLockSegs.rail[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Rail-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Rail-High-Quan', 1, 'text', '--');
                            railHigh = 0;
                            if (railLow === 0) changeUI('#icon-Lock-Rail', 0, 'lock', null);
                        });
                    }
                    if (railLow > 0) {
                        changeUI('#ls-Rail-Low-Quan', 1, 'text', railLow);
                        changeUI('#ls-Rail-Lock-Up', 1, 'lock', 'low');
                        $('#ls-Rail-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.rail.length; i++) {
                                const aryData = badLockSegs.rail[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Rail-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Rail-Low-Quan', 1, 'text', '--');
                            railLow = 0;
                            if (railHigh === 0) changeUI('#icon-Lock-Rail', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'fry') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') fryHigh++;
                    if (key[i].lockError === 'low') fryLow++;
                }
                if (fryHigh > 0 || fryLow > 0) {
                    changeUI('#icon-Lock-Fry', 1, 'lock', 'both');
                    $('#icon-Lock-Fry').click(() => {
                        for (let i = 0; i < badLockSegs.fry.length; i++) {
                            const aryData = badLockSegs.fry[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Fry', 0, 'lock', null);
                        changeUI('#ls-Fry-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Fry-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Fry-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Fry-High-Quan', 1, 'text', '--');
                    });
                    if (fryHigh > 0) {
                        changeUI('#ls-Fry-High-Quan', 1, 'text', fryHigh);
                        changeUI('#ls-Fry-Lock-Down', 1, 'lock', 'high');
                        $('#ls-Fry-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.fry.length; i++) {
                                const aryData = badLockSegs.fry[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Fry-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Fry-High-Quan', 1, 'text', '--');
                            fryHigh = 0;
                            if (fryLow === 0) changeUI('#icon-Lock-Fry', 0, 'lock', null);
                        });
                    }
                    if (fryLow > 0) {
                        changeUI('#ls-Fry-Low-Quan', 1, 'text', fryLow);
                        changeUI('#ls-Fry-Lock-Up', 1, 'lock', 'low');
                        $('#ls-Fry-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.fry.length; i++) {
                                const aryData = badLockSegs.fry[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Fry-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Fry-Low-Quan', 1, 'text', '--');
                            fryLow = 0;
                            if (fryHigh === 0) changeUI('#icon-Lock-Fry', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'rnwy') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') rnwyHigh++;
                    if (key[i].lockError === 'low') rnwyLow++;
                }
                if (rnwyHigh > 0 || rnwyLow > 0) {
                    changeUI('#icon-Lock-Rnwy', 1, 'lock', 'both');
                    $('#icon-Lock-Rnwy').click(() => {
                        for (let i = 0; i < badLockSegs.rnwy.length; i++) {
                            const aryData = badLockSegs.rnwy[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Rnwy', 0, 'lock', null);
                        changeUI('#ls-Rnwy-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Rnwy-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Rnwy-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Rnwy-High-Quan', 1, 'text', '--');
                    });
                    if (rnwyHigh > 0) {
                        changeUI('#ls-Rnwy-High-Quan', 1, 'text', rnwyHigh);
                        changeUI('#ls-Rnwy-Lock-Down', 1, 'lock', 'high');
                        $('#ls-Rnwy-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.rnwy.length; i++) {
                                const aryData = badLockSegs.rnwy[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Rnwy-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Rnwy-High-Quan', 1, 'text', '--');
                            rnwyHigh = 0;
                            if (rnwyLow === 0) changeUI('#icon-Lock-Rnwy', 0, 'lock', null);
                        });
                    }
                    if (rnwyLow > 0) {
                        changeUI('#ls-Rnwy-Low-Quan', 1, 'text', rnwyLow);
                        changeUI('#ls-Rnwy-Lock-Up', 1, 'lock', 'low');
                        $('#ls-Rnwy-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.rnwy.length; i++) {
                                const aryData = badLockSegs.rnwy[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Rnwy-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Rnwy-Low-Quan', 1, 'text', '--');
                            rnwyLow = 0;
                            if (rnwyHigh === 0) changeUI('#icon-Lock-Rnwy', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'ofrd') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') ofrdHigh++;
                    if (key[i].lockError === 'low') ofrdLow++;
                }
                if (ofrdHigh > 0 || ofrdLow > 0) {
                    changeUI('#icon-Lock-Ofrd', 1, 'lock', 'both');
                    $('#icon-Lock-Ofrd').click(() => {
                        for (let i = 0; i < badLockSegs.ofrd.length; i++) {
                            const aryData = badLockSegs.ofrd[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Ofrd', 0, 'lock', null);
                        changeUI('#ls-Ofrd-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Ofrd-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Ofrd-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Ofrd-High-Quan', 1, 'text', '--');
                    });
                    if (ofrdHigh > 0) {
                        changeUI('#ls-Ofrd-High-Quan', 1, 'text', ofrdHigh);
                        changeUI('#ls-Ofrd-Lock-Down', 1, 'lock', 'high');
                        $('#ls-Ofrd-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.ofrd.length; i++) {
                                const aryData = badLockSegs.ofrd[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Ofrd-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Ofrd-High-Quan', 1, 'text', '--');
                            ofrdHigh = 0;
                            if (ofrdLow === 0) changeUI('#icon-Lock-Ofrd', 0, 'lock', null);
                        });
                    }
                    if (ofrdLow > 0) {
                        changeUI('#ls-Ofrd-Low-Quan', 1, 'text', ofrdLow);
                        changeUI('#ls-Ofrd-Lock-Up', 1, 'lock', 'low');
                        $('#ls-Ofrd-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.ofrd.length; i++) {
                                const aryData = badLockSegs.ofrd[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Ofrd-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Ofrd-Low-Quan', 1, 'text', '--');
                            ofrdLow = 0;
                            if (ofrdHigh === 0) changeUI('#icon-Lock-Ofrd', 0, 'lock', null);
                        });
                    }
                }
            }
            if (value === 'nrpd') {
                for (let i = 0; i < key.length; i++) {
                    if (key[i].lockError === 'high') nrpdHigh++;
                    if (key[i].lockError === 'low') nrpdLow++;
                }
                if (nrpdHigh > 0 || nrpdLow > 0) {
                    changeUI('#icon-Lock-Nonped', 1, 'lock', 'both');
                    $('#icon-Lock-Nonped').click(() => {
                        for (let i = 0; i < badLockSegs.nrpd.length; i++) {
                            const aryData = badLockSegs.nrpd[i];
                            const seg = W.model.segments.getObjectById(aryData.segID);
                            processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                        }
                        changeUI('#icon-Lock-Nonped', 0, 'lock', null);
                        changeUI('#ls-Nonped-Lock-Up', 0, 'lock', null);
                        changeUI('#ls-Nonped-Lock-Down', 0, 'lock', null);
                        changeUI('#ls-Nonped-Low-Quan', 1, 'text', '--');
                        changeUI('#ls-Nonped-High-Quan', 1, 'text', '--');
                    });
                    if (nrpdHigh > 0) {
                        changeUI('#ls-Nonped-High-Quan', 1, 'text', nrpdHigh);
                        changeUI('#ls-Nonped-Lock-Down', 1, 'lock', 'high');
                        $('#ls-Nonped-Lock-Down').click(() => {
                            for (let i = 0; i < badLockSegs.nrpd.length; i++) {
                                const aryData = badLockSegs.nrpd[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'high') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Nonped-Lock-Down', 0, 'lock', null);
                            changeUI('#ls-Nonped-High-Quan', 1, 'text', '--');
                            nrpdHigh = 0;
                            if (nrpdLow === 0) changeUI('#icon-Lock-Nonped', 0, 'lock', null);
                        });
                    }
                    if (nrpdLow > 0) {
                        changeUI('#ls-Nonped-Low-Quan', 1, 'text', nrpdLow);
                        changeUI('#ls-Nonped-Lock-Up', 1, 'lock', 'low');
                        $('#ls-Nonped-Lock-Up').click(() => {
                            for (let i = 0; i < badLockSegs.nrpd.length; i++) {
                                const aryData = badLockSegs.nrpd[i];
                                const seg = W.model.segments.getObjectById(aryData.segID);
                                if (aryData.lockError === 'low') processLocks(seg, aryData.currLockRnk, aryData.stdLockRnk);
                            }
                            changeUI('#ls-Nonped-Lock-Up', 0, 'lock', null);
                            changeUI('#ls-Nonped-Low-Quan', 1, 'text', '--');
                            nrpdLow = 0;
                            if (nrpdHigh === 0) changeUI('#icon-Lock-Nonped', 0, 'lock', null);
                        });
                    }
                }
            }
        });

        let isActiveTab = $("a[href$='#sidepanel-lsus']").parent().prop('class');
        if (isActiveTab === '' || isActiveTab !== 'active') $("a[href$='#sidepanel-lsus']").css('background-color', '#ed503bb5');
    }
}

Locksmithbootstrap();