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