<commit_before>define(["map/clientlayer", "map/labelslayer",
        "d3", "leaflet", "moment", "locationmarker", "rbush",
        "leaflet.label", "leaflet.providers"],
  function (ClientLayer, LabelsLayer, d3, L, moment, LocationMarker, rbush) {
    var blinkingHours = 8

    var options = { worldCopyJump: true,
                    zoomControl: false
                  }

    var AddLayerButton = L.Control.extend({
        options: {
          position: "bottomright"
        },

        initialize: function (f, options) {
          L.Util.setOptions(this, options)
          this.f = f
        },

        onAdd: function () {
          var button = L.DomUtil.create("button", "add-layer")
          button.textContent = ""

          L.DomEvent.disableClickPropagation(button)
          L.DomEvent.addListener(button, "click", this.f, this)

          this.button = button

          return button
        }
    })

    var LocateButton = L.Control.extend({
        options: {
          position: "bottomright"
        },

        active: false,
        button: undefined,

        initialize: function (f, options) {
          L.Util.setOptions(this, options)
          this.f = f
        },

        onAdd: function () {
          var button = L.DomUtil.create("button", "locate-user")
          button.textContent = ""

          L.DomEvent.disableClickPropagation(button)
          L.DomEvent.addListener(button, "click", this.onClick, this)

          this.button = button

          return button
        },

        update: function() {
          this.button.classList.toggle("active", this.active)
        },

        set: function(v) {
          this.active = v
          this.update()
        },

        onClick: function () {
          this.f(!this.active)
        }
    })

    var CoordPickerButton = L.Control.extend({
        options: {
          position: "bottomright"
        },

        initialize: function (f, options) {
          L.Util.setOptions(this, options)
          this.f = f
        },

        onAdd: function () {
          var button = L.DomUtil.create("button", "coord-picker")
          button.textContent = "ↆ"

          L.DomEvent.disableClickPropagation(button)
          L.DomEvent.addListener(button, "click", this.f, this)

          this.button = button

          return button
        }
    })

    function mkMarker(dict, iconFunc, router) {
      return function (d) {
        var m = L.circleMarker([d.nodeinfo.location.latitude, d.nodeinfo.location.longitude], iconFunc(d))

        m.resetStyle = function () {
          m.setStyle(iconFunc(d))
        }

        m.on("click", router.node(d))
        m.bindLabel(d.nodeinfo.hostname)

        dict[d.nodeinfo.node_id] = m

        return m
      }
    }

    function addLinksToMap(dict, linkScale, graph, router) {
      graph = graph.filter( function (d) {
        return "distance" in d && !d.vpn
      })

      var lines = graph.map( function (d) {
        var opts = { color: linkScale(d.tq).hex(),
                     weight: 4,
                     opacity: 0.5,
                     dashArray: "none"
                   }

        var line = L.polyline(d.latlngs, opts)

        line.resetStyle = function () {
          line.setStyle(opts)
        }

        line.bindLabel(d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname + "<br><strong>" + showDistance(d) + " / " + showTq(d) + "</strong>")
        line.on("click", router.link(d))

        dict[d.id] = line

        return line
      })

      return lines
    }

    var iconNew     = { color: "#1566A9", fillColor: "#93E929", radius: 6, fillOpacity: 1.0, opacity: 0.5, weight: 2 }
    var iconOnline  = { color: "#1566A9", fillColor: "#1566A9", radius: 6, fillOpacity: 0.5, opacity: 0.5, weight: 2, className: "stroke-first" }
    var iconAlert   = { color: "#D43E2A", fillColor: "#D43E2A", radius: 5, fillOpacity: 0.8, opacity: 0.8, weight: 2, className: "stroke-first node-alert" }
    var iconLost    = { color: "#D43E2A", fillColor: "#D9513F", radius: 5, fillOpacity: 0.8, opacity: 0.8, weight: 1, className: "stroke-first" }
    var iconOffline = { color: "#D43E2A", fillColor: "#D9513F", radius: 3, fillOpacity: 0.5, opacity: 0.5, weight: 1, className: "stroke-first" }

    return function (config, linkScale, sidebar, router, buttons) {
      var self = this
      var barycenter
      var groupOnline, groupOffline, groupNew, groupLost, groupLines
      var savedView
      var showCoords = false

      var map, userLocation
      var layerControl
      var customLayers = new Set()
      var baseLayers = {}

      var locateUserButton = new LocateButton(function (d) {
        if (d)
          enableTracking()
        else
          disableTracking()
      })

      var mybuttons = []

      function addButton(button) {
        var el = button.onAdd()
        mybuttons.push(el)
        buttons.appendChild(el)
      }

      function clearButtons() {
        mybuttons.forEach( function (d) {
          buttons.removeChild(d)
        })
      }

      function saveView() {
        savedView = {center: map.getCenter(),
                     zoom: map.getZoom()}
      }

      function enableTracking() {
        map.locate({watch: true,
                    enableHighAccuracy: true,
                    setView: true
                   })
        locateUserButton.set(true)
      }

      function disableTracking() {
        map.stopLocate()
        locationError()
        locateUserButton.set(false)
      }

      function locationFound(e) {
        if (!userLocation)
          userLocation = new LocationMarker(e.latlng).addTo(map)

        userLocation.setLatLng(e.latlng)
        userLocation.setAccuracy(e.accuracy)
      }

      function locationError() {
        if (userLocation) {
          map.removeLayer(userLocation)
          userLocation = null
        }
      }

      function addLayer(layerName) {
        if (layerName in baseLayers)
          return

        if (customLayers.has(layerName))
          return

        try {
          var layer = L.tileLayer.provider(layerName)
          layerControl.addBaseLayer(layer, layerName)
          customLayers.add(layerName)

          if (localStorageTest())
            localStorage.setItem("map/customLayers", JSON.stringify(Array.from(customLayers)))
        } catch (e) {
          return
        }
      }

      var el = document.createElement("div")
      el.classList.add("map")

      map = L.map(el, options)

      var layers = config.mapLayers.map( function (d) {
        return {
          "name": d.name,
          "layer": "url" in d ? L.tileLayer(d.url, d.config) : L.tileLayer.provider(d.name)
        }
      })

      layers[0].layer.addTo(map)

      layers.forEach( function (d) {
        baseLayers[d.name] = d.layer
      })

      map.on("locationfound", locationFound)
      map.on("locationerror", locationError)
      map.on("dragend", saveView)

      addButton(locateUserButton)

      addButton(new AddLayerButton(function () {
        /*eslint no-alert:0*/
        var layerName = prompt("Leaflet Provider:")
        addLayer(layerName)
      }))

      addButton(new CoordPickerButton(function () {
        showCoords = true
      }))

      map.on("click", function(e) {
        if(showCoords) {
          prompt("Koordinaten:", e.latlng.lat + " " + e.latlng.lng)
          showCoords = false
        }
      })

      layerControl = L.control.layers(baseLayers, [], {position: "bottomright"})
      layerControl.addTo(map)

      if (localStorageTest()) {
        var d = JSON.parse(localStorage.getItem("map/customLayers"))

        if (d)
          d.forEach(addLayer)
      }

      var clientLayer = new ClientLayer({minZoom: 15})
      clientLayer.addTo(map)
      clientLayer.setZIndex(5)

      var labelsLayer = new LabelsLayer()
      labelsLayer.addTo(map)
      labelsLayer.setZIndex(6)

      var nodeDict = {}
      var linkDict = {}
      var highlight<commit_msg>change icon and location of coord picker<commit_after>define(["map/clientlayer", "map/labelslayer",
        "d3", "leaflet", "moment", "locationmarker", "rbush",
        "leaflet.label", "leaflet.providers"],
  function (ClientLayer, LabelsLayer, d3, L, moment, LocationMarker, rbush) {
    var blinkingHours = 8

    var options = { worldCopyJump: true,
                    zoomControl: false
                  }

    var AddLayerButton = L.Control.extend({
        options: {
          position: "bottomright"
        },

        initialize: function (f, options) {
          L.Util.setOptions(this, options)
          this.f = f
        },

        onAdd: function () {
          var button = L.DomUtil.create("button", "add-layer")
          button.textContent = ""

          L.DomEvent.disableClickPropagation(button)
          L.DomEvent.addListener(button, "click", this.f, this)

          this.button = button

          return button
        }
    })

    var LocateButton = L.Control.extend({
        options: {
          position: "bottomright"
        },

        active: false,
        button: undefined,

        initialize: function (f, options) {
          L.Util.setOptions(this, options)
          this.f = f
        },

        onAdd: function () {
          var button = L.DomUtil.create("button", "locate-user")
          button.textContent = ""

          L.DomEvent.disableClickPropagation(button)
          L.DomEvent.addListener(button, "click", this.onClick, this)

          this.button = button

          return button
        },

        update: function() {
          this.button.classList.toggle("active", this.active)
        },

        set: function(v) {
          this.active = v
          this.update()
        },

        onClick: function () {
          this.f(!this.active)
        }
    })

    var CoordPickerButton = L.Control.extend({
        options: {
          position: "bottomright"
        },

        initialize: function (f, options) {
          L.Util.setOptions(this, options)
          this.f = f
        },

        onAdd: function () {
          var button = L.DomUtil.create("button", "coord-picker")
          button.textContent = ""

          L.DomEvent.disableClickPropagation(button)
          L.DomEvent.addListener(button, "click", this.f, this)

          this.button = button

          return button
        }
    })

    function mkMarker(dict, iconFunc, router) {
      return function (d) {
        var m = L.circleMarker([d.nodeinfo.location.latitude, d.nodeinfo.location.longitude], iconFunc(d))

        m.resetStyle = function () {
          m.setStyle(iconFunc(d))
        }

        m.on("click", router.node(d))
        m.bindLabel(d.nodeinfo.hostname)

        dict[d.nodeinfo.node_id] = m

        return m
      }
    }

    function addLinksToMap(dict, linkScale, graph, router) {
      graph = graph.filter( function (d) {
        return "distance" in d && !d.vpn
      })

      var lines = graph.map( function (d) {
        var opts = { color: linkScale(d.tq).hex(),
                     weight: 4,
                     opacity: 0.5,
                     dashArray: "none"
                   }

        var line = L.polyline(d.latlngs, opts)

        line.resetStyle = function () {
          line.setStyle(opts)
        }

        line.bindLabel(d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname + "<br><strong>" + showDistance(d) + " / " + showTq(d) + "</strong>")
        line.on("click", router.link(d))

        dict[d.id] = line

        return line
      })

      return lines
    }

    var iconNew     = { color: "#1566A9", fillColor: "#93E929", radius: 6, fillOpacity: 1.0, opacity: 0.5, weight: 2 }
    var iconOnline  = { color: "#1566A9", fillColor: "#1566A9", radius: 6, fillOpacity: 0.5, opacity: 0.5, weight: 2, className: "stroke-first" }
    var iconAlert   = { color: "#D43E2A", fillColor: "#D43E2A", radius: 5, fillOpacity: 0.8, opacity: 0.8, weight: 2, className: "stroke-first node-alert" }
    var iconLost    = { color: "#D43E2A", fillColor: "#D9513F", radius: 5, fillOpacity: 0.8, opacity: 0.8, weight: 1, className: "stroke-first" }
    var iconOffline = { color: "#D43E2A", fillColor: "#D9513F", radius: 3, fillOpacity: 0.5, opacity: 0.5, weight: 1, className: "stroke-first" }

    return function (config, linkScale, sidebar, router, buttons) {
      var self = this
      var barycenter
      var groupOnline, groupOffline, groupNew, groupLost, groupLines
      var savedView
      var showCoords = false

      var map, userLocation
      var layerControl
      var customLayers = new Set()
      var baseLayers = {}

      var locateUserButton = new LocateButton(function (d) {
        if (d)
          enableTracking()
        else
          disableTracking()
      })

      var mybuttons = []

      function addButton(button) {
        var el = button.onAdd()
        mybuttons.push(el)
        buttons.appendChild(el)
      }

      function clearButtons() {
        mybuttons.forEach( function (d) {
          buttons.removeChild(d)
        })
      }

      function saveView() {
        savedView = {center: map.getCenter(),
                     zoom: map.getZoom()}
      }

      function enableTracking() {
        map.locate({watch: true,
                    enableHighAccuracy: true,
                    setView: true
                   })
        locateUserButton.set(true)
      }

      function disableTracking() {
        map.stopLocate()
        locationError()
        locateUserButton.set(false)
      }

      function locationFound(e) {
        if (!userLocation)
          userLocation = new LocationMarker(e.latlng).addTo(map)

        userLocation.setLatLng(e.latlng)
        userLocation.setAccuracy(e.accuracy)
      }

      function locationError() {
        if (userLocation) {
          map.removeLayer(userLocation)
          userLocation = null
        }
      }

      function addLayer(layerName) {
        if (layerName in baseLayers)
          return

        if (customLayers.has(layerName))
          return

        try {
          var layer = L.tileLayer.provider(layerName)
          layerControl.addBaseLayer(layer, layerName)
          customLayers.add(layerName)

          if (localStorageTest())
            localStorage.setItem("map/customLayers", JSON.stringify(Array.from(customLayers)))
        } catch (e) {
          return
        }
      }

      var el = document.createElement("div")
      el.classList.add("map")

      map = L.map(el, options)

      var layers = config.mapLayers.map( function (d) {
        return {
          "name": d.name,
          "layer": "url" in d ? L.tileLayer(d.url, d.config) : L.tileLayer.provider(d.name)
        }
      })

      layers[0].layer.addTo(map)

      layers.forEach( function (d) {
        baseLayers[d.name] = d.layer
      })

      map.on("locationfound", locationFound)
      map.on("locationerror", locationError)
      map.on("dragend", saveView)

      addButton(locateUserButton)

      addButton(new CoordPickerButton(function () {
        showCoords = true
      }))

      addButton(new AddLayerButton(function () {
        /*eslint no-alert:0*/
        var layerName = prompt("Leaflet Provider:")
        addLayer(layerName)
      }))

      map.on("click", function(e) {
        if(showCoords) {
          prompt("Koordinaten:", e.latlng.lat + " " + e.latlng.lng)
          showCoords = false
        }
      })

      layerControl = L.control.layers(baseLayers, [], {position: "bottomright"})
      layerControl.addTo(map)

      if (localStorageTest()) {
        var d = JSON.parse(localStorage.getItem("map/customLayers"))

        if (d)
          d.forEach(addLayer)
      }

      var clientLayer = new ClientLayer({minZoom: 15})
      clientLayer.addTo(map)
      clientLayer.setZIndex(5)

      var labelsLayer = new LabelsLayer()
      labelsLayer.addTo(map)
      labelsLayer.setZIndex(6)

      var nodeDict = {}
      var linkDict = {}
      var highlight
{'fraction_non_alphanumeric': 0.12390097898609466, 'fraction_numerical': 0.010226351562012846, 'mean_word_length': 1.905961224859576, 'pattern_counts': {'":': 4, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4836890', 'n_tokens_mistral': 5048, 'n_tokens_neox': 4782, 'n_words': 995}