From 3d2e88e0bea6694401ce6ab540df753bda07c3c1 Mon Sep 17 00:00:00 2001 From: Antonio Golfari Date: Mon, 16 Sep 2024 00:43:58 +0200 Subject: [PATCH] added FTV brackets preview page --- airscore/core/frontendUtils.py | 46 +++++++++ airscore/public/views.py | 15 +++ airscore/static/js/pop_ftv_bracket.js | 99 +++++++++++++++++++ airscore/templates/public/ftv_bracket.html | 61 ++++++++++++ .../templates/users/comp_score_admin.html | 2 + 5 files changed, 223 insertions(+) create mode 100644 airscore/static/js/pop_ftv_bracket.js create mode 100644 airscore/templates/public/ftv_bracket.html diff --git a/airscore/core/frontendUtils.py b/airscore/core/frontendUtils.py index 5005d437..099a7748 100644 --- a/airscore/core/frontendUtils.py +++ b/airscore/core/frontendUtils.py @@ -2694,3 +2694,49 @@ def get_task_from_file(task_id: int, file) -> bool: task = Task.update_from_dict(task_id, task_info) return True + +def create_ftv_bracket(comp_id: int) -> list: + from comp import Comp + from task import Task + from pilot.flightresult import FlightResult + + comp = Comp.read(comp_id) + comp.populate_from_tasks_result_files() + bracket = {} + + t = Task() + t.comp_id = comp_id + t.task_num = comp.tasks[-1].task_num + 1 + t.formula = comp.tasks[-1].formula + t.day_quality = 1 + t.status = 'dummy task for FTV brackets calculation' + t.get_pilots() + + for p in t.pilots: + p.score = 1000 + p.result_type = 'goal' + comp.tasks.append(t) + + comp.create_results_score_details() + + # create data + for p in comp.results: + bracket[p['ID']] = p['score'] + + # need to add a dummy pilot to calculate min score + dummy = FlightResult(name='dummy') + dummy.result_type = 'goal' + comp.tasks[-1].pilots.append(dummy) + + for p in comp.tasks[-1].pilots: + p.score = 0 if p.ID is not None else 1000 + + comp.create_results_score_details() + data = comp.json_elements + + # add min and max score to data + for p in data['results']: + p['min_score'] = p['score'] + p['max_score'] = bracket[p['ID']] + + return data diff --git a/airscore/public/views.py b/airscore/public/views.py index fa11d0f8..230d4adc 100644 --- a/airscore/public/views.py +++ b/airscore/public/views.py @@ -554,6 +554,21 @@ def comp_result(compid: int): return render_template('public/comp_overall.html', compid=compid, results=result_file) +@blueprint.route('/ftv_bracket/') +def ftv_bracket(compid: int): + + data = frontendUtils.create_ftv_bracket(compid) + result_file = frontendUtils.get_pretty_data(data, result_type='comp') + if result_file == 'error': + return render_template('404.html') + + for t in result_file['tasks']: + link, code = f"/task_result/{t['id']}", t['task_code'] + t['link'] = f"{code}" + + return render_template('public/ftv_bracket.html', compid=compid, results=result_file) + + @blueprint.route('/country_overall/') def country_overall(compid: int): return render_template('public/country_overall.html', compid=compid) diff --git a/airscore/static/js/pop_ftv_bracket.js b/airscore/static/js/pop_ftv_bracket.js new file mode 100644 index 00000000..6cef5a67 --- /dev/null +++ b/airscore/static/js/pop_ftv_bracket.js @@ -0,0 +1,99 @@ +function populate_ftv_brackets(json){ + $('#comp_name').text('Loading Results ...'); + var taskNum = json.stats.valid_tasks + console.log('taskNum='+taskNum); + var columns = []; + // rankings + json.rankings.forEach( function(item, index) { + columns.push({data: 'rankings.'+item.rank_id.toString(), title: '#', name: item.rank_id.toString(), className: "text-right", defaultContent: '', visible: (index === 0) ? true : false}); + }); + columns.push({data: 'ID', title:'ID', className: "text-right", defaultContent: ''}); + columns.push({data: 'fai_id', title:'FAI', className: "text-right", defaultContent: '', visible: false}); + columns.push({data: 'civl_id', title:'CIVL', className: "text-right", defaultContent: '', visible: false}); + columns.push({data: 'name', title:'Name'}); + columns.push({data: 'nat', title:'NAT', name:'NAT', defaultContent: ''}); + columns.push({data: 'sex', title:'Sex', defaultContent: '', visible: false}); + columns.push({data: 'glider', title:'Equip', defaultContent: '', visible: false}); + columns.push({data: 'glider_cert', title:'Class', defaultContent: '', visible: false}); + columns.push({data: 'sponsor', title:'Sponsor', defaultContent: '', visible: false}); + columns.push({data: 'max_score', title:'Max Score', className: "text-right"}); + columns.push({data: 'min_score', title:'Min Score', className: "text-right"}); + $('#results_table').DataTable( { + data: json.results, + paging: false, + searching: true, + saveState: true, + info: false, + dom: 'lrtip', + columns: columns, + rowId: function(data) { + return 'id_' + data.par_id; + }, + initComplete: function(settings) { + var table = $('#results_table'); + var rows = $("tr", table).length-1; + // Get number of all columns + var numCols = table.DataTable().columns().nodes().length; + console.log('numCols='+numCols); + + // comp info + $('#comp_name').text(json.info.comp_name); + $('#comp_date').text(json.info.date_from + ' - ' + json.info.date_to); + if (json.info.comp_class != "PG") { + update_classes(json.info.comp_class); + } + // description text + let text = document.createTextNode('Score bracket applying FTV parameters to the overall results after a new fully valid task'); + $('#comp_header').append(text); + + // some GAP parameters + $('#formula tbody').append( + "Director" + json.info.MD_name + '' + + "Location" + json.info.comp_site + '' + + "Formula" + json.formula.formula_name + '' + + "Overall Scoring" + json.formula.overall_validity + ' (' + json.formula.validity_param + ')'); + if (json.formula.overall_validity.toLowerCase() == 'ftv') { + $('#formula tbody').append( + "Assumed Total Validity" + json.stats.total_validity + ' (FTV validity ' + json.stats.avail_validity + ')'); + } + // remove empty cols and NAT if all pilots are from a single country + var natId = table.DataTable().column('NAT:name').index(); + var natRef = table.DataTable().column(natId).data()[0]; + for ( var col=1; col { + if (col == natId) { + if (val != natRef) { + empty = false; + } + } + else { + if (val != "") { + empty = false; + } + } + if (!empty) { + return false; + } + } ); + + if (empty) { + table.DataTable().column( col ).visible( false ); + } + } + + // class picker + $("#dhv option").remove(); // Remove all ") + .text(item.rank_name) + .val(item.rank_id) + ); + }); + } + }); +} \ No newline at end of file diff --git a/airscore/templates/public/ftv_bracket.html b/airscore/templates/public/ftv_bracket.html new file mode 100644 index 00000000..5899fc97 --- /dev/null +++ b/airscore/templates/public/ftv_bracket.html @@ -0,0 +1,61 @@ +{% extends "base.html"%} + +{% block page_title %} +Competition Results - Overall +{% endblock %} + +{% block head %} + + + + + + +{% endblock %} + +{% block back %} +Back to Competition +{% endblock %} + +{% block content %} +
+
+
+

+

+

+ +
+
+ + + + + + + + +
Information
+
+
+ {% from "macros.html" import datatable with context %} + {{ datatable('results_table') }} +

+ +

+
+{% endblock %} + +{% block js %} + + + + +{% endblock %} \ No newline at end of file diff --git a/airscore/templates/users/comp_score_admin.html b/airscore/templates/users/comp_score_admin.html index 4645fbc2..1eb72f40 100644 --- a/airscore/templates/users/comp_score_admin.html +++ b/airscore/templates/users/comp_score_admin.html @@ -89,6 +89,8 @@

Comp Result Info:

+

FTV Brackets Info:

+

If FTV is in use, at the url "/ftv_bracket/{{session.compid}}" is available the FTV bracket for each pilot after a new fully valid task.