spaceport/apiserver/apiserver/api/utils_stats.py

203 lines
6.4 KiB
Python

import logging
logger = logging.getLogger(__name__)
import time
from datetime import date, datetime, timedelta
import requests
from django.db.models import Prefetch
from django.core.cache import cache
from django.utils.timezone import now, pytz
from apiserver.api import models, utils
from apiserver import secrets
DEFAULTS = {
'last_card_change': time.time(),
'next_meeting': None,
'next_clean': None,
'next_class': None,
'prev_class': None,
'member_count': None,
'paused_count': None,
'green_count': None,
'bay_108_temp': None,
'bay_110_temp': None,
'minecraft_players': [],
'card_scans': 0,
'track': {},
'alarm': {},
'sign': '',
'link': '',
'autoscan': '',
}
if secrets.MUMBLE:
DEFAULTS['mumble_users'] = []
def changed_card():
'''
Called whenever the card list could change, ie. cards added, modified, or
user status becoming overdue by 3 months
'''
cache.set('last_card_change', time.time())
def calc_next_events():
sessions = models.Session.objects
# TODO, go by tag?
member_meeting = sessions.filter(is_cancelled=False, course__in=[317, 413], datetime__gte=now()).first()
monthly_clean = sessions.filter(is_cancelled=False, course=273, datetime__gte=now()).first()
next_class = sessions.exclude(course__in=[317, 413, 273]).filter(is_cancelled=False, datetime__gte=now()).order_by('datetime').first()
prev_class = sessions.exclude(course__in=[317, 413, 273]).filter(is_cancelled=False, datetime__lte=now()).order_by('datetime').last()
if member_meeting:
cache.set('next_meeting', member_meeting.datetime)
else:
cache.set('next_meeting', None)
if monthly_clean:
cache.set('next_clean', monthly_clean.datetime)
else:
cache.set('next_clean', None)
if next_class:
cache.set('next_class', dict(datetime=next_class.datetime, id=next_class.id, name=next_class.course.name))
else:
cache.set('next_class', None)
if prev_class:
cache.set('prev_class', dict(datetime=prev_class.datetime, id=prev_class.id, name=prev_class.course.name))
else:
cache.set('prev_class', None)
def calc_member_counts():
members = models.Member.objects
not_paused = members.filter(paused_date__isnull=True)
num_current = not_paused.filter(status='Current').count()
num_prepaid = not_paused.filter(status='Prepaid').count()
num_due = not_paused.filter(status='Due').count()
num_overdue = not_paused.filter(status='Overdue').count()
member_count = num_current + num_prepaid + num_due + num_overdue
paused_count = members.count() - member_count
green_count = num_current + num_prepaid
six_months_ago = utils.today_alberta_tz() - timedelta(days=183)
six_month_plus_count = not_paused.filter(application_date__lte=six_months_ago).count()
vetted_count = not_paused.filter(vetted_date__isnull=False).count()
related_membership_tx = Prefetch(
'user__transactions',
queryset=models.Transaction.objects.exclude(
number_of_membership_months=0,
).exclude(
number_of_membership_months__isnull=True,
),
)
subscriber_count = 0
for member in not_paused.prefetch_related(related_membership_tx):
if not member.user.transactions.count():
continue
if member.user.transactions.latest('date').paypal_txn_type == 'subscr_payment':
subscriber_count += 1
cache.set('member_count', member_count)
cache.set('paused_count', paused_count)
cache.set('green_count', green_count)
return dict(
member_count=member_count,
green_count=green_count,
six_month_plus_count=six_month_plus_count,
vetted_count=vetted_count,
subscriber_count=subscriber_count,
)
def calc_signup_counts():
month_beginning = utils.today_alberta_tz().replace(day=1)
members = models.Member.objects
new_members = members.filter(application_date__gte=month_beginning)
num_new_members = new_members.count()
return num_new_members
def calc_retain_counts():
signup_counts = models.StatsSignupCount.objects.all()
all_members = models.Member.objects
active_members = all_members.filter(paused_date__isnull=True)
vetted_members = all_members.filter(vetted_date__isnull=False)
for entry in signup_counts:
date = entry.month
active_new_members = active_members.filter(
application_date__month=date.month, application_date__year=date.year
)
vetted_new_members = vetted_members.filter(
application_date__month=date.month, application_date__year=date.year
)
entry.retain_count = active_new_members.count()
entry.vetted_count = vetted_new_members.count()
entry.save()
return active_members.count()
def check_minecraft_server():
if secrets.MINECRAFT:
url = 'https://api.minetools.eu/ping/' + secrets.MINECRAFT
try:
r = requests.get(url, timeout=5)
r.raise_for_status()
players = [x['name'] for x in r.json()['players']['sample']]
cache.set('minecraft_players', players)
return players
except BaseException as e:
logger.error('Problem checking Minecraft: {} - {}'.format(e.__class__.__name__, str(e)))
return []
def check_mumble_server():
if secrets.MUMBLE:
url = secrets.MUMBLE
try:
r = requests.get(url, timeout=5)
r.raise_for_status()
users = r.text.split()
cache.set('mumble_users', users)
return users
except BaseException as e:
logger.error('Problem checking Mumble: {} - {}'.format(e.__class__.__name__, str(e)))
return []
def calc_card_scans():
date = utils.today_alberta_tz()
dt = datetime.combine(date, datetime.min.time())
midnight = utils.TIMEZONE_CALGARY.localize(dt)
cards = models.Card.objects
count = cards.filter(last_seen__gte=midnight).count()
cache.set('card_scans', count)
models.StatsSpaceActivity.objects.update_or_create(
date=date,
defaults=dict(card_scans=count),
)
def get_progress(request_id):
return cache.get('request-progress-' + request_id, [])
def set_progress(request_id, data):
logger.info('Progress - ID: %s | Status: %s', request_id, data)
progress = get_progress(request_id)
progress.append(data)
cache.set('request-progress-' + request_id, progress)