202 lines
7.9 KiB
Python
202 lines
7.9 KiB
Python
from operator import itemgetter
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.cache import cache
|
|
from django.utils import timezone
|
|
from kombu.utils import cached_property
|
|
|
|
from c3nav.control.models import UserPermissions
|
|
from c3nav.mapdata.models import Level, LocationGroup, LocationSlug, Space
|
|
from c3nav.mapdata.models.geometry.space import POI, Area, WifiMeasurement
|
|
from c3nav.mapdata.models.locations import LocationRedirect
|
|
from c3nav.mapdata.utils.locations import CustomLocation, get_location_by_id_for_request
|
|
|
|
|
|
def increment_cache_key(cache_key):
|
|
try:
|
|
cache.incr(cache_key)
|
|
except ValueError:
|
|
cache.set(cache_key, 1, None)
|
|
|
|
|
|
def stats_snapshot(reset=True):
|
|
last_now = cache.get('apistats_last_reset', '', None)
|
|
now = timezone.now()
|
|
results = {}
|
|
for key in cache.keys('apistats__*'):
|
|
results[key] = cache.get(key)
|
|
if reset:
|
|
cache.delete(key)
|
|
if reset:
|
|
cache.set('apistats_last_reset', now, None)
|
|
results = dict(sorted(results.items()))
|
|
return {
|
|
'start_date': str(last_now),
|
|
'end_date': str(now),
|
|
'data': results
|
|
}
|
|
|
|
|
|
def _filter_stats(tag, stats, startswith=False):
|
|
if startswith:
|
|
return (([name[0][len(tag):]]+name[1:], value) for name, value in stats if name[0].startswith(tag))
|
|
return ((name[1:], value) for name, value in stats if name[0] == tag)
|
|
|
|
|
|
class FakeRequest():
|
|
@cached_property
|
|
def user(self):
|
|
return get_user_model().objects.filter(is_superuser=True).first()
|
|
|
|
@cached_property
|
|
def user_permissions(self):
|
|
return UserPermissions.get_for_user(self.user)
|
|
|
|
|
|
fake_request = FakeRequest()
|
|
|
|
|
|
def convert_stats(stats):
|
|
stats = [(name.split('__')[1:], value) for name, value in stats['data'].items()]
|
|
result = {}
|
|
result['locate'] = convert_locate(_filter_stats('locate', stats))
|
|
result['location_retrieve'] = convert_location(_filter_stats('location_retrieve', stats))
|
|
result['location_geometry'] = convert_location(_filter_stats('location_geometry', stats))
|
|
result['route_origin'] = convert_location(
|
|
(['pk']+name, value) for name, value in _filter_stats('route_origin_', stats, startswith=True)
|
|
)
|
|
result['route_destination'] = convert_location(
|
|
(['pk'] + name, value) for name, value in _filter_stats('route_destination_', stats, startswith=True)
|
|
)
|
|
return result
|
|
|
|
|
|
def _sort_count(map, key):
|
|
map[key] = dict(sorted(map[key].items(), key=itemgetter(1), reverse=True))
|
|
|
|
|
|
def convert_locate(data):
|
|
result = {
|
|
'total': 0,
|
|
'by_measurement_id': {},
|
|
'by_space': {},
|
|
'by_level': {},
|
|
}
|
|
measurement_lookup = {}
|
|
for measurement in WifiMeasurement.objects.all().select_related('space', 'space__level'):
|
|
pos = CustomLocation(measurement.space.level, measurement.geometry.x, measurement.geometry.y,
|
|
permissions=set()).pk
|
|
space_slug = measurement.space.get_slug()
|
|
level_label = measurement.space.level.short_label
|
|
measurement_lookup[pos] = (measurement.pk, space_slug, level_label)
|
|
result['by_measurement_id'][measurement.pk] = 0
|
|
result['by_space'][space_slug] = 0
|
|
result['by_level'][level_label] = 0
|
|
|
|
for name, value in data:
|
|
result['total'] += value
|
|
measurement = measurement_lookup.get(name[0], None)
|
|
if measurement:
|
|
result['by_measurement_id'][measurement[0]] += value
|
|
result['by_space'][measurement[1]] += value
|
|
result['by_level'][measurement[2]] += value
|
|
|
|
_sort_count(result, 'by_measurement_id')
|
|
_sort_count(result, 'by_space')
|
|
_sort_count(result, 'by_level')
|
|
return result
|
|
|
|
|
|
def convert_location(data):
|
|
result = {
|
|
'total': 0,
|
|
'invalid': 0,
|
|
'locations': {
|
|
'total': 0,
|
|
'by_type': {},
|
|
'by_space': {},
|
|
'by_level': {},
|
|
'by_group': {},
|
|
},
|
|
'coordinates': {
|
|
'total': 0,
|
|
'by_level': {},
|
|
'by_space': {},
|
|
'by_area': {},
|
|
'by_poi': {},
|
|
}
|
|
}
|
|
|
|
# fill up lists with zeros
|
|
location_slugs = {}
|
|
level_labels = {}
|
|
for location in LocationSlug.objects.all():
|
|
location = location.get_child()
|
|
if isinstance(location, LocationRedirect):
|
|
continue
|
|
result['locations']['by_type'].setdefault(location.__class__.__name__.lower(), {})[location.get_slug()] = 0
|
|
location_slugs[location.pk] = location.get_slug()
|
|
if isinstance(location, Level):
|
|
result['locations']['by_level'][location.short_label] = 0
|
|
result['coordinates']['by_level'][location.short_label] = 0
|
|
level_labels[location.pk] = location.short_label
|
|
if isinstance(location, Space):
|
|
result['locations']['by_space'][location.get_slug()] = 0
|
|
result['coordinates']['by_space'][location.get_slug()] = 0
|
|
if isinstance(location, Area):
|
|
if getattr(location, 'can_search', False) or getattr(location, 'can_describe', False):
|
|
result['coordinates']['by_area'][location.get_slug()] = 0
|
|
if isinstance(location, POI):
|
|
if getattr(location, 'can_search', False) or getattr(location, 'can_describe', False):
|
|
result['coordinates']['by_poi'][location.get_slug()] = 0
|
|
if isinstance(location, LocationGroup):
|
|
result['locations']['by_group'][location.get_slug()] = 0
|
|
|
|
for name, value in data:
|
|
if name[0] != 'pk' or name[0] == 'c:anywhere':
|
|
continue
|
|
location = get_location_by_id_for_request(name[1], fake_request)
|
|
result['total'] += value
|
|
if location is None:
|
|
result['invalid'] += value
|
|
continue
|
|
if isinstance(location, CustomLocation):
|
|
location.x += 1.5
|
|
location.y += 1.5
|
|
result['coordinates']['total'] += value
|
|
result['coordinates']['by_level'][location_slugs[location.level.pk]] += value
|
|
if location.space is None:
|
|
continue
|
|
result['coordinates']['by_space'][location_slugs[location.space.pk]] += value
|
|
for area in location.areas:
|
|
result['coordinates']['by_area'][location_slugs[area.pk]] += value
|
|
if location.near_area:
|
|
result['coordinates']['by_area'][location_slugs[location.near_area.pk]] += value
|
|
if location.near_poi:
|
|
result['coordinates']['by_poi'][location_slugs[location.near_poi.pk]] += value
|
|
else:
|
|
result['locations']['total'] += value
|
|
location = getattr(location, 'target', location)
|
|
result['locations']['by_type'].setdefault(location.__class__.__name__.lower(),
|
|
{})[location.get_slug()] += value
|
|
if hasattr(location, 'space_id'):
|
|
result['locations']['by_space'][location_slugs[location.space_id]] += value
|
|
if hasattr(location, 'level_id'):
|
|
result['locations']['by_level'][level_labels[location.level_id]] += value
|
|
if hasattr(location, 'groups'):
|
|
for group in location.groups.all():
|
|
result['locations']['by_group'][location_slugs[group.pk]] += value
|
|
|
|
_sort_count(result['locations']['by_type'], 'level')
|
|
_sort_count(result['locations']['by_type'], 'space')
|
|
_sort_count(result['locations']['by_type'], 'area')
|
|
_sort_count(result['locations']['by_type'], 'poi')
|
|
_sort_count(result['locations']['by_type'], 'locationgroup')
|
|
_sort_count(result['locations'], 'by_space')
|
|
_sort_count(result['locations'], 'by_level')
|
|
_sort_count(result['locations'], 'by_group')
|
|
_sort_count(result['coordinates'], 'by_level')
|
|
_sort_count(result['coordinates'], 'by_space')
|
|
_sort_count(result['coordinates'], 'by_area')
|
|
_sort_count(result['coordinates'], 'by_poi')
|
|
return result
|