ogn-python/app/tasks/sql_tasks.py

127 wiersze
4.8 KiB
Python

from datetime import datetime, timedelta
from app import db, celery
@celery.task(name="update_statistics")
def update_statistics(date_str=None):
""" Update relation_statistics, sender_statistics, receiver_statistics (all depend on coverage_statistics)."""
if date_str is None:
date_str = datetime.utcnow().strftime("%Y-%m-%d")
# Update relation statistics
db.session.execute(f"""
DELETE FROM relation_statistics
WHERE date = '{date_str}';
INSERT INTO relation_statistics AS rs (date, sender_id, receiver_id, is_trustworthy, max_distance, max_normalized_quality, messages_count, coverages_count)
SELECT
tmp.date,
tmp.sender_id,
tmp.receiver_id,
is_trustworthy,
MAX(tmp.max_distance) AS max_distance,
MAX(tmp.max_normalized_quality) AS max_normalized_quality,
SUM(tmp.messages_count) AS messages_count,
COUNT(DISTINCT tmp.location_mgrs_short) AS coverages_count
FROM coverage_statistics AS tmp
WHERE tmp.date = '{date_str}'
GROUP BY date, sender_id, receiver_id, is_trustworthy;
""")
# Update sender statistics
db.session.execute(f"""
DELETE FROM sender_statistics
WHERE date = '{date_str}';
INSERT INTO sender_statistics AS rs (date, sender_id, is_trustworthy, max_distance, max_normalized_quality, messages_count, coverages_count, receivers_count)
SELECT
tmp.date,
tmp.sender_id,
is_trustworthy,
MAX(tmp.max_distance) AS max_distance,
MAX(tmp.max_normalized_quality) AS max_normalized_quality,
SUM(tmp.messages_count) AS messages_count,
COUNT(DISTINCT tmp.location_mgrs_short) AS coverages_count,
COUNT(DISTINCT tmp.receiver_id) AS receivers_count
FROM coverage_statistics AS tmp
WHERE tmp.date = '{date_str}'
GROUP BY date, sender_id, is_trustworthy;
""")
# Update receiver statistics
db.session.execute(f"""
DELETE FROM receiver_statistics
WHERE date = '{date_str}';
INSERT INTO receiver_statistics AS rs (date, receiver_id, is_trustworthy, max_distance, max_normalized_quality, messages_count, coverages_count, senders_count)
SELECT
tmp.date,
tmp.receiver_id,
is_trustworthy,
MAX(tmp.max_distance) AS max_distance,
MAX(tmp.max_normalized_quality) AS max_normalized_quality,
SUM(tmp.messages_count) AS messages_count,
COUNT(DISTINCT tmp.location_mgrs_short) AS coverages_count,
COUNT(DISTINCT tmp.sender_id) AS senders_count
FROM coverage_statistics AS tmp
WHERE tmp.date = '{date_str}'
GROUP BY date, receiver_id, is_trustworthy;
""")
db.session.commit()
@celery.task(name="update_sender_direction_statistics")
def update_sender_direction_statistics():
""" Update sender_direction_statistics."""
db.session.execute("""
DELETE FROM sender_direction_statistics;
INSERT INTO sender_direction_statistics(sender_id, receiver_id, directions_count, messages_count, direction_data)
SELECT
sq2.sender_id,
sq2.receiver_id,
COUNT(sq2.*) AS directions_count,
SUM(sq2.messages_count) AS messages_count,
json_agg(json_build_object('direction', direction, 'messages_count', messages_count, 'max_range', max_range)) AS direction_data
FROM (
SELECT
sq.sender_id,
sq.receiver_id,
sq.direction,
COUNT(sq.*) AS messages_count,
MAX(sq.max_range) AS max_range
FROM (
SELECT
s.id AS sender_id,
r.id AS receiver_id,
10000 * 10^(sp.normalized_quality/20.0) AS max_range,
CASE
WHEN sp.bearing-sp.track < 0
THEN CAST((sp.bearing-sp.track+360)/10 AS INTEGER)*10
ELSE CAST((sp.bearing-sp.track)/10 AS INTEGER)*10
END AS direction
FROM sender_positions AS sp
INNER JOIN senders s ON sp.name = s.name
INNER JOIN receivers r ON sp.receiver_name = r.name
WHERE
sp.track IS NOT NULL AND sp.bearing IS NOT NULL AND sp.normalized_quality IS NOT NULL
AND sp.agl >= 200
AND turn_rate BETWEEN -10.0 AND 10.0
AND climb_rate BETWEEN -3.0 AND 3.0
) AS sq
GROUP BY sq.sender_id, sq.receiver_id, sq.direction
ORDER BY sq.sender_id, sq.receiver_id, sq.direction
) AS sq2
GROUP BY sq2.sender_id, sq2.receiver_id;
""")