<commit_before>// ==UserScript==
// @id             iitc-plugin-user-location@cradle
// @name           IITC plugin: User Location
// @category       Tweaks
// @version        0.2.0.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Show user location marker on map
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

window.plugin.userLocation = function() {};

window.plugin.userLocation.locationLayer = new L.LayerGroup();
window.plugin.userLocation.follow = false;

window.plugin.userLocation.setup = function() {
  $('<style>').prop('type', 'text/css').html('@@INCLUDESTRING:mobile/plugins/user-location.css@@').appendTo('head');

  $('<div style="position:absolute; left:-9999em; top:-9999em;">').html('@@INCLUDESTRING:mobile/plugins/user-location.svg@@').prependTo('body');

  var cssClass = PLAYER.team === 'RESISTANCE' ? 'res' : 'enl';

  var icon = L.divIcon({
    iconSize: L.point(32, 32),
    iconAnchor: L.point(16, 16),
    className: 'user-location',
    html: '<div class="container ' + cssClass + ' circle"><div class="outer"></div><div class="inner"></div></div>'
  });

  var marker = L.marker(new L.LatLng(0,0), {
    icon: icon,
    zIndexOffset: 300,
    clickable: false
  });

  var circle = new L.Circle(new L.LatLng(0,0), 40, {
    stroke: false,
    opacity: 0.7,
    fillOpacity: 1,
    fillColor: "url(#user-location-gradient)",
    weight: 1.5,
    clickable: false
  });

  marker.addTo(window.plugin.userLocation.locationLayer);
  window.plugin.userLocation.locationLayer.addTo(window.map);
  window.addLayerGroup('User location', window.plugin.userLocation.locationLayer, true);

  window.plugin.userLocation.marker = marker;
  window.plugin.userLocation.circle = circle;
  window.plugin.userLocation.icon = icon;

  window.map.on('movestart', window.plugin.userLocation.onMoveStart);
  window.map.on('zoomend', window.plugin.userLocation.onZoomEnd);
  window.plugin.userLocation.onZoomEnd();
};

window.plugin.userLocation.onMoveStart = function(e) {
  if(window.plugin.userLocation.moving)
    return;

  window.plugin.userLocation.follow = false;
  if(typeof android !== 'undefined' && android && android.setFollowMode)
    android.setFollowMode(window.plugin.userLocation.follow);
};

window.plugin.userLocation.onZoomEnd = function() {
  if(window.map.getZoom() < 16)
    window.plugin.userLocation.locationLayer.removeLayer(window.plugin.userLocation.circle);
  else
    window.plugin.userLocation.locationLayer.addLayer(window.plugin.userLocation.circle);
};

window.plugin.userLocation.locate = function(lat, lng, accuracy) {
  if(window.plugin.userLocation.follow) {
    window.plugin.userLocation.follow = false;
    if(typeof android !== 'undefined' && android && android.setFollowMode)
      android.setFollowMode(window.plugin.userLocation.follow);
    return;
  }

  var latlng = new L.LatLng(lat, lng);

  var latAccuracy = 180 * accuracy / 40075017;
  var lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat);

  var zoom = window.map.getBoundsZoom(L.latLngBounds(
    [lat - latAccuracy, lng - lngAccuracy],
    [lat + latAccuracy, lng + lngAccuracy]));

  // an extremely close view is pretty pointless (especially with maps that support zoom level 20+)
  // so limit to 17 (enough to see all portals)
  zoom = Math.min(zoom,17);

  if(window.map.getCenter().distanceTo(latlng) < 10) {
    window.plugin.userLocation.follow = true;
    if(typeof android !== 'undefined' && android && android.setFollowMode)
      android.setFollowMode(window.plugin.userLocation.follow);
  }

  window.map.setView(latlng, zoom);
}

window.plugin.userLocation.onLocationChange = function(lat, lng) {
  var latlng = new L.LatLng(lat, lng);
  window.plugin.userLocation.marker.setLatLng(latlng);
  window.plugin.userLocation.circle.setLatLng(latlng);

  if(window.plugin.userLocation.follow) {
    // move map if marker moves more than 35% from the center
    // 100% - 2*15% = 70% → 35% from center in either direction
    if(map.getBounds().pad(-0.15).contains(latlng))
      return;

    window.plugin.userLocation.moving = true;
    window.map.setView(latlng);
    window.plugin.userLocation.moving = false;
  }
};

window.plugin.userLocation.onOrientationChange = function(direction) {
  var container = $(".container", window.plugin.userLocation.marker._icon);
<commit_msg>don't leave follow mode on mapmove for a variable zoom the user may want to use different zooms in follow mode (for example if he rides a bike or drives a car)...unfortunately, leaflet triggers maps movestart event _before_ the zoomstart event. this makes it impossible to differentiate between a mapmove triggered by a zoom-event or a move-event. the user can leave the follow mode by pressing the getLocation button...this should be enough.<commit_after>// ==UserScript==
// @id             iitc-plugin-user-location@cradle
// @name           IITC plugin: User Location
// @category       Tweaks
// @version        0.2.0.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Show user location marker on map
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

window.plugin.userLocation = function() {};

window.plugin.userLocation.locationLayer = new L.LayerGroup();
window.plugin.userLocation.follow = false;

window.plugin.userLocation.setup = function() {
  $('<style>').prop('type', 'text/css').html('@@INCLUDESTRING:mobile/plugins/user-location.css@@').appendTo('head');

  $('<div style="position:absolute; left:-9999em; top:-9999em;">').html('@@INCLUDESTRING:mobile/plugins/user-location.svg@@').prependTo('body');

  var cssClass = PLAYER.team === 'RESISTANCE' ? 'res' : 'enl';

  var icon = L.divIcon({
    iconSize: L.point(32, 32),
    iconAnchor: L.point(16, 16),
    className: 'user-location',
    html: '<div class="container ' + cssClass + ' circle"><div class="outer"></div><div class="inner"></div></div>'
  });

  var marker = L.marker(new L.LatLng(0,0), {
    icon: icon,
    zIndexOffset: 300,
    clickable: false
  });

  var circle = new L.Circle(new L.LatLng(0,0), 40, {
    stroke: false,
    opacity: 0.7,
    fillOpacity: 1,
    fillColor: "url(#user-location-gradient)",
    weight: 1.5,
    clickable: false
  });

  marker.addTo(window.plugin.userLocation.locationLayer);
  window.plugin.userLocation.locationLayer.addTo(window.map);
  window.addLayerGroup('User location', window.plugin.userLocation.locationLayer, true);

  window.plugin.userLocation.marker = marker;
  window.plugin.userLocation.circle = circle;
  window.plugin.userLocation.icon = icon;

  window.map.on('zoomend', window.plugin.userLocation.onZoomEnd);
  window.plugin.userLocation.onZoomEnd();
};

window.plugin.userLocation.onZoomEnd = function() {
  if(window.map.getZoom() < 16)
    window.plugin.userLocation.locationLayer.removeLayer(window.plugin.userLocation.circle);
  else
    window.plugin.userLocation.locationLayer.addLayer(window.plugin.userLocation.circle);
};

window.plugin.userLocation.locate = function(lat, lng, accuracy) {
  if(window.plugin.userLocation.follow) {
    window.plugin.userLocation.follow = false;
    if(typeof android !== 'undefined' && android && android.setFollowMode)
      android.setFollowMode(window.plugin.userLocation.follow);
    return;
  }

  var latlng = new L.LatLng(lat, lng);

  var latAccuracy = 180 * accuracy / 40075017;
  var lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat);

  var zoom = window.map.getBoundsZoom(L.latLngBounds(
    [lat - latAccuracy, lng - lngAccuracy],
    [lat + latAccuracy, lng + lngAccuracy]));

  // an extremely close view is pretty pointless (especially with maps that support zoom level 20+)
  // so limit to 17 (enough to see all portals)
  zoom = Math.min(zoom,17);

  if(window.map.getCenter().distanceTo(latlng) < 10) {
    window.plugin.userLocation.follow = true;
    if(typeof android !== 'undefined' && android && android.setFollowMode)
      android.setFollowMode(window.plugin.userLocation.follow);
  }

  window.map.setView(latlng, zoom);
}

window.plugin.userLocation.onLocationChange = function(lat, lng) {
  var latlng = new L.LatLng(lat, lng);
  window.plugin.userLocation.marker.setLatLng(latlng);
  window.plugin.userLocation.circle.setLatLng(latlng);

  if(window.plugin.userLocation.follow) {
    // move map if marker moves more than 35% from the center
    // 100% - 2*15% = 70% → 35% from center in either direction
    if(map.getBounds().pad(-0.15).contains(latlng))
      return;

    window.map.setView(latlng);
  }
};

window.plugin.userLocation.onOrientationChange = function(direction) {
  var container = $(".container", window.plugin.userLocation.marker._icon);

{'fraction_non_alphanumeric': 0.161198738170347, 'fraction_numerical': 0.014511041009463722, 'mean_word_length': 3.6282238442822385, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 19, 'https://': 6, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7540716', 'n_tokens_mistral': 3174, 'n_tokens_neox': 2986, 'n_words': 587}