Ejemplo n.º 1
0
def opt_wp_enter(opt, t1, enter):
    # search for point that opt line crosses enter cylinder
    bearing = calcBearing(opt.lat, opt.lon, t1.lat, t1.lon)
    dist = geod.Inverse(opt.lat, opt.lon, t1.lat, t1.lon)['s12']
    point = opt
    found = False
    d1 = dist / 2
    direction = ''
    while not found:

        p = geod.Direct(opt.lat, opt.lon, bearing, dist)
        point = Turnpoint(lat=p['lat2'], lon=p['lon2'], type='optimised', radius=0, shape='optimised', how='optimised')
        dist_from_centre = int(c_round(geod.Inverse(point.lat, point.lon, enter.lat, enter.lon)['s12']))
        if dist_from_centre > enter.radius:
            if direction != 'plus':
                d1 = d1 / 2  # if we change direction halve the increment
            dist = dist + d1
            direction = 'plus'
        elif dist_from_centre < enter.radius:
            if direction != 'minus':
                d1 = d1 / 2  # if we change direction halve the increment
            dist = dist - d1
            direction = 'minus'
        else:
            found = True
    return point
Ejemplo n.º 2
0
 def avail_validity(self):
     if len(self.tasks) > 0:
         if self.formula.overall_validity == 'ftv':
             return c_round(self.total_validity * self.formula.validity_param, 4)
         else:
             return self.total_validity
     return 0
Ejemplo n.º 3
0
def rawtime_float_to_hms(timef):
    """Converts time from floating point seconds to hours/minutes/seconds.

    Args:
        timef: A floating point time in seconds to be converted

    Returns:
        A namedtuple with hours, minutes and seconds elements
    """
    time = int(c_round(timef))
    hms = namedtuple('hms', ['hours', 'minutes', 'seconds'])

    return hms(math.floor(time / 3600), math.floor((time % 3600) / 60), math.floor(time % 60))
Ejemplo n.º 4
0
def tp_time_civl(fix, next, tp):
    """return correct time of achieving a turnpoint based on CIVL rules"""

    '''
    The time of a crossing depends on whether it actually cuts across the actual cylinder,
    or whether both points lie within the tolerance band, but on the same side of the actual cylinder.

    (distance(center , trackpoint[j] ) < radius ∧ distance(center , trackpoint[j+1] ) < radius )
    ∨
    (distance(center , trackpoint[j] ) > radius ∧ distance(center , trackpoint[j+1] ) > radius )
    ∧
    turnpoint = ESS: crossing.time = trackpoint[j+1].time

    (distance(center , trackpoint[j] ) < radius ∧ distance(center , trackpoint[j+1] ) < radius )
    ∨
    (distance(center , trackpoint[j] ) > radius ∧ distance(center , trackpoint[j+1] ) > radius )
    ∧
    turnpoint ≠ ESS: crossing.time = trackpoint[j].time

    (distance(center , trackpoint[j] ) < radius ∧ distance(center , trackpoint[j+1] ) > radius )
    ∨
    (distance(center , trackpoint[j] ) > radius ∧ distance(center , trackpoint[j+1] ) < radius )
    crossing.time = interpolateTime(trackpoint[j],trackpoint[j+1])
    '''

    if ((tp.in_radius(fix, 0, 0) and tp.in_radius(next, 0, 0))
            or
            (not (tp.in_radius(fix, 0, 0)) and not (tp.in_radius(next, 0, 0)))):
        return fix.rawtime if tp.type != 'endspeed' else next.rawtime
    else:
        '''interpolate time:
        Will use distance from radius of the two points, and the proportion of times'''
        d1 = abs(distance(tp, fix) - tp.radius)
        d2 = abs(distance(tp, next) - tp.radius)
        speed = (d1 + d2) / (next.rawtime - fix.rawtime)
        t = c_round((fix.rawtime + d1 / speed), 2)
        return t
Ejemplo n.º 5
0
    def get_final_scores(self, d=0):
        """calculate final scores depending on overall validity:
            - all:      sum of all tasks results
            - round:    task discard every [param] tasks
            - ftv:      calculate task scores and total score based on FTV [param]

            input:
                results:    participant list
                tasks:      tasks list
                formula:    comp formula dict
                d:          decimals on single tasks score, default 0
        """
        from calcUtils import c_round

        val = self.formula.overall_validity
        param = self.formula.validity_param
        avail_validity = self.avail_validity

        for pil in self.results:
            pil['score'] = 0
            ''' if we score all tasks, or tasks are not enough to ha discards,
                or event has just one valid task regardless method,
                we can simply sum all score values
            '''
            if not ((val == 'all') or
                    (val == 'round' and self.dropped_tasks == 0) or
                    (len(self.tasks) < 2)):
                '''create a ordered list of results, perf desc'''
                # sorted_results = sorted(pil['results'], key=lambda x: (x[1]['perf'], x[1]['pre']), reverse=True)
                sorted_results = sorted(
                    [x for x in pil.items() if isinstance(x[1], dict)],
                    key=lambda x: (x[1]['perf'], x[1]['pre']),
                    reverse=True)

                if val == 'round' and len(self.tasks) >= param:
                    '''we need to order by score desc and sum only the ones we need'''
                    for i in range(self.dropped_tasks):
                        idx = sorted_results.pop()[
                            0]  # getting id of worst result task
                        pil[idx]['score'] = 0

                elif val == 'ftv' and len(self.tasks) > 1:
                    '''ftv calculation'''
                    pval = avail_validity
                    for idx, s in sorted_results:
                        if not (pval > 0):
                            pil[idx]['score'] = 0
                        else:
                            '''get ftv_validity of corresponding task'''
                            tval = next(t.ftv_validity for t in self.tasks
                                        if t.task_code == idx)
                            if pval > tval:
                                '''we can use the whole score'''
                                pval -= tval
                            else:
                                '''we need to calculate proportion'''
                                pil[idx]['score'] = c_round(
                                    pil[idx]['score'] * (pval / tval), d)
                                pval = 0
            '''calculates final pilot score'''
            pil['score'] = sum(pil[x]['score'] for x in pil.keys()
                               if isinstance(pil[x], dict))
        ''' order list'''
        self.results = sorted(self.results,
                              key=lambda x: x['score'],
                              reverse=True)
Ejemplo n.º 6
0
 def create_results(comp_id, status=None, decimals=None, name_suffix=None):
     """creates the json result file and the database entry
         :param
     name_suffix: optional name suffix to be used in filename.
     This is so we can overwrite comp results that are only used in front end to create competition
      page not display results """
     from calcUtils import c_round
     comp = Comp.read(comp_id)
     '''PARAMETER: decimal positions'''
     if decimals is None or not isinstance(decimals, int):
         decimals = comp.formula.comp_result_decimal
     '''retrieve active task result files and reads info'''
     files = get_tasks_result_files(comp_id)
     '''initialize obj attributes'''
     comp.participants = get_participants(comp_id)
     ''' get rankings '''
     comp.get_rankings()
     for idx, t in enumerate(files):
         task = Task.create_from_json(task_id=t.task_id, filename=t.file)
         comp.tasks.append(task)
         ''' task validity (if not using ftv, ftv_validity = day_quality)'''
         r = task.ftv_validity * 1000
         '''get pilots result'''
         for p in comp.participants:
             res = next((d for d in comp.results
                         if d.get('par_id', None) == p.par_id), False)
             if res is False:
                 ''' create pilot result Dict (once)'''
                 # comp.results.append({'par_id': p.par_id, 'results': []})
                 comp.results.append({'par_id': p.par_id})
                 res = comp.results[-1]
             s = next((c_round(pil.score or 0, decimals)
                       for pil in task.pilots if pil.par_id == p.par_id), 0)
             if r > 0:  # sanity
                 perf = c_round(s / r, decimals + 3)
                 # res['results'].append({task.task_code: {'pre': s, 'perf': perf, 'score': s}})
                 res.update(
                     {task.task_code: {
                         'pre': s,
                         'perf': perf,
                         'score': s
                     }})
             else:
                 # res['results'].append({task.task_code: {'pre': s, 'perf': 0, 'score': 0}})
                 res.update(
                     {task.task_code: {
                         'pre': s,
                         'perf': 0,
                         'score': 0
                     }})
     '''calculate final score'''
     comp.get_final_scores(decimals)
     ''' create result elements'''
     results = []
     for res in comp.results:
         '''create results dict'''
         p = next(x for x in comp.participants if x.par_id == res['par_id'])
         r = {
             x: getattr(p, x)
             for x in CompResult.result_list if x in dir(p)
         }
         r['score'] = res['score']
         r['results'] = {
             x: res[x]
             for x in res.keys() if isinstance(res[x], dict)
         }
         results.append(r)
     '''create json file'''
     result = {
         'info': {x: getattr(comp, x)
                  for x in CompResult.info_list},
         'rankings':
         comp.rankings,
         'tasks': [{x: getattr(t, x)
                    for x in CompResult.task_list} for t in comp.tasks],
         'results':
         results,
         'formula':
         {x: getattr(comp.formula, x)
          for x in CompResult.formula_list},
         'stats': {x: getattr(comp, x)
                   for x in CompResult.stats_list}
     }
     ref_id, filename, timestamp = create_json_file(comp_id=comp.id,
                                                    task_id=None,
                                                    code=comp.comp_code,
                                                    elements=result,
                                                    status=status,
                                                    name_suffix=name_suffix)
     return comp, ref_id, filename, timestamp
Ejemplo n.º 7
0
 def total_validity(self):
     if len(self.tasks) > 0:
         return c_round(sum([t.ftv_validity for t in self.tasks]), 4)
     else:
         return 0
Ejemplo n.º 8
0
    def to_file(self, participants_fsdb: bool = False):
        """ returns:
            - filename: STR
            - fsdb:     FSDB xml data, to be used in frontend."""

        formula = self.comp.formula
        pilots = self.comp.participants
        '''create dicts of attributes for each section'''
        comp_attr = {
            'id':
            '',  # still to do
            'name':
            self.comp.comp_name,
            'location':
            self.comp.comp_site,
            'from':
            self.comp.date_from,
            'to':
            self.comp.date_to,
            'utc_offset':
            self.comp.time_offset / 3600,
            'discipline':
            self.comp.comp_class.lower(),
            'ftv_factor':
            c_round(1 - formula.validity_param, 4),
            'fai_sanctioning': (1 if self.comp.sanction == 'FAI 1' else
                                2 if self.comp.sanction == 'FAI 2' else 0)
        }

        formula_attr = {
            'id':
            formula.formula_name,
            'min_dist':
            km(formula.min_dist, 1),
            'nom_dist':
            km(formula.nominal_dist, 1),
            'nom_time':
            formula.nominal_time / 3600,
            'nom_launch':
            formula.nominal_launch,
            'nom_goal':
            formula.nominal_goal,
            'day_quality_override':
            0,  # still to implement
            'bonus_gr':
            formula.glide_bonus,
            'jump_the_gun_factor': (0 if formula.max_JTG == 0 else c_round(
                1 / formula.JTG_penalty_per_sec, 1)),
            'jump_the_gun_max':
            formula.max_JTG,
            'normalize_1000_before_day_quality':
            0,  # still to implement
            'time_points_if_not_in_goal':
            c_round(1 - formula.no_goal_penalty, 1),
            'use_1000_points_for_max_day_quality':
            0,  # still to implement
            'use_arrival_position_points':
            1 if formula.formula_arrival == 'position' else 0,
            'use_arrival_time_points':
            1 if formula.formula_arrival == 'time' else 0,
            'use_departure_points':
            1 if formula.formula_departure == 'departure' else 0,
            'use_difficulty_for_distance_points':
            1 if formula.formula_distance == 'difficulty' else 0,
            'use_distance_points':
            1 if formula.formula_distance != 'off' else 0,
            'use_distance_squared_for_LC':
            1 if formula.comp_class == 'PG' else 0,  # still to implement
            'use_leading_points':
            1 if formula.formula_departure == 'leadout' else 0,
            'use_semi_circle_control_zone_for_goal_line':
            1,  # still to implement
            'use_time_points':
            1 if formula.formula_time == 'on' else 0,
            'scoring_altitude':
            'GPS' if formula.scoring_altitude == 'GPS' else 'QNH',
            'final_glide_decelerator':
            'none' if formula.arr_alt_bonus == 0 else 'aatb',
            'no_final_glide_decelerator_reason':
            '',
            'min_time_span_for_valid_task':
            60 if self.comp_class == 'PG' else 0,  # still to implement
            'score_back_time':
            formula.score_back_time / 60,
            'use_proportional_leading_weight_if_nobody_in_goal':
            '',  # still to implement
            'leading_weight_factor':
            (0 if formula.formula_departure != 'leadout' else c_round(
                formula.lead_factor, 3)),
            'turnpoint_radius_tolerance':
            formula.tolerance,
            'use_arrival_altitude_points':
            0 if formula.arr_alt_bonus == 0 else ''  # still to implement
        }
        if formula.arr_alt_bonus > 0:
            formula_attr['aatb_factor'] = c_round(formula.arr_alt_bonus, 3)
        '''create the file structure'''
        root = ET.Element('Fs')
        root.set('version', '3.5')
        root.set('comment', 'generated by AirScore')
        '''FsCompetition'''
        comp = ET.SubElement(root, 'FsCompetition')
        for k, v in comp_attr.items():
            comp.set(k, str(v))

        formula = ET.SubElement(comp, 'FsScoreFormula')
        for k, v in formula_attr.items():
            formula.set(k, str(v))

        notes = ET.SubElement(comp, 'FsCompetitionNotes')
        notes.text = CDATA('Generated by AirScore')
        # notes.text = '<![CDATA[Generated by AirScore]]>'
        '''FsParticipants'''
        participants = ET.SubElement(comp, 'FsParticipants')
        for p in pilots:
            pil = ET.SubElement(participants, 'FsParticipant')
            pilot_attr = {
                'id': p.ID or p.par_id,
                'name': p.name,
                'birthday': p.pilot_birthdate_str,
                'glider': p.glider,
                'glider_main_colors': '',
                'fai_licence': 1 if p.fai_id else 0,
                'female': p.female,
                'nat_code_3166_a3': p.nat,
                'sponsor': p.sponsor,
                'CIVLID': p.civl_id,
            }
            custom_attr = {
                'fai_n': p.fai_id,
                'class': p.glider_cert,
                'team': p.team,
                'LIVE': p.live_id
            }

            for k, v in pilot_attr.items():
                pil.set(k, str(v))
            cus = ET.SubElement(pil, 'FsCustomAttributes')
            for k, v in custom_attr.items():
                sub = ET.SubElement(cus, 'FsCustomAttribute')
                sub.set('name', k)
                sub.set('value', str(v))

        if not participants_fsdb:
            '''FsTasks'''
            tasks = ET.SubElement(comp, 'FsTasks')
            for idx, t in enumerate(self.tasks):
                task = ET.SubElement(tasks, 'FsTask')
                task.set('id', str(idx + 1))
                task.set('name', t.task_name)
                task.set('tracklog_folder', '')

                task_f = ET.SubElement(task, 'FsScoreFormula')
                task_d = ET.SubElement(task, 'FsTaskDefinition')
                task_s = ET.SubElement(task, 'FsTaskState')
                task_p = ET.SubElement(task, 'FsParticipants')
                task_sp = ET.SubElement(task, 'FsTaskScoreParams')

                # tf = dict(t.formula.to_dict(), **t.stats)
                '''FsTaskState'''
                task_s.set(
                    'task_state',
                    ('REGULAR' if not t.stopped_time else 'STOPPED'))  # ?
                task_s.set('score_back_time',
                           str(t.formula.score_back_time / 60))
                task_s.set('cancel_reason', t.comment)
                '''FsScoreFormula'''
                # we permit just few changes in single tasks from comp formula, so we just update those
                tf_attr = formula_attr
                tf_attr.update({
                    'jump_the_gun_factor':
                    (0 if not t.formula.JTG_penalty_per_sec else round(
                        1 / t.formula.JTG_penalty_per_sec, 1)),
                    'time_points_if_not_in_goal':
                    1 - t.formula.no_goal_penalty,
                    'use_arrival_position_points':
                    1 if t.formula.arrival == 'position' else 0,
                    'use_arrival_time_points':
                    1 if t.formula.arrival == 'time' else 0,
                    'use_departure_points':
                    1 if t.formula.departure == 'departure' else 0,
                    'use_difficulty_for_distance_points':
                    1 if t.formula.distance == 'difficulty' else 0,
                    'use_distance_points':
                    0 if t.formula.distance == 'off' else 1,
                    'use_leading_points':
                    0 if t.formula.departure == 'off' else 1,
                    'use_time_points':
                    0 if t.formula.time == 'off' else 1,
                    'scoring_altitude':
                    'GPS' if t.formula.scoring_altitude == 'GPS' else 'QNH',
                    'final_glide_decelerator':
                    'none' if t.formula.arr_alt_bonus == 0 else 'aatb',
                    'use_arrival_altitude_points':
                    0 if t.formula.arr_alt_bonus == 0 else 1,
                    'turnpoint_radius_tolerance':
                    t.formula.tolerance,
                })

                for k, v in tf_attr.items():
                    task_f.set(k, str(v))
                '''FsTaskDefinition'''
                tps = t.turnpoints
                td_attr = {
                    'ss':
                    [i + 1 for i, tp in enumerate(tps)
                     if tp.type == 'speed'].pop(0),
                    'es': [
                        i + 1 for i, tp in enumerate(tps)
                        if tp.type == 'endspeed'
                    ].pop(0),
                    'goal':
                    next(tp.shape for tp in tps if tp.type == 'goal').upper(),
                    'groundstart':
                    0,  # still to implement
                    'qnh_setting':
                    1013.25  # still to implement
                }

                for k, v in td_attr.items():
                    task_d.set(k, str(v))

                t_open = get_isotime(t.date, t.window_open_time, t.time_offset)
                t_close = get_isotime(t.date, t.task_deadline, t.time_offset)
                ss_open = get_isotime(t.date, t.start_time, t.time_offset)
                if t.start_close_time:
                    ss_close = get_isotime(t.date, t.start_close_time,
                                           t.time_offset)
                else:
                    ss_close = t_close
                if t.window_close_time:
                    w_close = get_isotime(t.date, t.window_close_time,
                                          t.time_offset)
                else:
                    w_close = ss_close

                for i, tp in enumerate(tps):
                    task_tp = ET.SubElement(task_d, 'FsTurnpoint')
                    tp_attr = {
                        'id':
                        tp.name,
                        'lat':
                        round(tp.lat, 5),
                        'lon':
                        round(tp.lon, 5),
                        'altitude':
                        tp.altitude,
                        'radius':
                        tp.radius,
                        'open':
                        t_open if i < (td_attr['ss'] - 1) else ss_open,
                        'close':
                        w_close if i == 0 else
                        ss_close if i == (td_attr['ss'] - 1) else t_close
                    }
                    for k, v in tp_attr.items():
                        task_tp.set(k, str(v))
                    '''we add also FsTaskDistToTp during tp iteration'''
                    sp_dist = ET.SubElement(task_sp, 'FsTaskDistToTp')
                    sp_dist.set('tp_no', str(i + 1))
                    sp_dist.set('distance', str(t.partial_distance[i]))
                '''add start gates'''
                gates = 1
                if t.SS_interval > 0:
                    gates += t.start_iteration
                for i in range(gates):
                    task_sg = ET.SubElement(task_d, 'FsStartGate')
                    intv = 0 if not t.SS_interval else t.SS_interval * i
                    i_time = get_isotime(t.date, (t.start_time + intv),
                                         t.time_offset)
                    task_sg.set('open', str(i_time))
                '''FsTaskScoreParams'''
                launch_ess = [
                    t.partial_distance[i] for i, tp in enumerate(t.turnpoints)
                    if tp.type == 'endspeed'
                ].pop()
                sp_attr = {
                    'ss_distance':
                    km(t.SS_distance),
                    'task_distance':
                    km(t.opt_dist),
                    'launch_to_ess_distance':
                    km(launch_ess),
                    'no_of_pilots_present':
                    t.pilots_present,
                    'no_of_pilots_flying':
                    t.pilots_launched,
                    'no_of_pilots_lo':
                    t.pilots_launched - t.pilots_goal,
                    'no_of_pilots_reaching_nom_dist':
                    len([
                        x for x in t.valid_results
                        if x.distance_flown > t.formula.nominal_dist
                    ]),
                    'no_of_pilots_reaching_es':
                    t.pilots_ess,
                    'no_of_pilots_reaching_goal':
                    t.pilots_goal,
                    'sum_flown_distance':
                    km(t.tot_distance_flown),
                    'best_dist':
                    km(t.max_distance or 0),
                    'best_time':
                    round((t.fastest or 0) / 3600, 14),
                    'worst_time':
                    round(
                        max((x.ESS_time or 0) - (x.SSS_time or 0)
                            for x in t.valid_results) / 3600, 14),
                    'no_of_pilots_in_competition':
                    len(self.comp.participants),
                    'no_of_pilots_landed_before_stop':
                    0 if not t.stopped_time else t.pilots_landed,
                    'sum_dist_over_min':
                    km(t.tot_dist_over_min),
                    'sum_real_dist_over_min':
                    km(t.tot_dist_over_min),  # not yet implemented
                    'best_real_dist':
                    km(t.max_distance),  # not yet implemented
                    'last_start_time':
                    get_isotime(
                        t.date,
                        max([
                            x.SSS_time for x in t.valid_results
                            if x.SSS_time is not None
                        ]), t.time_offset),
                    'first_start_time':
                    ('' if not t.min_dept_time else get_isotime(
                        t.date, t.min_dept_time, t.time_offset)),
                    'first_finish_time':
                    ('' if not t.min_ess_time else get_isotime(
                        t.date, t.min_ess_time, t.time_offset)),
                    'max_time_to_get_time_points':
                    round(0 / 3600, 14),  # not yet implemented
                    'no_of_pilots_with_time_points':
                    len([x for x in t.valid_results if x.time_score > 0]),
                    'goal_ratio': (0 if t.pilots_launched == 0 else round(
                        t.pilots_goal / t.pilots_launched, 15)),
                    'arrival_weight':
                    0 if t.arrival == 0 else c_round(t.arr_weight, 3),
                    'departure_weight':
                    0 if t.departure != 'on' else c_round(t.dep_weight, 3),
                    'leading_weight':
                    0 if t.departure != 'leadout' else c_round(
                        t.dep_weight, 3),
                    'time_weight':
                    0 if t.arrival == 'off' else c_round(t.time_weight, 3),
                    'distance_weight':
                    c_round(t.dist_weight, 3),  # not yet implemented
                    'smallest_leading_coefficient':
                    round(t.min_lead_coeff, 14),
                    'available_points_distance':
                    round(t.avail_dist_points, 14),
                    'available_points_time':
                    round(t.avail_time_points, 14),
                    'available_points_departure':
                    (0 if not t.formula.departure == 'departure' else round(
                        t.avail_dep_points, 14)),
                    'available_points_leading':
                    (0 if not t.formula.departure == 'leadout' else round(
                        t.avail_dep_points, 14)),
                    'available_points_arrival':
                    round(t.avail_arr_points, 14),
                    'time_validity':
                    c_round(t.time_validity, 3),
                    'launch_validity':
                    c_round(t.launch_validity, 3),
                    'distance_validity':
                    c_round(t.dist_validity, 3),
                    'stop_validity':
                    c_round(t.stop_validity, 3),
                    'day_quality':
                    c_round(t.day_quality, 3),
                    'ftv_day_validity':
                    t.ftv_validity,
                    'time_points_stop_correction':
                    0  # not yet implemented
                }
                for k, v in sp_attr.items():
                    task_sp.set(k, str(v))
                '''FsParticipants'''
                for i, pil in enumerate(t.pilots):
                    '''create pilot result for the task'''
                    pil_p = ET.SubElement(task_p, 'FsParticipant')
                    pil_p.set('id', str(pil.ID or pil.par_id))
                    if not (pil.result_type in ('abs', 'dnf', 'nyp')):
                        '''only if pilot flew'''
                        pil_fd = ET.SubElement(pil_p, 'FsFlightData')
                        pil_r = ET.SubElement(pil_p, 'FsResult')
                        if not (pil.result_type in ['mindist', 'min_dist']):
                            fd_attr = {
                                'distance':
                                km(pil.distance_flown),
                                'bonus_distance':
                                km(pil.distance),
                                # ?? seems 0 for PG and more than dist for HG
                                'started_ss':
                                '' if not pil.real_start_time else get_isotime(
                                    t.date, pil.real_start_time,
                                    t.time_offset),
                                'finished_ss':
                                '' if not pil.ESS_time else get_isotime(
                                    t.date, pil.ESS_time, t.time_offset),
                                'altitude_at_ess':
                                pil.ESS_altitude,
                                'finished_task':
                                '' if not pil.goal_time else get_isotime(
                                    t.date, pil.goal_time, t.time_offset),
                                'tracklog_filename':
                                pil.track_file,
                                'lc':
                                pil.lead_coeff,
                                'iv':
                                pil.fixed_LC or '',
                                'ts':
                                get_isotime(t.date, pil.first_time,
                                            t.time_offset),
                                'alt':
                                pil.last_altitude,  # ??
                                'bonus_alt':
                                '',  # ?? not implemented
                                'max_alt':
                                pil.max_altitude,
                                'last_tracklog_point_distance':
                                '',  # not implemented yet
                                'bonus_last_tracklog_point_distance':
                                '',  # ?? not implemented
                                'last_tracklog_point_time':
                                get_isotime(t.date, pil.landing_time,
                                            t.time_offset),
                                'last_tracklog_point_alt':
                                pil.landing_altitude,
                                'landed_before_deadline':
                                '1' if pil.landing_time <
                                (t.task_deadline if not t.stopped_time else
                                 t.stopped_time) else '0',
                                'reachedGoal':
                                1 if pil.goal_time else 0
                                # only deadline?
                            }
                            for k, v in fd_attr.items():
                                pil_fd.set(k, str(v))

                        r_attr = {
                            'rank':
                            i +
                            1,  # not implemented, they should be ordered tho
                            # Rank IS NOT SAFE (I guess)
                            'points':
                            c_round(pil.score),
                            'distance':
                            km(pil.total_distance if pil.
                               total_distance else pil.distance_flown),
                            'ss_time':
                            '' if not pil.ss_time else sec_to_time(
                                pil.ss_time).strftime('%H:%M:%S'),
                            'finished_ss_rank':
                            '' if not pil.ESS_time and pil.ESS_rank else
                            pil.ESS_rank,
                            'distance_points':
                            0 if not pil.distance_score else c_round(
                                pil.distance_score, 1),
                            'time_points':
                            0 if not pil.time_score else c_round(
                                pil.time_score, 1),
                            'arrival_points':
                            0 if not pil.arrival_score else c_round(
                                pil.arrival_score, 1),
                            'departure_points':
                            0 if not t.formula.departure == 'departure' else
                            c_round(pil.departure_score, 1),
                            'leading_points':
                            0 if not t.formula.departure == 'leadout' else
                            c_round(pil.departure_score, 1),
                            'penalty':
                            0 if not [
                                n for n in pil.notifications
                                if n.percentage_penalty > 0
                            ] else max(n.percentage_penalty
                                       for n in pil.notifications),
                            'penalty_points':
                            0 if not [
                                n for n in pil.notifications
                                if n.flat_penalty > 0
                            ] else max(n.flat_penalty
                                       for n in pil.notifications),
                            'penalty_reason':
                            '; '.join([
                                n.comment for n in pil.notifications
                                if n.flat_penalty + n.percentage_penalty > 0
                                and not n.notification_type == 'jtg'
                            ]),
                            'penalty_points_auto':
                            sum(n.flat_penalty for n in pil.notifications
                                if n.notification_type == 'jtg'),
                            'penalty_reason_auto':
                            '' if not [
                                n for n in pil.notifications
                                if n.notification_type == 'jtg'
                            ] else next(
                                n for n in pil.notifications
                                if n.notification_type == 'jtg').flat_penalty,
                            'penalty_min_dist_points':
                            0,  # ??
                            'got_time_but_not_goal_penalty':
                            (pil.ESS_time or 0) > 0 and not pil.goal_time,
                            'started_ss':
                            '' if not pil.real_start_time else get_isotime(
                                t.date, pil.SSS_time, t.time_offset),
                            'finished_ss':
                            '' if not pil.ESS_time else get_isotime(
                                t.date, pil.ESS_time, t.time_offset),
                            'ss_time_dec_hours':
                            0 if not pil.ESS_time else round(
                                pil.ss_time / 3600, 14),
                            'ts':
                            get_isotime(t.date, pil.first_time,
                                        t.time_offset),  # flight origin time
                            'real_distance':
                            km(pil.distance_flown),
                            'last_distance':
                            '',  # ?? last fix distance?
                            'last_altitude_above_goal':
                            pil.last_altitude,
                            'altitude_bonus_seconds':
                            0,  # not implemented
                            'altitude_bonus_time':
                            sec_to_time(0).strftime(
                                '%H:%M:%S'),  # not implemented
                            'altitude_at_ess':
                            pil.ESS_altitude,
                            'scored_ss_time':
                            ('' if not pil.ss_time else sec_to_time(
                                pil.ss_time).strftime('%H:%M:%S')),
                            'landed_before_stop':
                            t.stopped_time
                            and pil.landing_time < t.stopped_time
                        }

                        for k, v in r_attr.items():
                            pil_r.set(k, str(v))
        '''creates the file to store'''
        fsdb = ET.tostring(root,
                           pretty_print=True,
                           xml_declaration=True,
                           encoding='UTF-8')

        return self.filename, fsdb
Ejemplo n.º 9
0
def _get_livetracking(taskid):
    from livetracking import get_live_json
    from calcUtils import sec_to_string, time_to_seconds, c_round
    from datetime import datetime
    result_file = get_live_json(int(taskid))

    formatted = frontendUtils.get_pretty_data(result_file)
    timestamp = result_file['file_stats']['timestamp']
    offset = result_file['info']['time_offset']

    formatted['headers'] = result_file['headers']
    updated = datetime.fromtimestamp(timestamp + (offset or 0))
    formatted['file_stats'][
        'updated'] = f"Updated at {updated.strftime('%H:%M:%S')} Local Time"
    if result_file['data']:
        rawtime = time_to_seconds(datetime.fromtimestamp(timestamp).time())
        results = []
        goal = [p for p in result_file['data'] if p['goal_time']]
        results.extend(sorted(goal, key=lambda k: k['ss_time']))
        ess = [
            p for p in result_file['data']
            if p['ESS_time'] and not p['goal_time']
        ]
        results.extend(sorted(ess, key=lambda k: k['ss_time']))
        others = [p for p in result_file['data'] if not p['ESS_time']]
        results.extend(
            sorted(others, key=lambda k: k['distance'], reverse=True))
        data = []
        for idx, el in enumerate(results, 1):
            status = ''
            res = ''
            '''status, time or distance'''
            if el['first_time'] is None:
                '''not launched'''
                status = '[not launched yet]'
            elif el['ESS_time']:
                val = sec_to_string(el['ss_time'])
                res = f"<del>{val}</del>" if not el[
                    'goal_time'] else f"<b>{val}</b>"
            else:
                res = str(c_round(el['distance'] / 1000,
                                  2)) + ' Km' if el['distance'] > 500 else ''
                '''display status or altitude and height if reading is correct'''
                if el['landing_time']:
                    status = '[landed]'
                elif -100 < el['last_altitude'] < 10000:
                    status = f"{el['last_altitude']} m. [{el['height']} agl]"
                else:
                    status = 'unreliable altitude reading'
            '''notifications'''
            if el['notifications']:
                comment = '; '.join(
                    [n['comment'].split('.')[0] for n in el['notifications']])
                res = f"<span class='warning'>{res}</span>"
            else:
                comment = ''
            '''delay'''
            if not (el['landing_time']
                    or el['goal_time']) and el['last_time'] and rawtime - el[
                        'last_time'] > 120:  # 2 mins old
                if rawtime - el['last_time'] > 600:  # 10 minutes old
                    status = f"disconnected"
                else:
                    m, s = divmod(rawtime - el['last_time'], 60)
                    status = f"[{m:02d}:{s:02d} old]"
            time = sec_to_string(el['last_time'],
                                 offset) if el['last_time'] else ''
            p = dict(rank=idx,
                     id=el['ID'],
                     name=f"<span class='sex-{el['sex']}'>{el['name']}</span>",
                     sex=el['sex'],
                     result=res,
                     comment=comment,
                     time=time,
                     status=status)
            data.append(p)

        formatted['data'] = data

    return formatted
Ejemplo n.º 10
0
def get_fsdb_info(formula, form):
    formula.formula_name = form.get('id')
    '''scoring parameters'''
    # formula.comp_class = comp.comp_class
    formula.min_dist = 0 + float(
        form.get('min_dist')) * 1000  # min. distance, meters
    formula.nominal_dist = 0 + float(
        form.get('nom_dist')) * 1000  # nom. distance, meters
    formula.nominal_time = 0 + int(
        float(form.get('nom_time')) * 3600)  # nom. time, seconds
    formula.nominal_launch = 0 + float(
        form.get('nom_launch'))  # nom. launch, perc / 100
    formula.nominal_goal = 0 + float(
        form.get('nom_goal'))  # nom. goal, perc / 100
    formula.scoring_altitude = 'GPS' if form.get(
        'scoring_altitude') == 'GPS' else 'QNH'
    # print(f"min. dist.: {float(form.get('min_dist'))} - {formula.min_dist}")
    # print(f"nom. dist.: {float(form.get('nom_dist'))} - {formula.nominal_dist}")
    # print(f"Altitude.: {formula.scoring_altitude}")
    '''formula parameters'''
    # distance point: on, difficulty, off
    formula.formula_distance = (
        'difficulty' if form.get('use_difficulty_for_distance_points') == '1'
        else 'on' if form.get('use_distance_points') == '1' else 'off')
    # arrival points: position, time, off
    formula.formula_arrival = (
        'position' if form.get('use_arrival_position_points') == '1' else
        'time' if form.get('use_arrival_time_points') == '1' else 'off')
    # departure points: leadout, on, off
    formula.formula_departure = (
        'leadout' if form.get('use_leading_points') == '1' else
        'on' if form.get('use_departure_points') == '1' else 'off')
    # time points: on, off
    formula.formula_time = 'on' if form.get(
        'use_time_points') == '1' else 'off'
    # leading points factor: probably needs to be linked to GAP version
    formula.lead_factor = (None
                           if form.get('use_leading_points') == '0' else float(
                               form.get('leading_weight_factor') if form.
                               get('leading_weight_factor') else 1))
    '''tolerance'''
    formula.tolerance = 0.0 + float(
        form.get('turnpoint_radius_tolerance') if form.get(
            'turnpoint_radius_tolerance') else 0.001)  # tolerance, perc / 100
    '''stopped task parameters'''
    formula.validity_min_time = 0 + int(
        form.get('min_time_span_for_valid_task')
    ) * 60  # min. time for valid task, seconds
    formula.score_back_time = 0 + int(
        form.get('score_back_time')) * 60  # Scoreback Time, seconds
    formula.glide_bonus = 0.0 + float(form.get('bonus_gr'))  # glide ratio
    '''bonus and penalties'''
    formula.no_goal_penalty = c_round(
        1.0 - float(form.get('time_points_if_not_in_goal')), 4)
    formula.arr_alt_bonus = float(
        form.get('aatb_factor') if form.get('final_glide_decelerator') ==
        'aatb' else 0)
    '''jump the gun'''
    formula.max_JTG = int(form.get('jump_the_gun_max'))  # seconds
    formula.JTG_penalty_per_sec = (
        None if form.get('jump_the_gun_factor') == '0' else c_round(
            1 / float(form.get('jump_the_gun_factor')), 4))
    return formula