Failed Conditions
Pull Request — master (#275)
by Ramiro
02:40
created

pokemon.maps.js ➔ initMap   B

Complexity

Conditions 1
Paths 32

Size

Total Lines 95

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
nc 32
nop 0
dl 0
loc 95
rs 8.4117
c 2
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B pokemon.maps.js ➔ ... ➔ $.then 0 81 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
/** global: google */
2
/** global: pokemon_id */
3
/** global: navigator */
4
5
var map, heatmap;
6
var pokemonMarkers = {};
7
var updateLiveTimeout;
8
var markerCluster = false;
9
10
var ivMin = 80;
11
var ivMax = 100;
12
13
function initMap() {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
14
	var geoOpts = {
15
		'type': "GET",
16
		'global': false,
17
		'dataType': 'json',
18
		'url': "core/process/aru.php",
19
		'data': {
20
			'request': "",
21
			'target': 'arrange_url',
22
			'method': 'method_target',
23
			'type': 'maps_localization_coordinates'
24
		}
25
	}
26
	$.when($.getJSON( "core/json/variables.json"), $.ajax(geoOpts)).then(function (response1, response2) {
27
		var variables = response1[0];
28
		var coordinates = response2[0];
29
		var latitude = Number(variables['system']['map_center_lat']);
30
		var longitude = Number(variables['system']['map_center_long']);
31
		var zoom_level = Number(variables['system']['zoom_level']);
32
		var pokeimg_suffix = variables['system']['pokeimg_suffix'];
33
		var cluster = variables.system.cluster_pokemon;
34
35
		map = new google.maps.Map(document.getElementById('map'), {
36
			center: {
37
				lat: latitude,
38
				lng: longitude
39
			},
40
			zoom: zoom_level,
41
			zoomControl: true,
42
			scaleControl: false,
43
			scrollwheel: true,
44
			disableDoubleClickZoom: false,
45
			streetViewControl: false,
46
			mapTypeControlOptions: {
47
				mapTypeIds: [
48
					google.maps.MapTypeId.ROADMAP,
49
					'pogo_style',
50
					'dark_style',
51
				]
52
			}
53
		});
54
55
		$.getJSON( 'core/json/pogostyle.json', function( data ) {
56
			var styledMap_pogo = new google.maps.StyledMapType(data, {name: 'PoGo'});
57
			map.mapTypes.set('pogo_style', styledMap_pogo);
58
		});
59
		$.getJSON( 'core/json/darkstyle.json', function( data ) {
60
			var styledMap_dark = new google.maps.StyledMapType(data, {name: 'Dark'});
61
			map.mapTypes.set('dark_style', styledMap_dark);
62
		});
63
		$.getJSON( 'core/json/defaultstyle.json', function( data ) {
64
			map.set('styles', data);
65
		});
66
67
		if (navigator.geolocation) {
68
			navigator.geolocation.getCurrentPosition(function(position) {
69
				var pos = {
70
					lat: position.coords.latitude,
71
					lng: position.coords.longitude
72
				};
73
74
				if (position.coords.latitude <= coordinates.max_latitude && position.coords.latitude >= coordinates.min_latitude) {
75
					if (position.coords.longitude <= coordinates.max_longitude && position.coords.longitude >= coordinates.min_longitude) {
76
						map.setCenter(pos);
77
					}
78
				}
79
			});
80
		}
81
		
82
		if (cluster) {
83
			var clusterOptions = {
84
				cssClass: 'pokedexCluster',
85
				gridSize: cluster.grid || 60,
86
				minimumClusterSize: cluster.minCluster || 3,
87
			}
88
			markerCluster = new MarkerClusterer(map, [], clusterOptions);
0 ignored issues
show
Bug introduced by
The variable MarkerClusterer seems to be never declared. If this is a global, consider adding a /** global: MarkerClusterer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
89
			markerCluster.setCalculator(function(markers) {
90
				var index = 1;
91
				var len = markers.length;
92
				if (len > 7 && len < 15) {
93
					index = 2;
94
				} else if (len >= 15){
95
					index = 3;
96
				}
97
				return {
98
					text: len,
99
					index: index
100
				}
101
			});
102
		}
103
		initHeatmap();
104
		initSelector(pokeimg_suffix);
105
		
106
	});
107
}
108
109
function initSelector(pokeimg_suffix){
110
	$('#heatmapSelector').click(function(){
111
		hideLive();
112
		showHeatmap();
113
		$('#heatmapSelector').addClass('active');
114
		$('#liveSelector').removeClass('active');
115
	});
116
	$('#liveSelector').click(function(){
117
		hideHeatmap();
118
		map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
119
		initLive(pokeimg_suffix);
120
		
121
		
122
		$('#liveSelector').addClass('active');
123
		$('#heatmapSelector').removeClass('active');
124
	});
125
}
126
127
function initLive(pokeimg_suffix){
128
	showLive();
129
	$("#liveFilterSelector").rangeSlider({
130
		bounds:{
131
			min: 0,
132
			max: 100
133
		},
134
		defaultValues:{
135
			min: ivMin,
136
			max: ivMax
137
		},
138
		formatter:function(val) {
139
			return "IV: "+Math.round(val)+"%";
140
		}
141
	});
142
	
143
	$("#liveFilterSelector").bind("valuesChanged",function(e, data){
144
		clearTimeout(updateLiveTimeout);
145
		removePokemonMarkerByIv(data.values.min,data.values.max);
146
		ivMin = data.values.min;
147
		ivMax = data.values.max;
148
		updateLive(pokeimg_suffix);
149
	});
150
	updateLive(pokeimg_suffix);
151
	
152
}
153
154
function initHeatmap(){
155
	$.ajax({
156
		'async': true,
157
		'type': "GET",
158
		'global': false,
159
		'dataType': 'json',
160
		'url': "core/process/aru.php",
161
		'data': {
162
			'request': "",
163
			'target': 'arrange_url',
164
			'method': 'method_target',
165
			'type' : 'pokemon_slider_init'
166
		}
167
	}).done(function(bounds){
168
		initHeatmapData(bounds);
169
	});
170
	
171
}
172
173
function initHeatmapData(bounds){
174
	var boundMin = new Date(bounds.min.replace(/-/g, "/"));
175
	var boundMax = new Date(bounds.max.replace(/-/g, "/"));
176
	var selectorMax = boundMax;
177
	var selectorMin = boundMin;
178
179
	// two weeks in millisec
180
	var twoWeeks = 12096e5;
181
	var maxMinus2Weeks = new Date(selectorMax.getTime() - twoWeeks);
182
	if(selectorMin < maxMinus2Weeks){
183
		selectorMin = maxMinus2Weeks;
184
	}
185
186
	// dict with millisec => migration nr.
187
	var migrations = {};
188
	// start at 4 because 06. Oct 2016 was the 4th migration
189
	var migr_nr = 4;
190
	$("#timeSelector").dateRangeSlider({
191
		bounds:{
192
			min: boundMin,
193
			max: boundMax
194
		},
195
		defaultValues:{
196
			min: selectorMin,
197
			max: selectorMax
198
		},
199
		scales: [{
200
			first: function(value) {
201
				// 06. Oct 2016 (4th migration). 2 week schedule starts with this migration
202
				var migrationStart = new Date("2016-10-06T00:00:00Z");
203
				var now = new Date();
204
				var result = new Date();
205
				for (var migration = migrationStart; migration <= now; migration.setTime(migration.getTime() + twoWeeks)) {
206
					if (migration >= value) {
207
						result = migration;
208
						migrations[result.getTime()] = migr_nr;
209
						break;
210
					}
211
					migr_nr++;
212
				}
213
				return result;
214
			},
215
			next: function(value){
216
				var next = new Date(new Date(value).setTime(value.getTime() + twoWeeks));
217
				migr_nr++;
218
				migrations[next.getTime()] = migr_nr;
219
				return next;
220
			},
221
			label: function(value){
222
				if (isMobileDevice() && isTouchDevice()) {
223
					return "#" + migrations[value.getTime()];
224
				}
225
				return "Migration #" + migrations[value.getTime()];
226
			},
227
		}]
228
	});
229
	createHeatmap();
230
231
}
232
233
function createHeatmap() {
234
	
235
	heatmap = new google.maps.visualization.HeatmapLayer({
236
		data: [],
237
		map: map
238
	});
239
240
	var gradient = [
241
		'rgba(0, 255, 255, 0)',
242
		'rgba(0, 255, 255, 1)',
243
		'rgba(0, 191, 255, 1)',
244
		'rgba(0, 127, 255, 1)',
245
		'rgba(0, 63, 255, 1)',
246
		'rgba(0, 0, 255, 1)',
247
		'rgba(0, 0, 223, 1)',
248
		'rgba(0, 0, 191, 1)',
249
		'rgba(0, 0, 159, 1)',
250
		'rgba(0, 0, 127, 1)',
251
		'rgba(63, 0, 91, 1)',
252
		'rgba(127, 0, 63, 1)',
253
		'rgba(191, 0, 31, 1)',
254
		'rgba(255, 0, 0, 1)'
255
	];
256
	heatmap.set('gradient', gradient);
257
	heatmap.setMap(map);
258
	$("#timeSelector").bind("valuesChanged",function(){updateHeatmap()});
259
	$("#timeSelector").dateRangeSlider("min"); // will trigger valuesChanged
260
}
261
262
function updateHeatmap() {
263
	var dateMin = $("#timeSelector").dateRangeSlider("min");
264
	var dateMax = $("#timeSelector").dateRangeSlider("max");
265
	$("#loaderContainer").show();
266
	$.ajax({
267
		'async': true,
268
		'type': "GET",
269
		'global': false,
270
		'dataType': 'json',
271
		'url': "core/process/aru.php",
272
		'data': {
273
			'request': "",
274
			'target': 'arrange_url',
275
			'method': 'method_target',
276
			'type' : 'pokemon_heatmap_points',
277
			'pokemon_id' : pokemon_id,
278
			'start' : Math.floor(dateMin.getTime()/1000),
279
			'end' : Math.floor(dateMax.getTime()/1000)
280
		}
281
	}).done(function(points){
282
		var googlePoints = [];
283
		for (var i = 0; i < points.length; i++) {
284
			googlePoints.push(new google.maps.LatLng(points[i].latitude,points[i].longitude))
285
		}
286
		var newPoints = new google.maps.MVCArray(googlePoints);
287
		heatmap.set('data', newPoints);
288
		$("#loaderContainer").hide();
289
	});
290
}
291
292
function hideHeatmap() {
293
	$("#timeFilterContainer").hide();
294
	heatmap.set('map', null);
295
}
296
297
function showHeatmap() {
298
	$("#timeFilterContainer").show();
299
	heatmap.set('map', map);
300
	hideLive();
301
}
302
303
function hideLive() {
304
	$("#liveFilterContainer").hide();
305
	clearTimeout(updateLiveTimeout);
306
	clearPokemonMarkers();
307
}
308
309
function showLive() {
310
	hideHeatmap();
311
	clearTimeout(updateLiveTimeout);
312
	$("#liveFilterContainer").show();
313
	
314
}
315
316
function updateLive(pokeimg_suffix){
317
	$.ajax({
318
		'async': true,
319
		'type': "POST",
320
		'global': false,
321
		'dataType': 'json',
322
		'url': "core/process/aru.php",
323
		'data': {
324
			'request': "",
325
			'target': 'arrange_url',
326
			'method': 'method_target',
327
			'type' : 'pokemon_live',
328
			'pokemon_id' : pokemon_id,
329
			'inmap_pokemons' : extractEncountersId(),
330
			'ivMin' : ivMin,
331
			'ivMax' : ivMax
332
		}
333
	}).done(function(pokemons){
334
		for (var i = 0; i < pokemons.points.length; i++) {
335
			var marker = addPokemonMarker(pokemons.points[i],pokeimg_suffix, pokemons.locale);
336
			if (markerCluster) {
337
				markerCluster.addMarker(marker);
338
			} else {
339
				marker.setMap(map);
340
			}
341
		}		
342
		updateLiveTimeout=setTimeout(function(){ updateLive(pokeimg_suffix) },5000);
343
	});
344
}
345
346
function addPokemonMarker(pokemon,pokeimg_suffix, locale) {
347
	var image = {
348
		url:'core/pokemons/'+pokemon.pokemon_id+pokeimg_suffix,
349
		scaledSize: new google.maps.Size(32, 32),
350
		origin: new google.maps.Point(0,0),
351
		anchor: new google.maps.Point(16, 16),
352
		labelOrigin : new google.maps.Point(16, 36)
353
	};
354
	var encountered = false;
355
	var ivPercent = 100;
356
	if (pokemon.individual_attack !== null) {
357
		encounter = true;
0 ignored issues
show
Bug introduced by
The variable encounter seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.encounter.
Loading history...
358
		ivPercent = ((100/45)*(parseInt(pokemon.individual_attack)+parseInt(pokemon.individual_defense)+parseInt(pokemon.individual_stamina))).toFixed(2);
359
	}
360
	var marker = new google.maps.Marker({
361
		position: {lat: parseFloat(pokemon.latitude), lng:parseFloat(pokemon.longitude)},
362
		icon: image,
363
		ivPercent: ivPercent
364
	});
365
	if (encountered) {		
366
		marker.setLabel(getMarkerLabel(ivPercent));
367
	}
368
369
	var infoWindow = new google.maps.InfoWindow(getPokemonContent(pokemon, locale, encountered, ivPercent));	
370
	infoWindow.isClickOpen = false;
371
	marker.addListener('click', function() {
372
		infoWindow.isClickOpen = true;
373
		infoWindow.open(map, this);
374
	});
375
	google.maps.event.addListener(infoWindow,'closeclick',function(){
376
		this.isClickOpen = false;
377
	});
378
	marker.addListener('mouseover', function() {
379
		infoWindow.open(map, this);
380
	});
381
382
	// assuming you also want to hide the infowindow when user mouses-out
383
	marker.addListener('mouseout', function() {
384
		if(infoWindow.isClickOpen === false){
385
			infoWindow.close();
386
		}
387
	});
388
	pokemonMarkers[pokemon.encounter_id] = marker;
389
	var now = new Date().getTime();
390
	var endTime = new Date(pokemon.disappear_time_real.replace(/-/g, "/")).getTime();
391
	
392
	setTimeout(function(){ removePokemonMarker(pokemon.encounter_id) },endTime-now);
393
	return marker;
394
}
395
396
function getMarkerLabel(ivPercent) {
397
	if(ivPercent<80){
398
		return null;
399
	}
400
	var ivColor="rgba(0, 0, 255, 0.70)";
401
	if(ivPercent>90){
402
		ivColor="rgba(246, 178, 107, 0.90)";
403
	}
404
	if(ivPercent>99){
405
		ivColor="rgba(255, 0, 0, 1)";
406
	}
407
	return {
408
			color:ivColor,
409
			text:ivPercent+"%"
410
		};
411
}
412
413
function getPokemonContent(pokemon, locale, encountered, ivPercent) {
414
	var contentString = '<div>'+
415
			'<h4> '+pokemon.name+' #'+pokemon.pokemon_id+ (encountered?' IV: '+ivPercent+'% ':'')+'</h4>'+
416
			'<div id="bodyContent">'+
417
				'<p class="disappear_time_display text-center">'+pokemon.disappear_time_real+'<span class="disappear_time_display_timeleft"></span></p>';
418
	if (encountered) {
419
		contentString +=
420
				'<p></p>'+
421
				'<div class="progress" style="height: 6px; width: 120px; margin-bottom: 10px; margin-top: 2px; margin-left: auto; margin-right: auto">'+
422
					'<div title="'+locale.ivAttack+': '+pokemon.individual_attack+'" class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="'+pokemon.individual_attack+'" aria-valuemin="0" aria-valuemax="45" style="width: '+(((100/15)*pokemon.individual_attack)/3)+'%">'+
423
						'<span class="sr-only">'+locale.ivAttack+': '+pokemon.individual_attack+'</span>'+
424
					'</div>'+
425
					'<div title="'+locale.ivDefense+': '+pokemon.individual_defense+'" class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="'+pokemon.individual_defense+'" aria-valuemin="0" aria-valuemax="45" style="width: '+(((100/15)*pokemon.individual_defense)/3)+'%">'+
426
						'<span class="sr-only">'+locale.ivDefense+': '+pokemon.individual_defense+'</span>'+
427
					'</div>'+
428
					'<div title="'+locale.ivStamina+': '+pokemon.individual_stamina+'" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="'+pokemon.individual_stamina+'" aria-valuemin="0" aria-valuemax="45" style="width: '+(((100/15)*pokemon.individual_stamina)/3)+'%">'+
429
						'<span class="sr-only">'+locale.ivStamina+': '+pokemon.individual_stamina+'</span>'+
430
					'</div>'+
431
				'</div>'+
432
				'<p class="text-center">('+pokemon.individual_attack+"/"+pokemon.individual_defense+"/"+pokemon.individual_stamina+')</p>'+
433
				'<p class="text-center">'+pokemon.quick_move+"/"+pokemon.charge_move+'</p>';
434
	}
435
	contentString +='</div>';
436
	return {content: contentString};
437
}
438
439
function clearPokemonMarkers() {
440
	for(var key in pokemonMarkers) { 
441
	   if (pokemonMarkers.hasOwnProperty(key)) {
442
		   removePokemonMarker(pokemonMarkers[key]);
443
	   }
444
	}
445
	pokemonMarkers = {};
446
}
447
function removePokemonMarkerByEncounter(encounter_id) {
448
	removePokemonMarker(pokemonMarkers[encounter_id]);
449
	delete pokemonMarkers[encounter_id];
450
}
451
452
function removePokemonMarker(marker) {
453
	if (markerCluster) {
454
		markerCluster.removeMarker(marker);
455
	} else {
456
		marker.setMap(null);
457
	}
458
}
459
460
461
function removePokemonMarkerByIv(ivMin,ivMax) {
462
	for(var key in pokemonMarkers) { 
463
	   if (pokemonMarkers.hasOwnProperty(key)) {
464
			var marker = pokemonMarkers[key];
465
			if(marker.ivPercent < ivMin || marker.ivPercent > ivMax){
466
				removePokemonMarker(marker);
467
				delete pokemonMarkers[key];
468
			}
469
	   }
470
	}
471
}
472
473
function extractEncountersId(){
474
	var inmapEncounter = [];
475
	for(var key in pokemonMarkers) { 
476
		if (pokemonMarkers.hasOwnProperty(key)) {
477
			inmapEncounter.push(key);
478
		}
479
	}
480
	return inmapEncounter;
481
}
482
483
function isTouchDevice() {
484
	// Should cover most browsers
485
	return 'ontouchstart' in window || navigator.maxTouchPoints
486
}
487
488
function isMobileDevice() {
489
	// Basic mobile OS (not browser) detection
490
	return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
491
}
492