kopia lustrzana https://github.com/glidernet/ogn-python
Country dependant receiver rankings (#157)
* Added receiver_rankings, fixed receiver_status * Added receiver_rankings updates * Modified receiver_ranking.html * Removed obsolete code * Bugfix: order countries for select boxpull/78/head
rodzic
0dea6210c1
commit
b5893e9e61
|
@ -7,7 +7,7 @@ from sqlalchemy.orm.exc import NoResultFound
|
|||
|
||||
from app import db
|
||||
from app import cache
|
||||
from app.model import Airport, Country, Sender, SenderInfo, TakeoffLanding, Logbook, Receiver, SenderPosition, RelationStatistic, ReceiverStatistic, SenderStatistic, FrequencyScanFile
|
||||
from app.model import Airport, Country, Sender, SenderInfo, TakeoffLanding, Logbook, Receiver, SenderPosition, RelationStatistic, ReceiverRanking, ReceiverStatistic, SenderStatistic, FrequencyScanFile
|
||||
|
||||
from app.main import bp
|
||||
from app.main.matplotlib_service import create_range_figure
|
||||
|
@ -222,18 +222,36 @@ def sender_ranking():
|
|||
ranking=sender_statistics)
|
||||
|
||||
|
||||
@bp.route("/receiver_ranking.html")
|
||||
@cache.cached()
|
||||
@bp.route("/receiver_ranking.html", methods=["GET", "POST"])
|
||||
@cache.cached(query_string=True)
|
||||
def receiver_ranking():
|
||||
receiver_statistics = db.session.query(ReceiverStatistic) \
|
||||
.filter(db.and_(ReceiverStatistic.date == date.today(), ReceiverStatistic.is_trustworthy == db.true())) \
|
||||
.order_by(ReceiverStatistic.max_distance.desc()) \
|
||||
.all()
|
||||
sel_country = request.args.get("country")
|
||||
|
||||
countries = db.session.query(Country) \
|
||||
.filter(Country.gid == ReceiverRanking.country_id) \
|
||||
.filter(ReceiverRanking.date == date.today()) \
|
||||
.order_by(Country.iso2)
|
||||
|
||||
# Get receiver selection list
|
||||
if sel_country:
|
||||
ranking = db.session.query(ReceiverRanking) \
|
||||
.join(Country) \
|
||||
.filter(db.and_(ReceiverRanking.country_id == Country.gid, Country.iso2 == sel_country)) \
|
||||
.filter(db.and_(ReceiverRanking.date == date.today())) \
|
||||
.order_by(ReceiverRanking.global_rank.asc()) \
|
||||
.all()
|
||||
else:
|
||||
ranking = db.session.query(ReceiverRanking) \
|
||||
.filter(db.and_(ReceiverRanking.date == date.today())) \
|
||||
.order_by(ReceiverRanking.global_rank.asc()) \
|
||||
.all()
|
||||
|
||||
return render_template(
|
||||
"receiver_ranking.html",
|
||||
title="Receiver Ranking",
|
||||
ranking=receiver_statistics)
|
||||
sel_country=sel_country,
|
||||
countries=countries,
|
||||
ranking=ranking)
|
||||
|
||||
|
||||
@bp.route("/upload_file", methods=["POST"])
|
||||
|
|
|
@ -22,3 +22,4 @@ from .sender_statistic import SenderStatistic
|
|||
from .receiver_statistic import ReceiverStatistic
|
||||
from .sender_position_statistic import SenderPositionStatistic
|
||||
from .sender_direction_statistic import SenderDirectionStatistic
|
||||
from .receiver_ranking import ReceiverRanking
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
from app import db
|
||||
|
||||
|
||||
class ReceiverRanking(db.Model):
|
||||
__tablename__ = "receiver_rankings"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
||||
date = db.Column(db.Date)
|
||||
local_rank = db.Column(db.Integer)
|
||||
global_rank = db.Column(db.Integer)
|
||||
|
||||
max_distance = db.Column(db.Float(precision=2))
|
||||
max_normalized_quality = db.Column(db.Float(precision=2))
|
||||
messages_count = db.Column(db.Integer)
|
||||
coverages_count = db.Column(db.Integer)
|
||||
senders_count = db.Column(db.Integer)
|
||||
|
||||
# Relations
|
||||
receiver_id = db.Column(db.Integer, db.ForeignKey("receivers.id", ondelete="CASCADE"), index=True)
|
||||
receiver = db.relationship("Receiver", foreign_keys=[receiver_id], backref=db.backref("rankings", order_by=date.desc()))
|
||||
|
||||
country_id = db.Column(db.Integer, db.ForeignKey("countries.gid", ondelete="CASCADE"), index=True)
|
||||
country = db.relationship("Country", foreign_keys=[country_id], backref=db.backref("rankings", order_by=date.desc()))
|
||||
|
||||
__table_args__ = (db.Index('idx_receiver_rankings_uc', 'date', 'receiver_id', unique=True), )
|
|
@ -41,8 +41,3 @@ class ReceiverStatus(db.Model):
|
|||
good_senders_signal = None
|
||||
good_senders = None
|
||||
good_and_bad_senders = None
|
||||
|
||||
# Calculated values (from this software)
|
||||
location_mgrs = db.Column(db.String(15)) # full mgrs (15 chars)
|
||||
location_mgrs_short = db.Column(db.String(9)) # reduced mgrs (9 chars), e.g. used for melissas range tool
|
||||
agl = db.Column(db.Float(precision=2))
|
||||
|
|
|
@ -76,6 +76,30 @@ def update_statistics(date_str=None):
|
|||
GROUP BY date, receiver_id, is_trustworthy;
|
||||
""")
|
||||
|
||||
# Update receiver rankings
|
||||
db.session.execute(f"""
|
||||
DELETE FROM receiver_rankings
|
||||
WHERE date = '{date_str}';
|
||||
|
||||
INSERT INTO receiver_rankings AS rr (date, receiver_id, country_id, local_rank, global_rank, max_distance, max_normalized_quality, messages_count, coverages_count, senders_count)
|
||||
SELECT
|
||||
rs.date,
|
||||
rs.receiver_id,
|
||||
|
||||
r.country_id,
|
||||
RANK() OVER (PARTITION BY rs.date, r.country_id ORDER BY rs.max_distance DESC) AS local_rank,
|
||||
RANK() OVER (ORDER BY rs.max_distance DESC) AS global_rank,
|
||||
|
||||
rs.max_distance,
|
||||
rs.max_normalized_quality,
|
||||
rs.messages_count,
|
||||
rs.coverages_count,
|
||||
rs.senders_count
|
||||
FROM receiver_statistics AS rs
|
||||
LEFT JOIN receivers AS r ON rs.receiver_id = r.id
|
||||
WHERE rs.date = '{date_str}' AND rs.is_trustworthy IS TRUE;
|
||||
""")
|
||||
|
||||
db.session.commit()
|
||||
|
||||
|
||||
|
|
|
@ -8,25 +8,44 @@
|
|||
<div class="panel panel-success">
|
||||
<div class="panel-heading"><h3 class="panel-title">Receiver Ranking</h3></div>
|
||||
<div class="panel-body">
|
||||
|
||||
<form>
|
||||
<div class="well">
|
||||
<select name="country" onchange="this.form.submit();">
|
||||
<option value="">(all)</option>
|
||||
{% for country in countries %}
|
||||
<option value="{{ country.iso2 }}"{% if sel_country == country.iso2 %} SELECTED{% endif %}>{{ country.iso2 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table id="myTable" class="table table-striped table-bordered tablesorter tablesorter-bootstrap">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Country</th>
|
||||
<th colspan="2">Ranking</th>
|
||||
<th colspan="2">Receiver</th>
|
||||
<th colspan="2">Maximum</th>
|
||||
<th colspan="3">Counter</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-right">Local</th>
|
||||
<th class="text-right">Global</th>
|
||||
<th>Name</th>
|
||||
<th>Airport</th>
|
||||
<th class="text-right">Maximum distance [km]</th>
|
||||
<th class="text-right">Maximal normalized signal quality [dB]</th>
|
||||
<th class="text-right">Sender counter</th>
|
||||
<th class="text-right">Coverage counter</th>
|
||||
<th class="text-right">Message counter</th>
|
||||
<th class="text-right">Distance [km]</th>
|
||||
<th class="text-right">Normalized signal quality [dB]</th>
|
||||
<th class="text-right">Senders</th>
|
||||
<th class="text-right">Coverages</th>
|
||||
<th class="text-right">Messages</th>
|
||||
</tr>
|
||||
|
||||
|
||||
{% for entry in ranking %}
|
||||
<tr>
|
||||
<td>{{ loop.index }}</td>
|
||||
<td><img src="{{ url_for('static', filename='img/Transparent.gif') }}" class="flag flag-{{ entry.receiver.country.iso2|lower }}" alt="{{ entry.receiver.country.iso2 }}"/></td>
|
||||
<td>{{ entry.receiver|to_html_link|safe }}</a></td>
|
||||
<td>{{ entry.receiver.airport|to_html_link|safe }}</a></td>
|
||||
<td class="text-right">{{ entry.local_rank }}</td>
|
||||
<td class="text-right">{{ entry.global_rank }}</td>
|
||||
<td><img src="{{ url_for('static', filename='img/Transparent.gif') }}" class="flag flag-{{ entry.receiver.country.iso2|lower }}" alt="{{ entry.receiver.country.iso2 }}"/> {{ entry.receiver|to_html_link|safe }}</td>
|
||||
<td>{{ entry.receiver.airport|to_html_link|safe }}</td>
|
||||
<td class="text-right">{{ '%0.1f' | format(entry.max_distance/1000.0) }}</td>
|
||||
<td class="text-right">{{ '%0.1f' | format(entry.max_normalized_quality) }}</td>
|
||||
<td class="text-right">{{ entry.senders_count }}</td>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<link rel="stylesheet" href="{{ url_for('static', filename='css/flags/flags.css') }}"/>
|
||||
|
||||
<div class="container">
|
||||
<div class="panel panel-success" id="asdf">
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-heading"><h3 class="panel-title">Receivers</h3></div>
|
||||
<div class="panel-body">
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
"""Add ReceiverRanking
|
||||
|
||||
Revision ID: 7f5b8f65a977
|
||||
Revises: c53fdb39f5a5
|
||||
Create Date: 2020-12-02 22:33:58.821112
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '7f5b8f65a977'
|
||||
down_revision = 'c53fdb39f5a5'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('receiver_rankings',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('date', sa.Date(), nullable=True),
|
||||
sa.Column('local_rank', sa.Integer(), nullable=True),
|
||||
sa.Column('global_rank', sa.Integer(), nullable=True),
|
||||
sa.Column('max_distance', sa.Float(precision=2), nullable=True),
|
||||
sa.Column('max_normalized_quality', sa.Float(precision=2), nullable=True),
|
||||
sa.Column('messages_count', sa.Integer(), nullable=True),
|
||||
sa.Column('coverages_count', sa.Integer(), nullable=True),
|
||||
sa.Column('senders_count', sa.Integer(), nullable=True),
|
||||
sa.Column('receiver_id', sa.Integer(), nullable=True),
|
||||
sa.Column('country_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['country_id'], ['countries.gid'], ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['receiver_id'], ['receivers.id'], ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('idx_receiver_rankings_uc', 'receiver_rankings', ['date', 'receiver_id'], unique=True)
|
||||
op.create_index(op.f('ix_receiver_rankings_country_id'), 'receiver_rankings', ['country_id'], unique=False)
|
||||
op.create_index(op.f('ix_receiver_rankings_receiver_id'), 'receiver_rankings', ['receiver_id'], unique=False)
|
||||
|
||||
op.drop_column('receiver_statuses', 'agl')
|
||||
op.drop_column('receiver_statuses', 'location_mgrs')
|
||||
op.drop_column('receiver_statuses', 'location_mgrs_short')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('receiver_statuses', sa.Column('location_mgrs_short', sa.VARCHAR(length=9), autoincrement=False, nullable=True))
|
||||
op.add_column('receiver_statuses', sa.Column('location_mgrs', sa.VARCHAR(length=15), autoincrement=False, nullable=True))
|
||||
op.add_column('receiver_statuses', sa.Column('agl', sa.REAL(), autoincrement=False, nullable=True))
|
||||
|
||||
op.drop_index(op.f('ix_receiver_rankings_receiver_id'), table_name='receiver_rankings')
|
||||
op.drop_index(op.f('ix_receiver_rankings_country_id'), table_name='receiver_rankings')
|
||||
op.drop_index('idx_receiver_rankings_uc', table_name='receiver_rankings')
|
||||
op.drop_table('receiver_rankings')
|
||||
# ### end Alembic commands ###
|
Ładowanie…
Reference in New Issue