WME Wide-Angle Lens Cities

Find streets whose city doesn't match the boundaries of a polygon layer

目前為 2018-05-08 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name                WME Wide-Angle Lens Cities
// @namespace           https://greasyfork.org/en/users/19861-vtpearce
// @description         Find streets whose city doesn't match the boundaries of a polygon layer
// @author              vtpearce and crazycaveman
// @include             https://www.waze.com/editor
// @include             /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/
// @version             1.1.4
// @grant               none
// @copyright           2017 vtpearce
// @license             CC BY-SA 4.0
// ==/UserScript==
// ---------------------------------------------------------------------------------------
var WMEWAL_Cities;
(function (WMEWAL_Cities) {
    var Operation;
    (function (Operation) {
        Operation[Operation["Equal"] = 1] = "Equal";
        Operation[Operation["NotEqual"] = 2] = "NotEqual";
    })(Operation || (Operation = {}));
    var pluginName = "WMEWAL-Cities";
    WMEWAL_Cities.Title = "Cities";
    WMEWAL_Cities.MinimumZoomLevel = 2;
    WMEWAL_Cities.SupportsSegments = true;
    WMEWAL_Cities.SupportsVenues = false;
    var settingsKey = "WMEWALCitiesSettings";
    var savedSettingsKey = "WMEWALCitiesSavedSettings";
    var settings = null;
    var savedSettings = "";
    var streets = null;
    var state;
    var stateName;
    var cityRegex = null;
    var cityPolygons = null;
    var initCount = 0;
    function GetTab() {
        var html = "<table style='border-collapse: separate; border-spacing:0px 1px;'>";
        html += "<tbody>";
        html += "<tr><td style='font-size:1.2em'><b>Output To:</b></td></tr>";
        html += "<tr><td style='padding-left:20px'>" +
            "<select id='_wmewalCitiesOutputTo'>" +
            "<option value='csv'>CSV File</option>" +
            "<option value='tab'>Browser Tab</option>" +
            "<option value='both'>Both CSV File and Browser Tab</option></select></td></tr>";
        html += "<tr><td style='border-top: 1px solid; padding-top: 4px;font-size:1.2em'><b>Settings</b></td></tr>";
        html += "<tr><td><b>Polygon Layer:</b></td></tr>";
        html += "<tr><td style='padding-left: 20px'>" +
            "<select id='_wmewalCitiesLayer'/>" +
            "</td></tr>";
        html += "<tr><td style='border-top: 1px solid; font-size: 1.2em'><b>Saved Filters</b></td></tr>";
        html += "<tr><td style='padding-left: 20px; padding-bottom: 8px'>" +
            "<select id='_wmewalCitiesSavedSettings'/><br/>" +
            "<button class='btn btn-primary' id='_wmewalCitiesLoadSetting' title='Load'>Load</button>" +
            "<button class='btn btn-primary' style='margin-left: 4px;' id='_wmewalCitiesSaveSetting' title='Save'>Save</button>" +
            "<button class='btn btn-primary' style='margin-left: 4px;' id='_wmewalCitiesDeleteSetting' title='Delete'>Delete</button></td></tr>";
        html += "<tr><td style='border-top: 1px solid; padding-top: 4px;font-size:1.2em'><b>Filters</b></td></tr>";
        html += "<tr><td><b>City RegEx:</b></td></tr>";
        html += "<tr><td style='padding-left: 20px'><input type='text' id='_wmewalCitiesCity' class='wal-textbox'/><br/>" +
            "<input id='_wmewalCitiesCityIgnoreCase' type='checkbox'/>" +
            "<label for='_wmewalCitiesCityIgnoreCase' 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='_wmewalCitiesStateOp'>" +
            "<option value='" + Operation.Equal.toString() + "' selected='selected'>=</option>" +
            "<option value='" + Operation.NotEqual.toString() + "'>&lt;&gt;</option></select>" +
            "<select id='_wmewalCitiesState'/></td></tr>";
        html += "<tr><td><b>Road Type:</b></td></tr>";
        html += "<tr><td style='padding-left: 20px'>" +
            "<button id='_wmewalCitiesRoadTypeAny' class='btn btn-primary' style='margin-right: 8px' title='Any'>Any</button>" +
            "<button id='_wmewalCitiesRoadTypeClear' class='btn btn-primary' title='Clear'>Clear</button>" +
            "<div><input type='checkbox' checked='checked' id='_wmewalCitiesRoadTypeFreeway' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Freeway.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeFreeway' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Freeway)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeRamp' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Ramp.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeRamp' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Ramp)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeMajorHighway' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.MajorHighway.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeMajorHighway' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.MajorHighway)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeMinorHighway' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.MinorHighway.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeMinorHighway' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.MinorHighway)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypePrimary' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.PrimaryStreet.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypePrimary' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.PrimaryStreet)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeStreet' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Street.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeStreet' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Street)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeAlley' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Alley.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeAlley' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Alley)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeUnpaved' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Unpaved.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeUnpaved' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Unpaved)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypePLR' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.ParkingLotRoad.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypePLR' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.ParkingLotRoad)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypePrivate' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.PrivateRoad.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypePrivate' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.PrivateRoad)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeFerry' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Ferry.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeFerry' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Ferry)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeWT' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.WalkingTrail.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeWT' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.WalkingTrail)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypePB' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.PedestrianBoardwalk.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypePB' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.PedestrianBoardwalk)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeStairway' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Stairway.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeStairway' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Stairway)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeRR' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.Railroad.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeRR' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.Railroad)) + "</label></div>" +
            "<div><input type='checkbox' id='_wmewalCitiesRoadTypeRT' name='_wmewalCitiesRoadType' value='" + WMEWAL.RoadType.RunwayTaxiway.toString() + "'/>" +
            "<label for='_wmewalCitiesRoadTypeRT' style='margin-left: 8px'>" + WMEWAL.TranslateRoadType(WMEWAL.RoadTypeBitmaskToWazeRoadType(WMEWAL.RoadType.RunwayTaxiway)) + "</label></div>" +
            "</td></tr>";
        html += "<tr><td><input id='_wmewalCitiesEditable' type='checkbox'/>" +
            "<label for='_wmewalCitiesEditable' style='margin-left: 8px'>Editable by me</label></td></tr>";
        html += "<tr><td><input id='_wmewalCitiesExcludeJunctionBoxes' type='checkbox' checked='checked'/>" +
            "<label for='_wmewalCitiesExcludeJunctionBoxes' style='margin-left: 8px'>Exclude Junction Boxes</label></td></tr>";
        html += "</tbody></table>";
        return html;
    }
    WMEWAL_Cities.GetTab = GetTab;
    function TabLoaded() {
        updateStates();
        updateLayers();
        updateUI();
        updateSavedSettingsList();
        $("#_wmewalCitiesState").on("focus", updateStates);
        $("#_wmewalCitiesLayer").on("focus", updateLayers);
        $("#_wmewalCitiesRoadTypeAny").on("click", function () {
            $("input[name=_wmewalCitiesRoadType]").prop("checked", true);
        });
        $("#_wmewalCitiesRoadTypeClear").on("click", function () {
            $("input[name=_wmewalCitiesRoadType]").prop("checked", false);
        });
        $("#_wmewalCitiesLoadSetting").on("click", loadSetting);
        $("#_wmewalCitiesSaveSetting").on("click", saveSetting);
        $("#_wmewalCitiesDeleteSetting").on("click", deleteSetting);
    }
    WMEWAL_Cities.TabLoaded = TabLoaded;
    function updateStates() {
        var selectState = $("#_wmewalCitiesState");
        // 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.get(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 updateLayers() {
        var selectLayer = $("#_wmewalCitiesLayer");
        var currentLayer = selectLayer.val();
        selectLayer.empty();
        var layers = [];
        for (var ixLayer = 0; ixLayer < W.map.layers.length; ixLayer++) {
            var layer = W.map.layers[ixLayer];
            if (layer.CLASS_NAME === "OL.Layer.Vector" || layer.CLASS_NAME === "OpenLayers.Layer.Vector") {
                var vectorLayer = layer;
                if (vectorLayer.features && vectorLayer.features.length > 0) {
                    layers.push({
                        uniqueName: vectorLayer.uniqueName,
                        name: vectorLayer.name
                    });
                }
            }
        }
        layers.sort(function (a, b) {
            return a.name.localeCompare(b.name);
        });
        for (var ix = 0; ix < layers.length; ix++) {
            var l = layers[ix];
            var layerOption = $("<option/>").text(l.name).attr("value", l.uniqueName);
            if (currentLayer != null && currentLayer === l.uniqueName) {
                layerOption.attr("selected", "selected");
            }
            selectLayer.append(layerOption);
        }
    }
    function updateSavedSettingsList() {
        var s = $("#_wmewalCitiesSavedSettings");
        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() {
        $("#_wmewalCitiesOutputTo").val(settings.OutputTo);
        $("#_wmewalCitiesCity").val(settings.CityRegex || "");
        $("#_wmewalCitiesCityIgnoreCase").prop("checked", settings.CityRegexIgnoreCase);
        $("#_wmewalCitiesState").val(settings.State);
        $("#_wmewalCitiesStateOp").val(settings.StateOperation || Operation.Equal.toString());
        $("#_wmewalCitiesRoadTypeFreeway").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Freeway);
        $("#_wmewalCitiesRoadTypeRamp").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Ramp);
        $("#_wmewalCitiesRoadTypeMajorHighway").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.MajorHighway);
        $("#_wmewalCitiesRoadTypeMinorHighway").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.MinorHighway);
        $("#_wmewalCitiesRoadTypePrimary").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.PrimaryStreet);
        $("#_wmewalCitiesRoadTypeStreet").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Street);
        $("#_wmewalCitiesRoadTypeAlley").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Alley);
        $("#_wmewalCitiesRoadTypeUnpaved").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Unpaved);
        $("#_wmewalCitiesRoadTypePLR").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.ParkingLotRoad);
        $("#_wmewalCitiesRoadTypePrivate").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.PrivateRoad);
        $("#_wmewalCitiesRoadTypeFerry").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Ferry);
        $("#_wmewalCitiesRoadTypeWT").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.WalkingTrail);
        $("#_wmewalCitiesRoadTypePB").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.PedestrianBoardwalk);
        $("#_wmewalCitiesRoadTypeStairway").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Stairway);
        $("#_wmewalCitiesRoadTypeRR").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.Railroad);
        $("#_wmewalCitiesRoadTypeRT").prop("checked", settings.RoadTypeMask & WMEWAL.RoadType.RunwayTaxiway);
        $("#_wmewalCitiesEditable").prop("checked", settings.EditableByMe);
        $("#_wmewalCitiesExcludeJunctionBoxes").prop("checked", settings.ExcludeJunctionBoxes);
        $("#_wmewalCitiesLayer").val(settings.PolygonLayerUniqueName);
    }
    function loadSetting() {
        var selectedSetting = parseInt($("#_wmewalCitiesSavedSettings").val());
        if (selectedSetting == null || isNaN(selectedSetting) || selectedSetting < 0 || selectedSetting > savedSettings.length) {
            return;
        }
        settings.OutputTo = $("#_wmewalCitiesOutputTo").val();
        var savedSetting = savedSettings[selectedSetting].Setting;
        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=_wmewalCitiesRoadType]: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 = $("#_wmewalCitiesState").val();
        if (selectedState != null && selectedState.length > 0) {
            if (W.model.states.get(selectedState) == null) {
                message += ((message.length > 0 ? "\n" : "") + "Invalid state selection");
                allOk = false;
            }
        }
        var pattern = $("#_wmewalCitiesCity").val();
        var ignoreCase = $("#_wmewalCitiesCityIgnoreCase").prop("checked");
        var r;
        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;
            }
        }
        var layerUniqueName = $("#_wmewalCitiesLayer").val();
        if (layerUniqueName !== null && layerUniqueName.length > 0) {
            var layers = W.map.getLayersBy("uniqueName", layerUniqueName);
            if (layers.length === 0) {
                message += ((message.length > 0 ? "\n" : "") + "Could not find layer.");
                allOk = false;
            }
            else if (layers.length > 1) {
                message += ((message.length > 0 ? "\n" : "") + "More than one layer found");
                allOk = false;
            }
            else {
                cityPolygons = [];
                for (var ixFeature = 0; ixFeature < layers[0].features.length; ixFeature++) {
                    var feature = layers[0].features[ixFeature];
                    if (feature.style && feature.style.label && feature.style.label.length > 0) {
                        console.log("Checking to see if " + feature.style.label + " is in area");
                        if (feature.geometry.intersects(WMEWAL.areaToScan)) {
                            cityPolygons.push({
                                name: feature.style.label,
                                geometry: feature.geometry.clone(),
                                compressedName: feature.style.label.replace(/\s/g, "")
                            });
                        }
                    } else if (feature.attributes) {
                        if (feature.attributes.name && feature.attributes.name.length > 0) {
                            console.log("Checking to see if " + feature.attributes.name + " is in area");
                            if (feature.geometry.intersects(WMEWAL.areaToScan)) {
                                cityPolygons.push({
                                    name: feature.attributes.name,
                                    geometry: feature.geometry.clone(),
                                    compressedName: feature.attributes.name.replace(/\s/g, "")
                                });
                            }
                        } else if (feature.attributes.labelText && feature.attributes.labelText.length > 0) {
                            console.log("Checking to see if " + feature.attributes.labelText + " is in area");
                            if (feature.geometry.intersects(WMEWAL.areaToScan)) {
                                cityPolygons.push({
                                    name: feature.attributes.labelText,
                                    geometry: feature.geometry.clone(),
                                    compressedName: feature.attributes.labelText.replace(/\s/g, "")
                                });
                            } 
                        } 
                    }
                }
                if (cityPolygons.length === 0) {
                    message += ((message.length > 0 ? "\n" : "") + "No features in the layer have an appropriate label to use as City Name and are in the scanned area");
                    allOk = false;
                }
            }
        }
        else {
            message += ((message.length > 0 ? "\n" : "") + "Please select a layer containing City polygons");
            allOk = false;
        }
        if (!allOk) {
            alert(pluginName + ": " + message);
        }
        return allOk;
    }
    function saveSetting() {
        if (validateSettings()) {
            var s_1 = {
                RoadTypeMask: 0,
                State: null,
                StateOperation: parseInt($("#_wmewalCitiesStateOp").val()),
                ExcludeJunctionBoxes: $("#_wmewalCitiesExcludeJunctionBoxes").prop("checked"),
                EditableByMe: $("#_wmewalCitiesEditable").prop("checked"),
                CityRegex: null,
                CityRegexIgnoreCase: $("#_wmewalCitiesCityIgnoreCase").prop("checked"),
                PolygonLayerUniqueName: $("#_wmewalCitiesLayer").val()
            };
            $("input[name=_wmewalCitiesRoadType]:checked").each(function (ix, e) {
                s_1.RoadTypeMask = s_1.RoadTypeMask | parseInt(e.value);
            });
            var selectedState = $("#_wmewalCitiesState").val();
            if (selectedState != null && selectedState.length > 0) {
                s_1.State = W.model.states.get(selectedState).id;
            }
            var pattern = $("#_wmewalCitiesCity").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($("#_wmewalCitiesSavedSettings").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();
        if (allOk) {
            streets = [];
            settings.OutputTo = $("#_wmewalCitiesOutputTo").val();
            settings.PolygonLayerUniqueName = $("#_wmewalCitiesLayer").val();
            settings.RoadTypeMask = 0;
            $("input[name=_wmewalCitiesRoadType]:checked").each(function (ix, e) {
                settings.RoadTypeMask = settings.RoadTypeMask | parseInt(e.value);
            });
            var selectedState = $("#_wmewalCitiesState").val();
            state = null;
            settings.State = null;
            stateName = null;
            if (selectedState != null && selectedState.length > 0) {
                state = W.model.states.get(selectedState);
                settings.State = state.id;
                stateName = state.name;
            }
            settings.StateOperation = parseInt($("#_wmewalCitiesStateOp").val());
            settings.CityRegexIgnoreCase = $("#_wmewalCitiesCityIgnoreCase").prop("checked");
            var pattern = $("#_wmewalCitiesCity").val();
            settings.CityRegex = null;
            cityRegex = null;
            if (pattern.length > 0) {
                settings.CityRegex = pattern;
                cityRegex = (settings.CityRegexIgnoreCase ? new RegExp(pattern, "i") : new RegExp(pattern));
            }
            settings.ExcludeJunctionBoxes = $("#_wmewalCitiesExcludeJunctionBoxes").prop("checked");
            settings.EditableByMe = $("#_wmewalCitiesEditable").prop("checked");
            if (settings.RoadTypeMask & ~(WMEWAL.RoadType.Freeway | WMEWAL.RoadType.MajorHighway | WMEWAL.RoadType.MinorHighway | WMEWAL.RoadType.PrimaryStreet)) {
                WMEWAL_Cities.MinimumZoomLevel = 4;
            }
            else {
                WMEWAL_Cities.MinimumZoomLevel = 2;
            }
            updateSettings();
        }
        return allOk;
    }
    WMEWAL_Cities.ScanStarted = ScanStarted;
    function ScanExtent(segments, venues) {
        var def = $.Deferred();
        var extentStreets = [];
        var segment;
        var spaceRegex = /\s/g;
        function addSegment(s, incorrectCity, cityShouldBe, rId) {
            var sid = s.attributes.primaryStreetID;
            var address = s.getAddress();
            var thisStreet = null;
            if (sid != null) {
                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) {
                        // Test for alt names
                        for (var ixAlt = 0; ixAlt < e.altStreets.length && matches; ixAlt++) {
                            matches = false;
                            for (var ixSegAlt = 0; ixSegAlt < s.attributes.streetIDs.length && !matches; ixSegAlt++) {
                                if (e.altStreets[ixAlt].id === s.attributes.streetIDs[ixSegAlt]) {
                                    matches = true;
                                }
                            }
                        }
                    }
                    return matches;
                });
            }
            if (thisStreet == null) {
                thisStreet = {
                    id: sid,
                    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,
                    incorrectCity: incorrectCity,
                    cityShouldBe: cityShouldBe
                };
                for (var ixAlt = 0; ixAlt < s.attributes.streetIDs.length; ixAlt++) {
                    var altStreet = W.model.streets.get(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()]);
        }
        var _loop_1 = function(ix) {
            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) {
                                return "continue";
                            }
                        }
                        else if (settings.StateOperation === Operation.Equal) {
                            return "continue";
                        }
                    }
                    var altCityNames_1 = [];
                    if (segment.attributes.streetIDs != null) {
                        for (var streetIx = 0; streetIx < segment.attributes.streetIDs.length; streetIx++) {
                            if (segment.attributes.streetIDs[streetIx] != null) {
                                var street = W.model.streets.get(segment.attributes.streetIDs[streetIx]);
                                if (street != null) {
                                    if (street.cityID != null) {
                                        var city = W.model.cities.get(street.cityID);
                                        if (city != null) {
                                            altCityNames_1.push({
                                                hasName: city.hasName(),
                                                name: city.hasName() ? city.attributes.name : null,
                                                compressedName: city.hasName() ? city.attributes.name.replace(spaceRegex, "") : null
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (cityRegex != null) {
                        var nameMatched = false;
                        if (address.attributes != null && !address.attributes.isEmpty) {
                            if (address.attributes.city != null && address.attributes.city.hasName()) {
                                nameMatched = cityRegex.test(address.attributes.city.attributes.name);
                            }
                            if (!nameMatched) {
                                for (var altIx = 0; altIx < altCityNames_1.length && !nameMatched; altIx++) {
                                    if (altCityNames_1[altIx].hasName) {
                                        nameMatched = cityRegex.test(altCityNames_1[altIx].name);
                                    }
                                }
                            }
                        }
                        if (!nameMatched) {
                            return "continue";
                        }
                    }
                    if (!WMEWAL.IsSegmentInArea(segment)) {
                        return "continue";
                    }
                    var cityMatches = true;
                    var cityNames = [];
                    var cityShouldBe = "";
                    var incorrectCity = "";
                    var anyBlankCity = false;
                    if (address.attributes != null && address.attributes.city && address.attributes.city.hasName()) {
                        cityNames.push({
                            hasName: true,
                            name: address.attributes.city.attributes.name,
                            compressedName: address.attributes.city.attributes.name.replace(spaceRegex, "")
                        });
                    }
                    else {
                        anyBlankCity = true;
                    }
                    var _loop_2 = function(ixAlt) {
                        if (altCityNames_1[ixAlt].hasName) {
                            if (cityNames.find(function (c) {
                                return c.compressedName === altCityNames_1[ixAlt].compressedName;
                            })) {
                                cityNames.push({
                                    hasName: true,
                                    name: altCityNames_1[ixAlt].name,
                                    compressedName: altCityNames_1[ixAlt].name.replace(spaceRegex, "")
                                });
                            }
                        }
                        else {
                            anyBlankCity = true;
                        }
                    };
                    for (var ixAlt = 0; ixAlt < altCityNames_1.length; ixAlt++) {
                        _loop_2(ixAlt);
                    }
                    if (cityNames.length > 0) {
                        // Check to see if it's in any of the city polygons that are referenced
                        for (var ixCityName = 0; ixCityName < cityNames.length && cityMatches; ixCityName++) {
                            var foundAny = false;
                            for (var ixCity = 0; ixCity < cityPolygons.length && cityMatches; ixCity++) {
                                if (cityNames[ixCityName].compressedName === cityPolygons[ixCity].name.replace(spaceRegex, "")) {
                                    foundAny = true;
                                    if (!cityPolygons[ixCity].geometry.intersects(segment.geometry)) {
                                        incorrectCity = cityNames[ixCityName].name;
                                        cityShouldBe = "No City";
                                        cityMatches = false;
                                    }
                                }
                            }
                            if (!foundAny) {
                                incorrectCity = cityNames[ixCityName].name;
                                cityShouldBe = "No matching city polygon";
                                cityMatches = false;
                            }
                        }
                    }
                    if (anyBlankCity && cityMatches) {
                        // No city names listed, so check to see if it's inside any of the city polygons
                        for (var ixCity = 0; ixCity < cityPolygons.length && cityMatches; ixCity++) {
                            if (cityPolygons[ixCity].geometry.intersects(segment.geometry)) {
                                incorrectCity = "No City";
                                cityShouldBe = cityPolygons[ixCity].name;
                                cityMatches = false;
                            }
                        }
                    }
                    if (cityMatches) {
                        return "continue";
                    }
                    if (!segment.isInRoundabout()) {
                        addSegment(segment, incorrectCity, cityShouldBe, null);
                    }
                    else {
                        var r = segment.getRoundabout();
                        for (var rIx = 0; rIx < r.segIDs.length; rIx++) {
                            addSegment(W.model.segments.get(r.segIDs[rIx]), incorrectCity, cityShouldBe, r.id);
                        }
                    }
                }
            }
        };
        for (var ix = 0; ix < segments.length; ix++) {
            _loop_1(ix);
        }
        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_Cities.ScanExtent = ScanExtent;
    function ScanComplete() {
        cityPolygons = [];
        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;
                }
                if (a.lockLevel < b.lockLevel) {
                    return -1;
                }
                else if (a.lockLevel > b.lockLevel) {
                    return 1;
                }
                return 0;
            });
            var outputTo = $("#_wmewalCitiesOutputTo").val();
            var isCSV = (outputTo === "csv" || outputTo === "both");
            var isTab = (outputTo === "tab" || outputTo === "both");
            var lineArray = void 0;
            var columnArray = void 0;
            var w = void 0;
            var fileName = void 0;
            if (isCSV) {
                lineArray = [];
                columnArray = ["Name"];
                columnArray.push("Alt Names");
                columnArray.push("State");
                columnArray.push("Road Type");
                columnArray.push("Lock Level");
                columnArray.push("Incorrect City");
                columnArray.push("City Should Be");
                columnArray.push("Latitude");
                columnArray.push("Longitude");
                columnArray.push("Permalink");
                lineArray.push(columnArray);
                fileName = "Cities_" + WMEWAL.areaName + ".csv";
            }
            if (isTab) {
                w = window.open();
                w.document.write("<html><head><title>Cities</title></head><body>");
                w.document.write("<h3>Area: " + WMEWAL.areaName + "</h3>");
                w.document.write("<b>Filters</b>");
                if (cityRegex != null) {
                    w.document.write("<br/>City Name matches " + cityRegex.source);
                    if (settings.CityRegexIgnoreCase) {
                        w.document.write(" (ignoring case)");
                    }
                }
                if (stateName != null) {
                    w.document.write("<br/>State " + (settings.StateOperation === Operation.NotEqual ? "does not equal " : "equals ") + stateName);
                }
                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>");
                w.document.write("<th>Alt Names</th><th>State</th>");
                w.document.write("<th>Road Type</th><th>Lock Level</th>");
                w.document.write("<th>Incorrect City</th><th>City Should Be</th>");
                w.document.write("<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)];
                            columnArray.push("");
                            columnArray.push("\"" + street.state + "\"");
                            columnArray.push("\"" + roadTypeText + "\"");
                            columnArray.push(street.lockLevel.toString());
                            columnArray.push("\"" + street.incorrectCity + "\"");
                            columnArray.push("\"" + street.cityShouldBe + "\"");
                            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>");
                            w.document.write("<td>&nbsp;</td>");
                            w.document.write("<td>" + street.state + "</td>");
                            w.document.write("<td>" + roadTypeText + "</td><td>" + street.lockLevel + "</td>");
                            w.document.write("<td>" + street.incorrectCity + "</td><td>" + street.cityShouldBe + "</td>");
                            w.document.write("<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) + "\""];
                        columnArray.push("\"" + altNames + "\"");
                        columnArray.push("\"" + street.state + "\"");
                        columnArray.push("\"" + roadTypeText + "\"");
                        columnArray.push(street.lockLevel.toString());
                        columnArray.push("\"" + street.incorrectCity + "\"");
                        columnArray.push("\"" + street.cityShouldBe + "\"");
                        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>");
                        w.document.write("<td>" + altNames + "</td>");
                        w.document.write("<td>" + street.state + "</td>");
                        w.document.write("<td>" + roadTypeText + "</td><td>" + street.lockLevel + "</td>");
                        w.document.write("<td>" + street.incorrectCity + "</td><td>" + street.cityShouldBe + "</td>");
                        w.document.write("<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;
            }
            streets = [];
        }
    }
    WMEWAL_Cities.ScanComplete = ScanComplete;
    function ScanCancelled() {
        ScanComplete();
    }
    WMEWAL_Cities.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.location.code + "&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.location.code + "&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.location",
            "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 === "")
                {
                    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 === "")
                    {
                        console.debug(pluginName + ": decompress failed, savedSettings unrecoverable. Using blank");
                        savedSettings = [];
                    }
                    updateSavedSettings();
                }
                for (var ix = 0; ix < savedSettings.length; ix++) {
                    if (savedSettings[ix].Setting.hasOwnProperty("OutputTo")) {
                        delete savedSettings[ix].Setting.OutputTo;
                    }
                }
            }
        }
        if (settings == null) {
            settings = {
                RoadTypeMask: WMEWAL.RoadType.Freeway,
                OutputTo: "csv",
                State: null,
                StateOperation: Operation.Equal,
                ExcludeJunctionBoxes: true,
                EditableByMe: true,
                CityRegex: null,
                CityRegexIgnoreCase: true,
                PolygonLayerUniqueName: null
            };
        }
        console.log("Initialized");
        console.groupEnd();
        WMEWAL.RegisterPlugIn(WMEWAL_Cities);
    }
    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_Cities || (WMEWAL_Cities = {}));