1
0
Fork 0
satnogs-network/network/base/stats.py

107 lines
3.9 KiB
Python

import math
from django.core.cache import cache
from django.db.models import Case, IntegerField, Sum, When
from django.utils.timezone import now
from network.base.models import Observation
def transmitter_stats_by_uuid(uuid):
stats = cache.get('tr-{0}-stats'.format(uuid))
if stats is None:
# Sum - Case - When should be replaced with Count and filter when we move to Django 2.*
# more at https://docs.djangoproject.com/en/2.2/ref/models/conditional-expressions in
# "Conditional aggregation" section.
stats = Observation.objects.filter(
transmitter_uuid=uuid
).exclude(
vetted_status='failed'
).aggregate(
good=Sum(
Case(When(vetted_status='good', then=1),
output_field=IntegerField())
),
bad=Sum(
Case(When(vetted_status='bad', then=1),
output_field=IntegerField())
),
unvetted=Sum(
Case(When(vetted_status='unknown',
end__lte=now(), then=1),
output_field=IntegerField())
),
future=Sum(
Case(When(vetted_status='unknown',
end__gt=now(), then=1),
output_field=IntegerField())
)
)
cache.set('tr-{0}-stats'.format(uuid), stats, 3600)
total_count = 0
unvetted_count = 0 if stats['unvetted'] is None else stats['unvetted']
future_count = 0 if stats['future'] is None else stats['future']
good_count = 0 if stats['good'] is None else stats['good']
bad_count = 0 if stats['bad'] is None else stats['bad']
total_count = unvetted_count + future_count + good_count + bad_count
unvetted_rate = 0
future_rate = 0
success_rate = 0
bad_rate = 0
if total_count:
unvetted_rate = math.trunc(10000 * (float(unvetted_count) / float(total_count))) / 100.0
future_rate = math.trunc(10000 * (float(future_count) / float(total_count))) / 100.0
success_rate = math.trunc(10000 * (float(good_count) / float(total_count))) / 100.0
bad_rate = math.trunc(10000 * (float(bad_count) / float(total_count))) / 100.0
return {
'total_count': total_count,
'unvetted_count': unvetted_count,
'future_count': future_count,
'good_count': good_count,
'bad_count': bad_count,
'unvetted_rate': unvetted_rate,
'future_rate': future_rate,
'success_rate': success_rate,
'bad_rate': bad_rate
}
def satellite_stats_by_transmitter_list(transmitter_list):
total_count = 0
unvetted_count = 0
future_count = 0
good_count = 0
bad_count = 0
unvetted_rate = 0
future_rate = 0
success_rate = 0
bad_rate = 0
for transmitter in transmitter_list:
transmitter_stats = transmitter_stats_by_uuid(transmitter['uuid'])
total_count += transmitter_stats['total_count']
unvetted_count += transmitter_stats['unvetted_count']
future_count += transmitter_stats['future_count']
good_count += transmitter_stats['good_count']
bad_count += transmitter_stats['bad_count']
if total_count:
unvetted_rate = math.trunc(10000 * (float(unvetted_count) / float(total_count))) / 100.0
future_rate = math.trunc(10000 * (float(future_count) / float(total_count))) / 100.0
success_rate = math.trunc(10000 * (float(good_count) / float(total_count))) / 100.0
bad_rate = math.trunc(10000 * (float(bad_count) / float(total_count))) / 100.0
return {
'total_count': total_count,
'unvetted_count': unvetted_count,
'future_count': future_count,
'good_count': good_count,
'bad_count': bad_count,
'unvetted_rate': unvetted_rate,
'future_rate': future_rate,
'success_rate': success_rate,
'bad_rate': bad_rate
}