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