Greasy Fork is available in English.

WME Wide-Angle Lens Locks

Find segments that don't match lock levels

// ==UserScript==
// @name                WME Wide-Angle Lens Locks
// @namespace           https://greasyfork.org/en/users/19861-vtpearce
// @description         Find segments that don't match lock levels
// @author              vtpearce and crazycaveman
// @include             https://www.waze.com/editor
// @include             /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/
// @version             1.2.8
// @grant               none
// @copyright           2017 vtpearce
// @license             CC BY-SA 4.0
// ==/UserScript==

/*global W, OL, $, WazeWrap, WMEWAL*/

var WMEWAL_Locks;
(function (WMEWAL_Locks) {
    const scrName = GM_info.script.name;
    const Version = GM_info.script.version;
    const updateText = 'Fix Waze mucking around with roundabout attributes';
    const greasyForkPage = 'https://greasyfork.org/scripts/40643';
    const wazeForumThread = 'https://www.waze.com/forum/viewtopic.php?t=206376';

    var IncludeInOutput;
    (function (IncludeInOutput) {
        IncludeInOutput[IncludeInOutput["Low"] = 1] = "Low";
        IncludeInOutput[IncludeInOutput["High"] = 2] = "High";
    })(IncludeInOutput || (IncludeInOutput = {}));
    var Operation;
    (function (Operation) {
        Operation[Operation["Equal"] = 1] = "Equal";
        Operation[Operation["NotEqual"] = 2] = "NotEqual";
    })(Operation || (Operation = {}));
    var pluginName = "WMEWAL-Locks";
    WMEWAL_Locks.Title = "Locks";
    WMEWAL_Locks.MinimumZoomLevel = 2;
    WMEWAL_Locks.SupportsSegments = true;
    WMEWAL_Locks.SupportsVenues = false;
    var settingsKey = "WMEWALLocksSettings";
    var savedSettingsKey = "WMEWALLocksSavedSettings";
    var settings = null;
    var savedSettings = [];
    var streets = null;
    var state;
    var stateName;
    var nameRegex = null;
    var cityRegex = null;
    var initCount = 0;

    function GetTab() {
        var html = "<table style='border-collapse: separate; border-spacing:0px 1px;'>";
        html += "<tbody>";
        html += "<tr><td class='wal-heading' style='border-top: 1px solid;><b>Saved Settings</b></td></tr>";
        html += "<tr><td style='padding-left: 20px; padding-bottom: 8px'>" +
            "<select id='_wmewalLocksSavedSettings'/><br/>" +
            "<button class='btn btn-primary' id='_wmewalLocksLoadSetting' title='Load'>Load</button>" +
            "<button class='btn btn-primary' style='margin-left: 4px;' id='_wmewalLocksSaveSetting' title='Save'>Save</button>" +
            "<button class='btn btn-primary' style='margin-left: 4px;' id='_wmewalLocksDeleteSetting' title='Delete'>Delete</button></td></tr>";
        html += "<tr><td class='wal-heading' style='border-top: 1px solid; padding-top: 4px;'><b>Lock Levels</b></td></tr>";
        html += "<tr><td><table style='border-collapse: separate; border-spacing: 0px'>";
        html += "<tr><td><b>Include in output</b></td>" +
            "<td><select id='_wmewalLocksIncludeInOutput'>" +
            "<option value='" + IncludeInOutput.Low.toString() + "'>Locked too low</option>" +
            "<option value='" + IncludeInOutput.High.toString() + "'>Locked too high</option>" +
            "<option value='" + (IncludeInOutput.Low | IncludeInOutput.High).toString() + "'>Locked incorrectly</option></select></td></tr>";
        html += "<tr><td>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Street)) + "</td><td><select id='_wmewalLocksStreet'>" +
            "<option value='1' selected='selected'>1</option>" +
            "<option value='2'>2</option>" +
            "<option value='3'>3</option>" +
            "<option value='4'>4</option>" +
            "<option value='5'>5</option>" +
            "<option value='6'>6</option></select>" +
            "<br/><input id='_wmewalLocksPlusOneWayStreet' type='checkbox'/><label for='_wmewalLocksPlusOneWayStreet' style='margin-left: 8px'>+1 for One-Way</label>" +
            "</td></tr>";
        html += "<tr><td>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.PrimaryStreet)) + "</td><td><select id='_wmewalLocksPrimaryStreet'>" +
            "<option value='1'>1</option>" +
            "<option value='2' selected='selected'>2</option>" +
            "<option value='3'>3</option>" +
            "<option value='4'>4</option>" +
            "<option value='5'>5</option>" +
            "<option value='6'>6</option></select>" +
            "<br/><input id='_wmewalLocksPlusOneWayPS' type='checkbox'/><label for='_wmewalLocksPlusOneWayPS' style='margin-left: 8px'>+1 for One-Way</label></td></tr>";
        html += "<tr><td>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.MinorHighway)) + "</td><td><select id='_wmewalLocksMinorHighway'>" +
            "<option value='1'>1</option>" +
            "<option value='2'>2</option>" +
            "<option value='3' selected='selected'>3</option>" +
            "<option value='4'>4</option>" +
            "<option value='5'>5</option>" +
            "<option value='6'>6</option></select>" +
            "<br/><input id='_wmewalLocksPlusOneWayMinorH' type='checkbox'/><label for='_wmewalLocksPlusOneWayMinorH' style='margin-left: 8px'>+1 for One-Way</label></td></tr>";
        html += "<tr><td>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.MajorHighway)) + "</td><td><select id='_wmewalLocksMajorHighway'>" +
            "<option value='1'>1</option>" +
            "<option value='2'>2</option>" +
            "<option value='3'>3</option>" +
            "<option value='4' selected='selected'>4</option>" +
            "<option value='5'>5</option>" +
            "<option value='6'>6</option></select>" +
            "<br/><input id='_wmewalLocksPlusOneWayMajorH' type='checkbox'/><label for='_wmewalLocksPlusOneWayMajorH' style='margin-left: 8px'>+1 for One-Way</label></td></tr>";
        html += "<tr><td>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Freeway)) + "</td><td><select id='_wmewalLocksFreeway'>" +
            "<option value='1'>1</option>" +
            "<option value='2'>2</option>" +
            "<option value='3'>3</option>" +
            "<option value='4'>4</option>" +
            "<option value='5' selected='selected'>5</option>" +
            "<option value='6'>6</option></select>" +
            "<br/><input id='_wmewalLocksPlusOneWayFW' type='checkbox'/><label for='_wmewalLocksPlusOneWayFW' style='margin-left: 8px'>+1 for One-Way</label></td></tr>";
        html += "<tr><td>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Ramp)) + "</td><td><select id='_wmewalLocksRamp'>" +
            "<option value='7' selected='selected'>Highest connection</option>" +
            "<option value='1'>1</option>" +
            "<option value='2'>2</option>" +
            "<option value='3'>3</option>" +
            "<option value='4'>4</option>" +
            "<option value='5'>5</option>" +
            "<option value='6'>6</option></select>" +
            "<br/><input id='_wmewalLocksPlusOneWayRamp' type='checkbox'/><label for='_wmewalLocksPlusOneWayRamp' style='margin-left: 8px'>+1 for One-Way</label></td></tr>";
        html += "<tr><td>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Railroad)) + "</td><td><select id='_wmewalLocksRailroad'>" +
            "<option value='1'>1</option>" +
            "<option value='2' selected='selected'>2</option>" +
            "<option value='3'>3</option>" +
            "<option value='4'>4</option>" +
            "<option value='5'>5</option>" +
            "<option value='6'>6</option></select>" +
            "</td></tr>";
        html += "</table></td></tr>";
        html += "<tr><td class='wal-heading' style='border-top: 1px solid; padding-top: 4px;'><b>Filters</b></td></tr>";
        html += "<tr><td><b>Name RegEx:</b></td></tr>";
        html += "<tr><td style='padding-left: 20px'><input type='text' id='_wmewalLocksName' class='wal-textbox'/><br/>" +
            "<input id='_wmewalLocksIgnoreCase' type='checkbox'/>" +
            "<label for='_wmewalLocksIgnoreCase' style='margin-left: 8px'>Ignore case</label></td></tr>";
        html += "<tr><td><b>City RegEx:</b></td></tr>";
        html += "<tr><td style='padding-left: 20px'><input type='text' id='_wmewalLocksCity' class='wal-textbox'/><br/>" +
            "<input id='_wmewalLocksCityIgnoreCase' type='checkbox'/>" +
            "<label for='_wmewalLocksCityIgnoreCase' style='margin-left: 8px'>Ignore case</label></td></tr>";
        html += "<tr><td><b>State:</b></td></tr>";
        html += "<tr><td style='padding-left: 20px'>" +
            "<select id='_wmewalLocksStateOp'>" +
            "<option value='" + Operation.Equal.toString() + "' selected='selected'>=</option>" +
            "<option value='" + Operation.NotEqual.toString() + "'>&lt;&gt;</option></select>" +
            "<select id='_wmewalLocksState'/></td></tr>";
        html += "<tr><td><b>Road Type:</b></td></tr>";
        html += "<tr><td style='padding-left: 20px'>" +
            "<button id='_wmewalLocksRoadTypeAny' class='btn btn-primary' style='margin-right: 8px' title='Any'>Any</button>" +
            "<button id='_wmewalLocksRoadTypeClear' class='btn btn-primary' title='Clear'>Clear</button><br/>" +
            "<input type='checkbox' id='_wmewalLocksRoadTypeStreet' name='_wmewalLocksRoadType' value='" + WMEWAL.RoadType.Street.toString() + "'/>" +
            "<label for='_wmewalLocksRoadTypeStreet' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Street)) + "</label><br/>" +
            "<input type='checkbox' id='_wmewalLocksRoadTypePrimary' name='_wmewalLocksRoadType' value='" + WMEWAL.RoadType.PrimaryStreet.toString() + "'/>" +
            "<label for='_wmewalLocksRoadTypePrimary' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.PrimaryStreet)) + "</label><br/>" +
            "<input type='checkbox' id='_wmewalLocksRoadTypeMinorHighway' name='_wmewalLocksRoadType' value='" + WMEWAL.RoadType.MinorHighway.toString() + "'/>" +
            "<label for='_wmewalLocksRoadTypeMinorHighway' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.MinorHighway)) + "</label><br/>" +
            "<input type='checkbox' id='_wmewalLocksRoadTypeMajorHighway' name='_wmewalLocksRoadType' value='" + WMEWAL.RoadType.MajorHighway.toString() + "'/>" +
            "<label for='_wmewalLocksRoadTypeMajorHighway' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.MajorHighway)) + "</label><br/>" +
            "<input type='checkbox' id='_wmewalLocksRoadTypeRamp' name='_wmewalLocksRoadType' value='" + WMEWAL.RoadType.Ramp.toString() + "'/>" +
            "<label for='_wmewalLocksRoadTypeRamp' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Ramp)) + "</label><br/>" +
            "<input type='checkbox' checked='checked' id='_wmewalLocksRoadTypeFreeway' name='_wmewalLocksRoadType' value='" + WMEWAL.RoadType.Freeway.toString() + "'/>" +
            "<label for='_wmewalLocksRoadTypeFreeway' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Freeway)) + "</label><br/>" +
            "<input type='checkbox' checked='checked' id='_wmewalLocksRoadTypeRailroad' name='_wmewalLocksRoadType' value='" + WMEWAL.RoadType.Railroad.toString() + "'/>" +
            "<label for='_wmewalLocksRoadTypeRailroad' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Railroad)) + "</label>" +
            "</td></tr>";
        html += "<tr><td><input id='_wmewalLocksEditable' type='checkbox'/>" +
            "<label for='_wmewalLocksEditable' style='margin-left: 8px'>Editable by me</label></td></tr>";
        html += "<tr><td><input id='_wmewalLocksExcludeRoundabouts' type='checkbox'/>" +
            "<label for='_wmewalLocksExcludeRoundabouts' style='margin-left: 8px'>Exclude Roundabouts</label></td></tr>";
        html += "<tr><td><input id='_wmewalLocksExcludeJunctionBoxes' type='checkbox' checked='checked'/>" +
            "<label for='_wmewalLocksExcludeJunctionBoxes' style='margin-left: 8px'>Exclude Junction Boxes</label></td></tr>";
        html += "</tbody></table>";
        return html;
    }
    WMEWAL_Locks.GetTab = GetTab;
    function TabLoaded() {
        updateStates();
        updateUI();
        updateSavedSettingsList();
        $("#_wmewalLocksState").on("focus", updateStates);
        $("#_wmewalLocksRoadTypeAny").on("click", function () {
            $("input[name=_wmewalLocksRoadType]").prop("checked", true);
        });
        $("#_wmewalLocksRoadTypeClear").on("click", function () {
            $("input[name=_wmewalLocksRoadType]").prop("checked", false);
        });
        $("#_wmewalLocksLoadSetting").on("click", loadSetting);
        $("#_wmewalLocksSaveSetting").on("click", saveSetting);
        $("#_wmewalLocksDeleteSetting").on("click", deleteSetting);
    }
    WMEWAL_Locks.TabLoaded = TabLoaded;
    function updateStates() {
        var selectState = $("#_wmewalLocksState");
        // Preserve current selection
        var currentId = parseInt(selectState.val());
        selectState.empty();
        var stateObjs = [];
        stateObjs.push({ id: null, name: "" });
        for (var s in W.model.states.objects) {
            if (W.model.states.objects.hasOwnProperty(s)) {
                var st = W.model.states.getObjectById(parseInt(s));
                if (st.id !== 1 && st.name.length > 0) {
                    stateObjs.push({ id: st.id, name: st.name });
                }
            }
        }
        stateObjs.sort(function (a, b) {
            if (a.id == null) {
                return -1;
            }
            else {
                return a.name.localeCompare(b.name);
            }
        });
        for (var ix = 0; ix < stateObjs.length; ix++) {
            var so = stateObjs[ix];
            var stateOption = $("<option/>").text(so.name).attr("value", so.id);
            if (currentId != null && so.id === currentId) {
                stateOption.attr("selected", "selected");
            }
            selectState.append(stateOption);
        }
    }
    function updateSavedSettingsList() {
        var s = $("#_wmewalLocksSavedSettings");
        s.empty();
        for (var ixSaved = 0; ixSaved < savedSettings.length; ixSaved++) {
            var opt = $("<option/>").attr("value", ixSaved).text(savedSettings[ixSaved].Name);
            s.append(opt);
        }
    }
    function updateUI() {
        // $("#_wmewalLocksOutputTo").val(settings.OutputTo);
        $("#_wmewalLocksIncludeInOutput").val(settings.IncludeInOutput);
        $("#_wmewalLocksStreet").val(settings.StreetLockLevel);
        $("#_wmewalLocksPrimaryStreet").val(settings.PrimaryStreetLockLevel);
        $("#_wmewalLocksMinorHighway").val(settings.MinorHighwayLockLevel);
        $("#_wmewalLocksMajorHighway").val(settings.MajorHighwayLockLevel);
        $("#_wmewalLocksFreeway").val(settings.FreewayLockLevel);
        $("#_wmewalLocksRamp").val(settings.RampLockLevel);
        $("#_wmewalLocksRailroad").val(settings.RailroadLockLevel);
        $("#_wmewalLocksName").val(settings.Regex || "");
        $("#_wmewalLocksIgnoreCase").prop("checked", settings.RegexIgnoreCase);
        $("#_wmewalLocksCity").val(settings.CityRegex || "");
        $("#_wmewalLocksCityIgnoreCase").prop("checked", settings.CityRegexIgnoreCase);
        $("#_wmewalLocksState").val(settings.State);
        $("#_wmewalLocksRoadTypeStreet").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Street);
        $("#_wmewalLocksRoadTypePrimary").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.PrimaryStreet);
        $("#_wmewalLocksRoadTypeMinorHighway").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.MinorHighway);
        $("#_wmewalLocksRoadTypeMajorHighway").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.MajorHighway);
        $("#_wmewalLocksRoadTypeRamp").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Ramp);
        $("#_wmewalLocksRoadTypeFreeway").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Freeway);
        $("#_wmewalLocksRoadTypeRailroad").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Railroad);
        $("#_wmewalLocksEditable").prop("checked", settings.EditableByMe);
        $("#_wmewalLocksExcludeRoundabouts").prop("checked", settings.ExcludeRoundabouts);
        $("#_wmewalLocksExcludeJunctionBoxes").prop("checked", settings.ExcludeJunctionBoxes);
        $("#_wmewalLocksPlusOneWayStreet").prop("checked", settings.PlusOneWayMask & WMEWAL.RoadType.Street);
        $("#_wmewalLocksPlusOneWayPS").prop("checked", settings.PlusOneWayMask & WMEWAL.RoadType.PrimaryStreet);
        $("#_wmewalLocksPlusOneWayMinorH").prop("checked", settings.PlusOneWayMask & WMEWAL.RoadType.MinorHighway);
        $("#_wmewalLocksPlusOneWayMajorH").prop("checked", settings.PlusOneWayMask & WMEWAL.RoadType.MajorHighway);
        $("#_wmewalLocksPlusOneWayFW").prop("checked", settings.PlusOneWayMask & WMEWAL.RoadType.Freeway);
        $("#_wmewalLocksPlusOneWayRamp").prop("checked", settings.PlusOneWayMask & WMEWAL.RoadType.Ramp);
        $("#_wmewalLocksStateOp").val(settings.StateOperation || Operation.Equal.toString());
    }
    function loadSetting() {
        var selectedSetting = parseInt($("#_wmewalLocksSavedSettings").val());
        if (selectedSetting == null || isNaN(selectedSetting) || selectedSetting < 0 || selectedSetting > savedSettings.length) {
            return;
        }
        var savedSetting = savedSettings[selectedSetting].Setting;
        // settings.OutputTo = $("#_wmewalLocksOutputTo").val();
        for (var name_1 in savedSetting) {
            if (settings.hasOwnProperty(name_1)) {
                settings[name_1] = savedSetting[name_1];
            }
        }
        updateUI();
    }
    function validateSettings() {
        var allOk = true;
        var message = "";
        var mask = 0;
        $("input[name=_wmewalLocksRoadType]:checked").each(function (ix, e) {
            mask = mask | parseInt(e.value);
        });
        if (mask === 0) {
            message = "Please select at least one road type.";
            allOk = false;
        }
        var selectedState = $("#_wmewalLocksState").val();
        if (selectedState != null && selectedState.length > 0) {
            if (W.model.states.getObjectById(selectedState) == null) {
                message += ((message.length > 0 ? "\n" : "") + "Invalid state selection");
                allOk = false;
            }
        }
        var ignoreCase = $("#_wmewalLocksIgnoreCase").prop("checked");
        var pattern = $("#_wmewalLocksName").val();
        var r;
        if (pattern.length > 0) {
            try {
                r = (ignoreCase ? new RegExp(pattern, "i") : new RegExp(pattern));
            }
            catch (error) {
                message += ((message.length > 0 ? "\n" : "") + "Name RegEx is invalid");
                allOk = false;
            }
        }
        ignoreCase = $("#_wmewalLocksCityIgnoreCase").prop("checked");
        pattern = $("#_wmewalLocksCity").val();
        if (pattern.length > 0) {
            try {
                r = (ignoreCase ? new RegExp(pattern, "i") : new RegExp(pattern));
            }
            catch (error) {
                message += ((message.length > 0 ? "\n" : "") + "City RegEx is invalid");
                allOk = false;
            }
        }
        if (!allOk) {
            alert(pluginName + ": " + message);
        }
        return allOk;
    }
    function saveSetting() {
        if (validateSettings()) {
            var plusOneWayMask = 0;
            var s_1 = {
                RoadTypeMask: null,
                State: null,
                Regex: null,
                RegexIgnoreCase: $("#_wmewalLocksIgnoreCase").prop("checked"),
                ExcludeJunctionBoxes: $("#_wmewalLocksExcludeJunctionBoxes").prop("checked"),
                ExcludeRoundabouts: $("#_wmewalLocksExcludeRoundabouts").prop("checked"),
                EditableByMe: $("#_wmewalLocksEditable").prop("checked"),
                StreetLockLevel: parseInt($("#_wmewalLocksStreet").val()),
                PrimaryStreetLockLevel: parseInt($("#_wmewalLocksPrimaryStreet").val()),
                MinorHighwayLockLevel: parseInt($("#_wmewalLocksMinorHighway").val()),
                MajorHighwayLockLevel: parseInt($("#_wmewalLocksMajorHighway").val()),
                FreewayLockLevel: parseInt($("#_wmewalLocksFreeway").val()),
                RampLockLevel: parseInt($("#_wmewalLocksRamp").val()),
                IncludeInOutput: parseInt($("#_wmewalLocksIncludeInOutput").val()),
                PlusOneWayMask: plusOneWayMask,
                CityRegex: null,
                CityRegexIgnoreCase: $("#_wmewalLocksCityIgnoreCase").prop("checked"),
                StateOperation: parseInt($("#_wmewalLocksStateOp").val()),
                RailroadLockLevel: parseInt($("#_wmewalLocksRailroad").val())
            };
            s_1.RoadTypeMask = 0;
            $("input[name=_wmewalLocksRoadType]:checked").each(function (ix, e) {
                s_1.RoadTypeMask = s_1.RoadTypeMask | parseInt(e.value);
            });
            if ($("#_wmewalLocksPlusOneWayStreet").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.Street;
            }
            if ($("#_wmewalLocksPlusOneWayPS").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.PrimaryStreet;
            }
            if ($("#_wmewalLocksPlusOneWayMinorH").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.MinorHighway;
            }
            if ($("#_wmewalLocksPlusOneWayMajorH").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.MajorHighway;
            }
            if ($("#_wmewalLocksPlusOneWayFW").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.Freeway;
            }
            if ($("#_wmewalLocksPlusOneWayRamp").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.Ramp;
            }
            var selectedState = $("#_wmewalLocksState").val();
            if (selectedState != null && selectedState.length > 0) {
                s_1.State = W.model.states.getObjectById(parseInt(selectedState)).id;
            }
            var pattern = $("#_wmewalLocksName").val();
            if (pattern.length > 0) {
                s_1.Regex = pattern;
            }
            pattern = $("#_wmewalLocksCity").val();
            if (pattern.length > 0) {
                s_1.CityRegex = pattern;
            }
            var sName = prompt("Enter a name for this setting");
            if (sName == null) {
                return;
            }
            // Check to see if there is already a name that matches this
            for (var ixSetting = 0; ixSetting < savedSettings.length; ixSetting++) {
                if (savedSettings[ixSetting].Name === sName) {
                    if (confirm("A setting with this name already exists. Overwrite?")) {
                        savedSettings[ixSetting].Setting = s_1;
                        updateSavedSettings();
                    }
                    else {
                        alert("Please pick a new name.");
                    }
                    return;
                }
            }
            var savedSetting = {
                Name: sName,
                Setting: s_1
            };
            savedSettings.push(savedSetting);
            updateSavedSettings();
        }
    }
    function deleteSetting() {
        var selectedSetting = parseInt($("#_wmewalLocksSavedSettings").val());
        if (selectedSetting == null || isNaN(selectedSetting) || selectedSetting < 0 || selectedSetting > savedSettings.length) {
            return;
        }
        if (confirm("Are you sure you want to delete this saved setting?")) {
            savedSettings.splice(selectedSetting, 1);
            updateSavedSettings();
        }
    }
    function ScanStarted() {
        var allOk = validateSettings();
        streets = [];
        if (allOk) {
            // settings.OutputTo = $("#_wmewalLocksOutputTo").val();
            settings.RoadTypeMask = 0;
            $("input[name=_wmewalLocksRoadType]:checked").each(function (ix, e) {
                settings.RoadTypeMask = settings.RoadTypeMask | parseInt(e.value);
            });
            var selectedState = $("#_wmewalLocksState").val();
            state = null;
            settings.State = null;
            stateName = null;
            if (selectedState != null && selectedState.length > 0) {
                state = W.model.states.getObjectById(selectedState);
                settings.State = state.id;
                stateName = state.name;
            }
            settings.StateOperation = parseInt($("#_wmewalLocksStateOp").val());
            settings.RegexIgnoreCase = $("#_wmewalLocksIgnoreCase").prop("checked");
            var pattern = $("#_wmewalLocksName").val();
            settings.Regex = null;
            nameRegex = null;
            if (pattern.length > 0) {
                settings.Regex = pattern;
                nameRegex = (settings.RegexIgnoreCase ? new RegExp(pattern, "i") : new RegExp(pattern));
            }
            settings.CityRegexIgnoreCase = $("#_wmewalLocksCityIgnoreCase").prop("checked");
            pattern = $("#_wmewalLocksCity").val();
            settings.CityRegex = null;
            cityRegex = null;
            if (pattern.length > 0) {
                settings.CityRegex = pattern;
                cityRegex = (settings.CityRegexIgnoreCase ? new RegExp(pattern, "i") : new RegExp(pattern));
            }
            settings.ExcludeRoundabouts = $("#_wmewalLocksExcludeRoundabouts").prop("checked");
            settings.ExcludeJunctionBoxes = $("#_wmewalLocksExcludeJunctionBoxes").prop("checked");
            settings.EditableByMe = $("#_wmewalLocksEditable").prop("checked");
            settings.StreetLockLevel = parseInt($("#_wmewalLocksStreet").val());
            settings.PrimaryStreetLockLevel = parseInt($("#_wmewalLocksPrimaryStreet").val());
            settings.MinorHighwayLockLevel = parseInt($("#_wmewalLocksMinorHighway").val());
            settings.MajorHighwayLockLevel = parseInt($("#_wmewalLocksMajorHighway").val());
            settings.FreewayLockLevel = parseInt($("#_wmewalLocksFreeway").val());
            settings.RampLockLevel = parseInt($("#_wmewalLocksRamp").val());
            settings.RailroadLockLevel = parseInt($("#_wmewalLocksRailroad").val());
            settings.IncludeInOutput = parseInt($("#_wmewalLocksIncludeInOutput").val());
            var plusOneWayMask = 0;
            if ($("#_wmewalLocksPlusOneWayStreet").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.Street;
            }
            if ($("#_wmewalLocksPlusOneWayPS").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.PrimaryStreet;
            }
            if ($("#_wmewalLocksPlusOneWayMinorH").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.MinorHighway;
            }
            if ($("#_wmewalLocksPlusOneWayMajorH").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.MajorHighway;
            }
            if ($("#_wmewalLocksPlusOneWayFW").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.Freeway;
            }
            if ($("#_wmewalLocksPlusOneWayRamp").prop("checked")) {
                plusOneWayMask = plusOneWayMask | WMEWAL.RoadType.Ramp;
            }
            settings.PlusOneWayMask = plusOneWayMask;
            if (settings.RoadTypeMask & 1 || settings.RoadTypeMask & 4096) {
                WMEWAL_Locks.MinimumZoomLevel = 4;
            }
            else {
                WMEWAL_Locks.MinimumZoomLevel = 2;
            }
            updateSettings();
        }
        return allOk;
    }
    WMEWAL_Locks.ScanStarted = ScanStarted;
    function isOneWay(segment) {
        return segment.attributes.fwdDirection !== segment.attributes.revDirection && (segment.attributes.fwdDirection || segment.attributes.revDirection);
    }
    function ScanExtent(segments, venues) {
        var def = $.Deferred();
        var extentStreets = [];
        function addSegment(s, rId) {
            var sid = s.attributes.primaryStreetID;
            var address = s.getAddress();
            var thisStreet = null;
            if (sid != null) {
                // let street = W.model.streets.getObjectById(sid);
                thisStreet = extentStreets.find(function (e) {
                    var matches = (e.id === sid && (e.lockLevel === (s.attributes.lockRank || 0) + 1) && e.roundaboutId === rId && e.roadType === s.attributes.roadType);
                    if (matches && (nameRegex != null || cityRegex != null)) {
                        // Test for alt names
                        for (var ixAlt = 0; ixAlt < e.altStreets.length && matches; ixAlt++) {
                            matches = false;
                            for (var ixSegAlt = 0; ixSegAlt < address.attributes.altStreets.length && !matches; ixSegAlt++) {
                                if (e.altStreets[ixAlt].id === address.attributes.altStreets[ixSegAlt].id) {
                                    matches = true;
                                }
                            }
                        }
                    }
                    return matches;
                });
            }
            if (thisStreet == null) {
                thisStreet = {
                    id: sid,
                    city: ((address && !address.attributes.isEmpty && address.attributes.city.hasName()) ? address.attributes.city.attributes.name : "No City"),
                    state: ((address && !address.attributes.isEmpty) ? address.attributes.state.name : "No State"),
                    name: ((address && !address.attributes.isEmpty && !address.attributes.street.isEmpty) ? address.attributes.street.name : "No street"),
                    geometries: new OL.Geometry.Collection(),
                    lockLevel: (s.attributes.lockRank || 0) + 1,
                    segments: [],
                    roundaboutId: rId,
                    altStreets: [],
                    roadType: s.attributes.roadType
                };
                if (nameRegex != null) {
                    for (var ixAlt = 0; ixAlt < s.attributes.streetIDs.length; ixAlt++) {
                        var altStreet = W.model.streets.getObjectById(s.attributes.streetIDs[ixAlt]);
                        if (altStreet != null) {
                            thisStreet.altStreets.push({
                                id: s.attributes.streetIDs[ixAlt],
                                name: altStreet.name
                            });
                        }
                    }
                }
                extentStreets.push(thisStreet);
            }
            thisStreet.segments.push({
                id: s.attributes.id,
                center: s.attributes.geometry.getCentroid()
            });
            thisStreet.geometries.addComponents([s.attributes.geometry.clone()]);
        }
        for (var ix = 0; ix < segments.length; ix++) {
            var segment = segments[ix];
            if (segment != null) {
                if ((WMEWAL.WazeRoadTypeToRoadTypeBitmask(segment.attributes.roadType) & settings.RoadTypeMask) &&
                    (!settings.EditableByMe || segment.arePropertiesEditable()) &&
                    (!settings.ExcludeJunctionBoxes || !segment.isInBigJunction())) {
                    var address = segment.getAddress();
                    if (state != null) {
                        if (address != null && address.attributes != null && !address.attributes.isEmpty && address.attributes.state != null) {
                            if (settings.StateOperation === Operation.Equal && address.attributes.state.id !== state.id ||
                                settings.StateOperation === Operation.NotEqual && address.attributes.state.id === state.id) {
                                continue;
                            }
                        }
                        else if (settings.StateOperation === Operation.Equal) {
                            continue;
                        }
                    }
                    var plusOne = (isOneWay(segment) && (WMEWAL.WazeRoadTypeToRoadTypeBitmask(segment.attributes.roadType) & settings.PlusOneWayMask)) ? 1 : 0;
                    var incorrectLock = false;
                    switch (segment.attributes.roadType) {
                        case 1:
                            if ((settings.IncludeInOutput & IncludeInOutput.Low && (segment.attributes.lockRank || 0) + 1 < settings.StreetLockLevel + plusOne) ||
                                (settings.IncludeInOutput & IncludeInOutput.High && (segment.attributes.lockRank || 0) + 1 > settings.StreetLockLevel + plusOne)) {
                                incorrectLock = true;
                            }
                            break;
                        case 2:
                            if ((settings.IncludeInOutput & IncludeInOutput.Low && (segment.attributes.lockRank || 0) + 1 < settings.PrimaryStreetLockLevel + plusOne) ||
                                (settings.IncludeInOutput & IncludeInOutput.High && (segment.attributes.lockRank || 0) + 1 > settings.PrimaryStreetLockLevel + plusOne)) {
                                incorrectLock = true;
                            }
                            break;
                        case 3:
                            if ((settings.IncludeInOutput & IncludeInOutput.Low && (segment.attributes.lockRank || 0) + 1 < settings.FreewayLockLevel + plusOne) ||
                                (settings.IncludeInOutput & IncludeInOutput.High && (segment.attributes.lockRank || 0) + 1 > settings.FreewayLockLevel + plusOne)) {
                                incorrectLock = true;
                            }
                            break;
                        case 4:
                            var expectedLockRank = 0;
                            if (settings.RampLockLevel === 7) {
                                // Find lock rank of every connected segment
                                var fromSegments = segment.getConnectedSegments("from");
                                for (var ix_1 = 0; ix_1 < fromSegments.length; ix_1++) {
                                    if (fromSegments[ix_1].attributes.id !== segment.attributes.id && (fromSegments[ix_1].attributes.lockRank || 0) + 1 > expectedLockRank) {
                                        expectedLockRank = (fromSegments[ix_1].attributes.lockRank || 0) + 1;
                                    }
                                }
                                var toSegments = segment.getConnectedSegments("to");
                                for (var ix_2 = 0; ix_2 < toSegments.length; ix_2++) {
                                    if (toSegments[ix_2].attributes.id !== segment.attributes.id && (toSegments[ix_2].attributes.lockRank || 0) + 1 > expectedLockRank) {
                                        expectedLockRank = (toSegments[ix_2].attributes.lockRank || 0) + 1;
                                    }
                                }
                            }
                            else {
                                expectedLockRank = settings.RampLockLevel;
                            }
                            expectedLockRank += plusOne;
                            if ((settings.IncludeInOutput & IncludeInOutput.Low && (segment.attributes.lockRank || 0) + 1 < expectedLockRank) ||
                                (settings.IncludeInOutput & IncludeInOutput.High && (segment.attributes.lockRank || 0) + 1 > expectedLockRank)) {
                                incorrectLock = true;
                            }
                            break;
                        case 6:
                            if ((settings.IncludeInOutput & IncludeInOutput.Low && (segment.attributes.lockRank || 0) + 1 < settings.MajorHighwayLockLevel + plusOne) ||
                                (settings.IncludeInOutput & IncludeInOutput.High && (segment.attributes.lockRank || 0) + 1 > settings.MajorHighwayLockLevel + plusOne)) {
                                incorrectLock = true;
                            }
                            break;
                        case 7:
                            if ((settings.IncludeInOutput & IncludeInOutput.Low && (segment.attributes.lockRank || 0) + 1 < settings.MinorHighwayLockLevel + plusOne) ||
                                (settings.IncludeInOutput & IncludeInOutput.High && (segment.attributes.lockRank || 0) + 1 > settings.MinorHighwayLockLevel + plusOne)) {
                                incorrectLock = true;
                            }
                            break;
                        case 18:
                            if ((settings.IncludeInOutput & IncludeInOutput.Low && (segment.attributes.lockRank || 0) + 1 < settings.RailroadLockLevel + plusOne) ||
                                (settings.IncludeInOutput & IncludeInOutput.High && (segment.attributes.lockRank || 0) + 1 > settings.RailroadLockLevel + plusOne)) {
                                incorrectLock = true;
                            }
                            break;
                        default:
                            break;
                    }
                    if (!incorrectLock) {
                        continue;
                    }
                    if (nameRegex != null || cityRegex != null) {
                        var nameMatched = false;
                        if (address != null && address.attributes != null && !address.attributes.isEmpty) {
                            if (nameRegex != null && address.attributes.street != null) {
                                nameMatched = nameRegex.test(address.attributes.street.name);
                            }
                            if (!nameMatched && cityRegex != null && address.attributes.city != null && address.attributes.city.hasName()) {
                                nameMatched = cityRegex.test(address.attributes.city.attributes.name);
                            }
                            if (!nameMatched && segment.attributes.streetIDs != null) {
                                for (var streetIx = 0; streetIx < segment.attributes.streetIDs.length && !nameMatched; streetIx++) {
                                    if (segment.attributes.streetIDs[streetIx] != null) {
                                        var street = W.model.streets.getObjectById(segment.attributes.streetIDs[streetIx]);
                                        if (street != null) {
                                            if (nameRegex != null) {
                                                nameMatched = nameRegex.test(street.name);
                                            }
                                            if (!nameMatched && cityRegex != null && street.cityID != null) {
                                                var city = W.model.cities.getObjectById(street.cityID);
                                                if (city != null && city.hasName()) {
                                                    nameMatched = cityRegex.test(city.attributes.name);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (!nameMatched) {
                            continue;
                        }
                    }
                    if (!WMEWAL.IsSegmentInArea(segment)) {
                        continue;
                    }
                    if (!segment.isInRoundabout()) {
                        addSegment(segment, null);
                    }
                    else if (!settings.ExcludeRoundabouts) {
                        var r = segment.getRoundabout().attributes;
                        for (var rIx = 0; rIx < r.segIDs.length; rIx++) {
                            addSegment(W.model.segments.getObjectById(r.segIDs[rIx]), r.id);
                        }
                    }
                }
            }
        }
        for (var ix = 0; ix < extentStreets.length; ix++) {
            extentStreets[ix].center = extentStreets[ix].geometries.getCentroid(true);
            delete extentStreets[ix].geometries;
            streets.push(extentStreets[ix]);
        }
        def.resolve();
        return def.promise();
    }
    WMEWAL_Locks.ScanExtent = ScanExtent;
    function ScanComplete() {
        if (streets.length === 0) {
            alert(pluginName + ": No streets found.");
        }
        else {
            streets.sort(function (a, b) {
                var cmp = getStreetName(a).localeCompare(getStreetName(b));
                if (cmp !== 0) {
                    return cmp;
                }
                cmp = a.state.localeCompare(b.state);
                if (cmp !== 0) {
                    return cmp;
                }
                cmp = a.city.localeCompare(b.city);
                if (cmp !== 0) {
                    return cmp;
                }
                if (a.lockLevel < b.lockLevel) {
                    return -1;
                }
                else if (a.lockLevel > b.lockLevel) {
                    return 1;
                }
                return 0;
            });
            var outputTo = $("#_wmewalScanOutputTo").val();
            var isCSV = (outputTo === "csv" || outputTo === "both");
            var isTab = (outputTo === "tab" || outputTo === "both");
            var includeAltNames = (nameRegex != null || cityRegex != null);
            var lineArray = void 0;
            var columnArray = void 0;
            var w = void 0;
            var fileName = void 0;
            if (isCSV) {
                lineArray = [];
                columnArray = ["Name"];
                if (includeAltNames) {
                    columnArray.push("Alt Names");
                }
                columnArray.push("City");
                columnArray.push("State");
                columnArray.push("Road Type");
                columnArray.push("Lock Level");
                columnArray.push("Latitude");
                columnArray.push("Longitude");
                columnArray.push("Permalink");
                lineArray.push(columnArray);
                fileName = "Locks_" + WMEWAL.areaName;
                for (var rt in WMEWAL.RoadType) {
                    if (WMEWAL.RoadType.hasOwnProperty(rt)) {
                        var mask = parseInt(rt);
                        if (!isNaN(mask) && settings.RoadTypeMask & mask) {
                            fileName += "_" + WMEWAL.RoadType[mask.toString()];
                        }
                    }
                }
                fileName += ".csv";
            }
            if (isTab) {
                w = window.open();
                w.document.write("<html><head><title>Locks</title></head><body>");
                w.document.write("<h3>Area: " + WMEWAL.areaName + "</h3>");
                w.document.write("<b>Filters</b>");
                w.document.write("<br/>Road Type(s): ");
                var comma = "";
                for (var rt in WMEWAL.RoadType) {
                    if (WMEWAL.RoadType.hasOwnProperty(rt)) {
                        var mask = parseInt(rt);
                        if (!isNaN(mask) && settings.RoadTypeMask & mask) {
                            w.document.write(comma + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(mask)));
                            if (settings.PlusOneWayMask & mask) {
                                w.document.write(" (+1 for one-way)");
                            }
                            comma = ", ";
                        }
                    }
                }
                if (stateName != null) {
                    w.document.write("<br/>State " + (settings.StateOperation === Operation.NotEqual ? "does not equal " : "equals ") + stateName);
                }
                if (nameRegex != null) {
                    w.document.write("<br/>Name matches " + nameRegex.source);
                    if (settings.RegexIgnoreCase) {
                        w.document.write(" (ignoring case)");
                    }
                }
                if (cityRegex != null) {
                    w.document.write("</br/>City name matches " + cityRegex.source);
                    if (settings.CityRegexIgnoreCase) {
                        w.document.write(" (ignoring case)");
                    }
                }
                if (settings.ExcludeRoundabouts) {
                    w.document.write("<br/>Roundabouts excluded");
                }
                if (settings.ExcludeJunctionBoxes) {
                    w.document.write("<br/>Junction boxes excluded");
                }
                if (settings.EditableByMe) {
                    w.document.write("<br/>Editable by me");
                }
                w.document.write("</p><table style='border-collapse: separate; border-spacing: 8px 0px'><tr><th>Name</th>");
                if (includeAltNames) {
                    w.document.write("<th>Alt Names</th>");
                }
                w.document.write("<th>City</th><th>State</th>");
                w.document.write("<th>Road Type</th><th>Lock Level</th><th>Latitude</th><th>Longitude</th><th>Permalink</th></tr>");
            }
            for (var ixStreet = 0; ixStreet < streets.length; ixStreet++) {
                var street = streets[ixStreet];
                var roadTypeText = WMEWAL.TranslateRoadType(street.roadType);
                if (street.name == null && street.roundaboutId == null) {
                    for (var ixSeg = 0; ixSeg < street.segments.length; ixSeg++) {
                        var segment = street.segments[ixSeg];
                        var latlon = OL.Layer.SphericalMercator.inverseMercator(segment.center.x, segment.center.y);
                        var plSeg = getSegmentPL(segment);
                        if (isCSV) {
                            columnArray = [getStreetName(street)];
                            if (includeAltNames) {
                                columnArray.push("");
                            }
                            columnArray.push("\"" + street.city + "\"");
                            columnArray.push("\"" + street.state + "\"");
                            columnArray.push("\"" + roadTypeText + "\"");
                            columnArray.push(street.lockLevel.toString());
                            columnArray.push(latlon.lat.toString());
                            columnArray.push(latlon.lon.toString());
                            columnArray.push("\"" + plSeg + "\"");
                            lineArray.push(columnArray);
                        }
                        if (isTab) {
                            w.document.write("<tr><td>" + getStreetName(street) + "</td>");
                            if (includeAltNames) {
                                w.document.write("<td>&nbsp;</td>");
                            }
                            w.document.write("<td>" + street.city + "</td>");
                            w.document.write("<td>" + street.state + "</td>");
                            w.document.write("<td>" + roadTypeText + "</td><td>" + street.lockLevel + "</td>" +
                                "<td>" + latlon.lat.toString() + "</td><td>" + latlon.lon.toString() + "</td>" +
                                "<td><a href=\'" + plSeg + "\' target=\'_blank\'>Permalink</a></td></tr>");
                        }
                    }
                }
                else {
                    var latlon = OL.Layer.SphericalMercator.inverseMercator(street.center.x, street.center.y);
                    var plStreet = getStreetPL(street);
                    var altNames = "";
                    for (var ixAlt = 0; ixAlt < street.altStreets.length; ixAlt++) {
                        if (ixAlt > 0) {
                            altNames += ", ";
                        }
                        altNames += street.altStreets[ixAlt].name;
                    }
                    if (isCSV) {
                        columnArray = ["\"" + getStreetName(street) + "\""];
                        if (includeAltNames) {
                            columnArray.push("\"" + altNames + "\"");
                        }
                        columnArray.push("\"" + street.city + "\"");
                        columnArray.push("\"" + street.state + "\"");
                        columnArray.push("\"" + roadTypeText + "\"");
                        columnArray.push(street.lockLevel.toString());
                        columnArray.push(latlon.lat.toString());
                        columnArray.push(latlon.lon.toString());
                        columnArray.push("\"" + plStreet + "\"");
                        lineArray.push(columnArray);
                    }
                    if (isTab) {
                        w.document.write("<tr><td>" + getStreetName(street) + "</td>");
                        if (includeAltNames) {
                            w.document.write("<td>" + altNames + "</td>");
                        }
                        w.document.write("<td>" + street.city + "</td>");
                        w.document.write("<td>" + street.state + "</td>");
                        w.document.write("<td>" + roadTypeText + "</td><td>" + street.lockLevel + "</td>" +
                            "<td>" + latlon.lat.toString() + "</td><td>" + latlon.lon.toString() + "</td>" +
                            "<td><a href=\'" + plStreet + "\' target=\'_blank\'>Permalink</a></td></tr>");
                    }
                }
            }
            if (isCSV) {
                var csvContent = lineArray.join("\n");
                //var encodedUri = "data:text/csv;charset=utf-8," + encodeURIComponent(csvContent);
                var blob = new Blob([csvContent], {type: "data:text/csv;charset=utf-8;"});
                var link = document.createElement("a");
                var url = URL.createObjectURL(blob);
                link.setAttribute("href", url);
                link.setAttribute("download", fileName);
                var node = document.body.appendChild(link);
                link.click();
                document.body.removeChild(node);
            }
            if (isTab) {
                w.document.write("</table></body></html>");
                w.document.close();
                w = null;
            }
        }
    }
    WMEWAL_Locks.ScanComplete = ScanComplete;
    function ScanCancelled() {
        ScanComplete();
    }
    WMEWAL_Locks.ScanCancelled = ScanCancelled;
    function getStreetPL(street) {
        var latlon = OL.Layer.SphericalMercator.inverseMercator(street.center.x, street.center.y);
        var url = "https://www.waze.com/editor/?env=" + W.app.getAppRegionCode() + "&lon=" + latlon.lon + "&lat=" + latlon.lat + "&zoom=" + WMEWAL.zoomLevel + "&segments=";
        for (var ix = 0; ix < street.segments.length; ix++) {
            if (ix > 0) {
                url += ",";
            }
            url += street.segments[ix].id;
        }
        return url;
    }
    function getSegmentPL(segment) {
        var latlon = OL.Layer.SphericalMercator.inverseMercator(segment.center.x, segment.center.y);
        return "https://www.waze.com/editor/?env=" + W.app.getAppRegionCode() + "&lon=" + latlon.lon + "&lat=" + latlon.lat + "&zoom=5&segments=" + segment.id;
    }
    function getStreetName(street) {
        return street.name || "No street";
    }
    function Init() {
        console.group(pluginName + ": Initializing");
        initCount++;
        var objectToCheck = [
            "W.app",
            "W.model.states",
            "OL",
            "WMEWAL.RegisterPlugIn"];
        for (var i = 0; i < objectToCheck.length; i++) {
            var path = objectToCheck[i].split(".");
            var object = window;
            for (var j = 0; j < path.length; j++) {
                object = object[path[j]];
                if (typeof object === "undefined" || object == null) {
                    console.warn(path[j] + " NOT OK");
                    if (initCount < 60) {
                        console.groupEnd();
                        window.setTimeout(Init, 1000);
                    }
                    else {
                        console.error("Giving up on initialization");
                        console.groupEnd();
                    }
                    return;
                }
            }
            console.log(objectToCheck[i] + " OK");
        }
        if (typeof Storage !== "undefined") {
            if (localStorage[settingsKey]) {
                settings = JSON.parse(localStorage[settingsKey]);
            }
            if (localStorage[savedSettingsKey]) {
                try {
                    savedSettings = JSON.parse(WMEWAL.LZString.decompressFromUTF16(localStorage[savedSettingsKey]));
                } catch (e) {}
                if (typeof savedSettings === "undefined" || savedSettings === null || savedSettings.length === 0)
                {
                    console.debug(pluginName + ": decompressFromUTF16 failed, attempting decompress");
                    localStorage[savedSettingsKey +"Backup"] = localStorage[savedSettingsKey];
                    try {
                        savedSettings = JSON.parse(WMEWAL.LZString.decompress(localStorage[savedSettingsKey]));
                    } catch (e) {}
                    if (typeof savedSettings === "undefined" || savedSettings === null || savedSettings.length === 0)
                    {
                        console.debug(pluginName + ": decompress failed, savedSettings unrecoverable. Using blank");
                        savedSettings = [];
                    }
                    updateSavedSettings();
                }
            }
        }
        if (settings == null) {
            settings = {
                OutputTo: "csv",
                RoadTypeMask: WMEWAL.RoadType.Freeway,
                State: null,
                Regex: null,
                RegexIgnoreCase: true,
                ExcludeRoundabouts: false,
                ExcludeJunctionBoxes: true,
                EditableByMe: true,
                StreetLockLevel: 1,
                PrimaryStreetLockLevel: 2,
                MinorHighwayLockLevel: 3,
                MajorHighwayLockLevel: 4,
                FreewayLockLevel: 5,
                RampLockLevel: 7,
                IncludeInOutput: IncludeInOutput.Low | IncludeInOutput.High,
                PlusOneWayMask: 0,
                CityRegex: null,
                CityRegexIgnoreCase: true,
                StateOperation: Operation.Equal,
                RailroadLockLevel: 2
            };
        }
        else {
            if (!settings.hasOwnProperty("RailroadLockLevel")) {
                settings.RailroadLockLevel = 2;
            }
        }
        console.log("Initialized");
        console.groupEnd();
        WazeWrap.Interface.ShowScriptUpdate(scrName, Version, updateText, greasyForkPage, wazeForumThread);
        WMEWAL.RegisterPlugIn(WMEWAL_Locks);
    }
    function updateSavedSettings() {
        if (typeof Storage !== "undefined") {
            localStorage[savedSettingsKey] = WMEWAL.LZString.compressToUTF16(JSON.stringify(savedSettings));
        }
        updateSavedSettingsList();
    }
    function updateSettings() {
        if (typeof Storage !== "undefined") {
            localStorage[settingsKey] = JSON.stringify(settings);
        }
    }
    Init();
})(WMEWAL_Locks || (WMEWAL_Locks = {}));