<commit_before><!DOCTYPE html>
<html>
<head>
  <title>SignalK Tracker</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <style>
    body {
      padding: 0;
      margin: 0;
    }

    html, body, #map {
      height: 100%;
    }

    svg {
      position: relative;
    }

    .targets {
      position: absolute;
      top: 0px;
      left: 0px;
    }

    .targetlist {
      background-image: url(FFFFFF-0.6.png);
      font-family: sans-serif;
    }
  </style>
  <script src="/signalk/stream/v1/primus.js"></script>
  <script src="dist/map.js"></script>
  <script src="/bower_components/L.EasyButton/easy-button.js"></script>
  <link rel="stylesheet" href="/bower_components/leaflet/dist/leaflet.css">
  <link href="/bower_components/components-font-awesome/css/font-awesome.css" rel="stylesheet">
</head>

<body class="leaflet-dragging">
<div id="map"></div>

<div class="targets">
  <table class="targetlist" id="targetList">
  </table>
</div>
</body>


<script>
  var map = new L.Map("map", {
    center: [37.8, -96.9],
    zoom: 4,
    zoomControl: false
  });
  map.setView([60.1, 24.8], 13);

  new L.Control.Zoom({ position: 'topright' }).addTo(map);

  var homeButton = new L.Control.EasyButtons();
  homeButton.options.intentedIcon = 'fa-home';
  homeButton.options.position = 'topright';
  homeButton.intendedFunction = function () {
    map.panTo(selfLocation);
  };
  map.addControl(homeButton);


  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map);


  var svg = d3.select(map.getPanes().overlayPane).append("svg");
  var g = svg.append("g").attr("class", "leaflet-zoom-hide");

  var transform = d3.geo.transform({point: projectPoint});
  var path = d3.geo.path().projection(transform);

  map.on("viewreset", reset);

  function updateMarkers(multiPointForBounds, targetsArray) {
    var bounds = path.bounds(multiPointForBounds),
        topLeft = bounds[0],
        bottomRight = bounds[1];

    svg.attr("width", bottomRight[0] - topLeft[0] + 20)
        .attr("height", bottomRight[1] - topLeft[1] + 20)
        .style("left", (topLeft[0] - 10) + "px")
        .style("top", (topLeft[1] - 10) + "px");

    g.attr("transform", "translate(" + (-topLeft[0] + 10) + "," + (-topLeft[1] + 10) + ")");

    var vesselColor = d3.scale.linear()
        .domain([0.9 * selfSpeed, selfSpeed, 1.1 * selfSpeed])
        .range(['blue', 'grey', 'red']);


    var boatData = g.selectAll('.vessel').data(targetsArray, function (d) {
      return d.id
    });
    boatData.enter().append("polygon").attr("class", "vessel").attr('points', "0,-10 5,10 -5,10");
    boatData
        .attr("style", function (d, i) {
          return d.id === 'self' ? "fill:black" : "fill:" + vesselColor(d.sog);
        })
        .attr('transform', function (d) {
          var point = map.latLngToLayerPoint(d.position);
          return 'translate(' + point.x + ',' + point.y + ') rotate(' + d.cog + ')';
        })
    boatData.exit().remove();
  }
  function reset() {
    var targetsArray = [];
    var multiPointForBounds = {
      "type": "MultiPoint",
      "coordinates": []
    };
    var threshold = new Date().getTime() - (2 * 60 * 1000);
    for (key in targets) {
      if (targets[key].timestamp > threshold) {
        targetsArray.push(targets[key]);
        multiPointForBounds.coordinates.push([targets[key].position.lng, targets[key].position.lat]);
      } else {
        delete targets[key];
      }
    };

    targetsArray = targetsArray.sort(function (a, b) {
      return b.sog - a.sog
    });

    var targetList = $('#targetList');
    targetList.empty();
    targetsArray.forEach(function (target) {
      if (target.show) {
        targetList.append('<tr><td>' + target.id + '</td><td>' + getName(target) + '</td><td>' +
            target.sog +'</td></tr>');
      }
    });<commit_msg>Safeguard against nonexistent position<commit_after><!DOCTYPE html>
<html>
<head>
  <title>SignalK Tracker</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <style>
    body {
      padding: 0;
      margin: 0;
    }

    html, body, #map {
      height: 100%;
    }

    svg {
      position: relative;
    }

    .targets {
      position: absolute;
      top: 0px;
      left: 0px;
    }

    .targetlist {
      background-image: url(FFFFFF-0.6.png);
      font-family: sans-serif;
    }
  </style>
  <script src="/signalk/stream/v1/primus.js"></script>
  <script src="dist/map.js"></script>
  <script src="/bower_components/L.EasyButton/easy-button.js"></script>
  <link rel="stylesheet" href="/bower_components/leaflet/dist/leaflet.css">
  <link href="/bower_components/components-font-awesome/css/font-awesome.css" rel="stylesheet">
</head>

<body class="leaflet-dragging">
<div id="map"></div>

<div class="targets">
  <table class="targetlist" id="targetList">
  </table>
</div>
</body>


<script>
  var map = new L.Map("map", {
    center: [37.8, -96.9],
    zoom: 4,
    zoomControl: false
  });
  map.setView([60.1, 24.8], 13);

  new L.Control.Zoom({ position: 'topright' }).addTo(map);

  var homeButton = new L.Control.EasyButtons();
  homeButton.options.intentedIcon = 'fa-home';
  homeButton.options.position = 'topright';
  homeButton.intendedFunction = function () {
    map.panTo(selfLocation);
  };
  map.addControl(homeButton);


  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map);


  var svg = d3.select(map.getPanes().overlayPane).append("svg");
  var g = svg.append("g").attr("class", "leaflet-zoom-hide");

  var transform = d3.geo.transform({point: projectPoint});
  var path = d3.geo.path().projection(transform);

  map.on("viewreset", reset);

  function updateMarkers(multiPointForBounds, targetsArray) {
    var bounds = path.bounds(multiPointForBounds),
        topLeft = bounds[0],
        bottomRight = bounds[1];

    svg.attr("width", bottomRight[0] - topLeft[0] + 20)
        .attr("height", bottomRight[1] - topLeft[1] + 20)
        .style("left", (topLeft[0] - 10) + "px")
        .style("top", (topLeft[1] - 10) + "px");

    g.attr("transform", "translate(" + (-topLeft[0] + 10) + "," + (-topLeft[1] + 10) + ")");

    var vesselColor = d3.scale.linear()
        .domain([0.9 * selfSpeed, selfSpeed, 1.1 * selfSpeed])
        .range(['blue', 'grey', 'red']);


    var boatData = g.selectAll('.vessel').data(targetsArray, function (d) {
      return d.id
    });
    boatData.enter().append("polygon").attr("class", "vessel").attr('points', "0,-10 5,10 -5,10");
    boatData
        .attr("style", function (d, i) {
          return d.id === 'self' ? "fill:black" : "fill:" + vesselColor(d.sog);
        })
        .attr('transform', function (d) {
          var point = map.latLngToLayerPoint(d.position);
          return 'translate(' + point.x + ',' + point.y + ') rotate(' + d.cog + ')';
        })
    boatData.exit().remove();
  }
  function reset() {
    var targetsArray = [];
    var multiPointForBounds = {
      "type": "MultiPoint",
      "coordinates": []
    };
    var threshold = new Date().getTime() - (2 * 60 * 1000);
    for (key in targets) {
      if (targets[key].timestamp > threshold && targets[key].position) {
        targetsArray.push(targets[key]);
        multiPointForBounds.coordinates.push([targets[key].position.lng, targets[key].position.lat]);
      } else {
        delete targets[key];
      }
    };

    targetsArray = targetsArray.sort(function (a, b) {
      return b.sog - a.sog
    });

    var targetList = $('#targetList');
    targetList.empty();
    targetsArray.forEach(function (target) {
      if (target.show) {
        targetList.append('<tr><td>' + target.id + '</td><td>' + getName(target) + '</td><td>' +
            target.sog +'</td></tr>');
      }
    });
{'fraction_non_alphanumeric': 0.1952463912394226, 'fraction_numerical': 0.018666002986560477, 'mean_word_length': 2.9493857493857494, 'pattern_counts': {'":': 4, '<': 75, '<?xml version=': 0, '>': 77, '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': '4383338', 'n_tokens_mistral': 2907, 'n_tokens_neox': 2747, 'n_words': 502}