Example #1
0
    def __get_result(model, flight_field, **kw):
        subq = (
            DBSession.query(
                getattr(Flight, flight_field),
                func.count("*").label("count"),
                func.sum(Flight.index_score).label("total"),
            )
            .group_by(getattr(Flight, flight_field))
            .outerjoin(Flight.model)
        )

        if "year" in kw:
            try:
                year = int(kw["year"])
            except:
                raise HTTPBadRequest

            year_start = date(year, 1, 1)
            year_end = date(year, 12, 31)
            subq = subq.filter(Flight.date_local >= year_start).filter(Flight.date_local <= year_end)

        subq = subq.subquery()

        result = DBSession.query(
            model, subq.c.count, subq.c.total, over(func.rank(), order_by=desc("total")).label("rank")
        ).join((subq, getattr(subq.c, flight_field) == model.id))

        result = result.order_by(desc("total"))
        return result
Example #2
0
    def guess_model(self):
        from skylines.model.flight import Flight
        from skylines.model.model import Model

        # first try to find the reg number in the database
        if self.registration is not None:
            glider_reg = self.registration

            result = DBSession.query(Flight) \
                .filter(func.upper(Flight.registration) == func.upper(glider_reg)) \
                .order_by(desc(Flight.id)) \
                .first()

            if result and result.model_id:
                return result.model_id

        # try to find another flight with the same logger and use it's aircraft type
        if self.logger_id is not None \
            and self.logger_manufacturer_id is not None:
            logger_id = self.logger_id
            logger_manufacturer_id = self.logger_manufacturer_id

            result = DBSession.query(Flight).outerjoin(IGCFile) \
                .filter(func.upper(IGCFile.logger_manufacturer_id) == func.upper(logger_manufacturer_id)) \
                .filter(func.upper(IGCFile.logger_id) == func.upper(logger_id)) \
                .filter(Flight.model_id != None) \
                .order_by(desc(Flight.id))

            if self.logger_manufacturer_id.startswith('X'):
                result = result.filter(Flight.pilot == self.owner)

            result = result.first()

            if result and result.model_id:
                return result.model_id

        if self.model is not None:
            glider_type = self.model.lower()

            # otherwise, try to guess the glider model by the glider type igc header
            text_fragments = ['%{}%'.format(v) for v in re.sub(r'[^a-z]', ' ', glider_type).split()]
            digit_fragments = ['%{}%'.format(v) for v in re.sub(r'[^0-9]', ' ', glider_type).split()]

            if not text_fragments and not digit_fragments:
                return None

            glider_type_clean = re.sub(r'[^a-z0-9]', '', glider_type)

            result = DBSession.query(Model) \
                .filter(and_( \
                    func.regexp_replace(func.lower(Model.name), '[^a-z]', ' ').like(func.any(text_fragments)), \
                    func.regexp_replace(func.lower(Model.name), '[^0-9]', ' ').like(func.all(digit_fragments)))) \
                .order_by(func.levenshtein(func.regexp_replace(func.lower(Model.name), '[^a-z0-9]', ''), glider_type_clean))

            if result.first():
                return result.first().id

        # nothing found
        return None
Example #3
0
 def clubs(self):
     subq = DBSession.query(Flight.club_id,
                            func.count('*').label('count'),
                            func.sum(Flight.olc_plus_score).label('total')) \
            .group_by(Flight.club_id).subquery()
     result = DBSession.query(Club, subq.c.count, subq.c.total) \
              .join((subq, subq.c.club_id == Club.id))
     result = result.order_by(desc('total'))
     result = result.limit(20)
     return dict(tab='clubs', result=result)
Example #4
0
 def pilots(self):
     subq = DBSession.query(Flight.pilot_id,
                            func.count('*').label('count'),
                            func.sum(Flight.olc_plus_score).label('total')) \
            .group_by(Flight.pilot_id).subquery()
     result = DBSession.query(User, subq.c.count, subq.c.total) \
              .join((subq, subq.c.pilot_id == User.user_id))
     result = result.order_by(desc('total'))
     result = result.limit(20)
     return dict(tab='pilots', result=result)
Example #5
0
 def airports(self):
     subq = DBSession.query(Flight.takeoff_airport_id,
                            func.count('*').label('count'),
                            func.sum(Flight.olc_plus_score).label('total')) \
            .group_by(Flight.takeoff_airport_id).subquery()
     result = DBSession.query(Airport, subq.c.count, subq.c.total) \
              .join((subq, subq.c.takeoff_airport_id == Airport.id))
     result = result.order_by(desc('total'))
     result = result.limit(20)
     return dict(tab='airports', result=result)
Example #6
0
    def trafficRequestReceived(self, host, port, key, payload):
        if len(payload) != 8: return
        data = struct.unpack('!II', payload)

        pilot = User.by_tracking_key(key)
        if pilot is None:
            log.err("No such pilot: %d" % key)
            return

        flags = data[0]
        or_filters = []

        if flags & TRAFFIC_FLAG_FOLLOWEES:
            subq = DBSession.query(Follower.destination_id) \
                   .filter(Follower.source_id == pilot.id) \
                   .subquery()
            or_filters.append(TrackingFix.pilot_id.in_(subq))

        if flags & TRAFFIC_FLAG_CLUB:
            subq = DBSession.query(User.id) \
                   .filter(User.club_id == pilot.club_id) \
                   .subquery()
            or_filters.append(TrackingFix.pilot_id.in_(subq))

        if len(or_filters) == 0:
            return

        query = DBSession.query(TrackingFix) \
            .distinct(TrackingFix.pilot_id) \
            .filter(and_(TrackingFix.time >= datetime.datetime.utcnow() - datetime.timedelta(hours=2),
                         TrackingFix.pilot_id != pilot.id,
                         TrackingFix.location_wkt != None,
                         TrackingFix.altitude != None,
                         or_(*or_filters))) \
            .order_by(TrackingFix.pilot_id, desc(TrackingFix.time)) \
            .limit(32)

        response = ''
        count = 0
        for fix in query:
            location = fix.location
            if location is None: continue

            t = fix.time
            t = t.hour * 3600000 + t.minute * 60000 + t.second * 1000 + t.microsecond / 1000
            response += struct.pack('!IIiihHI', fix.pilot_id, t,
                                    int(location.latitude * 1000000),
                                    int(location.longitude * 1000000),
                                    int(fix.altitude), 0, 0)
            count += 1

        response = struct.pack('!HBBI', 0, 0, count, 0) + response
        response = struct.pack('!IHHQ', MAGIC, 0, TYPE_TRAFFIC_RESPONSE, 0) + response
        response = set_crc(response)
        self.transport.write(response, (host, port))
Example #7
0
    def get_last_year_statistics(self):
        query = DBSession.query(func.count('*').label('flights'),
                                func.sum(Flight.olc_classic_distance).label('distance'),
                                func.sum(Flight.duration).label('duration')) \
                         .filter(Flight.pilot == self.user) \
                         .filter(Flight.date_local > (date.today() - timedelta(days=365))) \
                         .first()

        last_year_statistics = dict(flights=0,
                                    distance=0,
                                    duration=timedelta(0),
                                    speed=0)

        if query and query.flights > 0:
            duration_seconds = query.duration.days * 24 * 3600 + query.duration.seconds

            if duration_seconds > 0:
                last_year_statistics['speed'] = float(query.distance) / duration_seconds

            last_year_statistics['flights'] = query.flights
            last_year_statistics['distance'] = query.distance
            last_year_statistics['duration'] = query.duration

            last_year_statistics['average_distance'] = query.distance / query.flights
            last_year_statistics['average_duration'] = query.duration / query.flights

        return last_year_statistics
Example #8
0
 def update_params(self, d):
     models = DBSession.query(Model) \
             .order_by(Model.name)
     options = [(None, '[unspecified]')] + \
               [(model.id, model) for model in models]
     d['options'] = options
     return SingleSelectField.update_params(self, d)
Example #9
0
 def get_optimised_contest_trace(self, contest_type, trace_type):
     from skylines.model.trace import Trace
     query = DBSession.query(Trace) \
                 .filter(Trace.contest_type == contest_type) \
                 .filter(Trace.trace_type == trace_type) \
                 .filter(Trace.flight == self).first()
     return query
Example #10
0
 def _my_update_params(self, d, nullable=False):
     query = DBSession.query(User.id, User.display_name) \
             .filter(User.club_id == request.identity['user'].club_id) \
             .order_by(User.display_name)
     options = [(None, 'None')] + query.all()
     d['options'] = options
     return d
Example #11
0
def remove_country(country_code):
    print "removing all entries for country_code " + country_code
    query = DBSession.query(Airspace) \
        .filter(Airspace.country_code == country_code)
    query.delete(synchronize_session=False)
    DBSession.flush()
    transaction.commit()
Example #12
0
def get_flight_path2(pilot, last_update = None):
    query = DBSession.query(TrackingFix)
    query = query.filter(and_(TrackingFix.pilot == pilot,
                              TrackingFix.location != None,
                              TrackingFix.altitude != None,
                              TrackingFix.time >= datetime.utcnow() - timedelta(hours=12)))
    if pilot.tracking_delay > 0 and not pilot.is_readable():
        query = query.filter(TrackingFix.time <= datetime.utcnow() - timedelta(minutes=pilot.tracking_delay))
    query = query.order_by(TrackingFix.time)

    start_fix = query.first()

    if not start_fix:
        return None

    start_time = start_fix.time.hour * 3600 + start_fix.time.minute * 60 + start_fix.time.second

    if last_update:
        query = query.filter(TrackingFix.time >= \
            start_fix.time + timedelta(seconds=(last_update - start_time)))

    result = []
    for fix in query:
        location = fix.location
        if location is None:
            continue

        time_delta = fix.time - start_fix.time
        time = start_time + time_delta.days * 86400 + time_delta.seconds

        result.append((time, location.latitude, location.longitude,
                       fix.altitude, fix.engine_noise_level))
    return result
Example #13
0
 def update_params(self, d):
     users = DBSession.query(User) \
             .filter(User.club_id == request.identity['user'].club_id) \
             .order_by(User.display_name)
     options = [(None, '[unspecified]')] + \
               [(user.id, user) for user in users]
     d['options'] = options
     return SingleSelectField.update_params(self, d)
Example #14
0
    def analysis(self):
        """Hidden method that restarts flight analysis."""

        for flight in DBSession.query(Flight):
            analyse_flight(flight)
            DBSession.flush()

        return redirect('/flights/')
Example #15
0
    def today(self, **kw):
        query = DBSession.query(Flight).filter(Flight.takeoff_time < datetime.utcnow())
        query = query.from_self(func.max(Flight.takeoff_time).label('date'))
        date = query.one().date
        if not date:
            raise HTTPNotFound

        return self.date(date, today = True, **kw)
Example #16
0
    def __get_result(model, flight_field):
        subq = (
            DBSession.query(
                getattr(Flight, flight_field),
                func.count("*").label("count"),
                func.sum(Flight.index_score).label("total"),
            )
            .group_by(getattr(Flight, flight_field))
            .outerjoin(Flight.model)
            .subquery()
        )

        result = DBSession.query(
            model, subq.c.count, subq.c.total, over(func.rank(), order_by=desc("total")).label("rank")
        ).join((subq, getattr(subq.c, flight_field) == model.id))

        result = result.order_by(desc("total"))
        return result
Example #17
0
    def by_location(cls, location, distance_threshold = 0.025):
        airport = DBSession.query(cls, functions.distance(cls.location_wkt, location.to_wkt()).label('distance'))\
            .order_by(functions.distance(cls.location_wkt, location.to_wkt())).first()

        if airport is not None and (distance_threshold is None or
                                    airport.distance < distance_threshold):
            return airport.Airport
        else:
            return None
Example #18
0
    def today(self, **kw):
        query = DBSession.query(func.max(Flight.date_local).label('date')) \
                         .filter(Flight.takeoff_time < datetime.utcnow())

        date = query.one().date
        if not date:
            date = datetime.utcnow()

        return self.date(date, today=True, **kw)
Example #19
0
def get_elevations(flight, encoder):
    # Prepare column expressions
    locations = Flight.locations.ST_DumpPoints()
    location_id = extract_array_item(locations.path, 1)
    location = locations.geom

    # Prepare subquery
    subq = DBSession.query(location_id.label('location_id'),
                           location.label('location')) \
                    .filter(Flight.id == flight.id).subquery()

    # Prepare column expressions
    timestamp = literal_column('timestamps[location_id]')
    elevation = Elevation.rast.ST_Value(subq.c.location)

    # Prepare main query
    q = DBSession.query(timestamp.label('timestamp'),
                        elevation.label('elevation')) \
                 .filter(and_(Flight.id == flight.id,
                              subq.c.location.ST_Intersects(Elevation.rast),
                              elevation != None)).all()

    if len(q) == 0:
        return [], []

    # Assemble elevation data
    elevations_t = []
    elevations_h = []

    start_time = q[0][0]
    start_midnight = start_time.replace(hour=0, minute=0, second=0, microsecond=0)

    for time, elevation in q:
        time_delta = time - start_midnight
        time = time_delta.days * 86400 + time_delta.seconds

        elevations_t.append(time)
        elevations_h.append(elevation)

    # Encode lists
    elevations_t = encoder.encodeList(elevations_t)
    elevations_h = encoder.encodeList(elevations_h)

    return elevations_t, elevations_h
Example #20
0
    def generate_keys(self):
        """Hidden method that generates missing tracking keys."""

        for user in DBSession.query(User):
            if user.tracking_key is None:
                user.generate_tracking_key()

        DBSession.flush()

        return redirect('/users/')
Example #21
0
def get_near_flights(flight, location, time, max_distance=1000):
    # calculate max_distance in degrees at the earth's sphere (approximate,
    # cutoff at +-85 deg)
    max_distance_deg = (max_distance / METERS_PER_DEGREE) / \
        math.cos(math.radians(min(abs(location.latitude), 85)))

    # the distance filter is geometric only, so max_distance must be given in
    # SRID units (which is degrees for WGS84). The filter will be more and more
    # inaccurate further to the poles. But it's a lot faster than the geograpic
    # filter...

    result = DBSession.query(Flight) \
        .filter(Flight.id != flight.id) \
        .filter(Flight.takeoff_time <= time) \
        .filter(Flight.landing_time >= time) \
        .filter(func.ST_DWithin(Flight.locations,
                                WKTElement(location.to_wkt(), srid=4326),
                                max_distance_deg))

    flights = []
    for flight in result:
        # find point closest to given time
        closest = min(range(len(flight.timestamps)),
                      key=lambda x: abs((flight.timestamps[x] - time).total_seconds()))

        trace = to_shape(flight.locations).coords

        if closest == 0 or closest == len(trace) - 1:
            point = trace[closest]
        else:
            # interpolate flight trace between two fixes
            next_smaller = closest if flight.timestamps[closest] < time else closest - 1
            next_larger = closest if flight.timestamps[closest] > time else closest + 1
            dx = (time - flight.timestamps[next_smaller]).total_seconds() / \
                 (flight.timestamps[next_larger] - flight.timestamps[next_smaller]).total_seconds()

            point_next = trace[closest]
            point_prev = trace[closest]

            point = [point_prev[0] + (point_next[0] - point_prev[0]) * dx,
                     point_prev[1] + (point_next[1] - point_prev[1]) * dx]

        point_distance = location.geographic_distance(
            Location(latitude=point[1], longitude=point[0]))

        if point_distance > max_distance:
            continue

        flights.append(flight)

        # limit to 5 flights
        if len(flights) == 5:
            break

    return flights
Example #22
0
    def index(self, **kw):
        subq = DBSession.query(TrackingFix,
                               over(func.rank(),
                                    partition_by=TrackingFix.pilot_id,
                                    order_by=desc(TrackingFix.time)).label('rank')) \
                .outerjoin(TrackingFix.pilot) \
                .filter(TrackingFix.time >= datetime.utcnow() - timedelta(hours=6)) \
                .filter(TrackingFix.location_wkt != None) \
                .subquery()

        query = DBSession.query(TrackingFix) \
                .filter(TrackingFix.id == subq.c.id) \
                .filter(subq.c.rank == 1) \
                .order_by(desc(TrackingFix.time))

        tracks = []
        for track in query.all():
            airport = Airport.by_location(track.location, None)
            distance = airport.distance(track.location)
            tracks.append([track, airport, distance])

        return dict(tracks=tracks)
Example #23
0
    def get_latest_fixes(self, max_age=timedelta(hours=6), **kw):
        row_number = over(func.row_number(),
                          partition_by=TrackingFix.pilot_id,
                          order_by=desc(TrackingFix.time))

        tracking_delay = cast(cast(User.tracking_delay, String) + ' minutes', Interval)

        subq = DBSession.query(TrackingFix.id,
                               row_number.label('row_number')) \
                .outerjoin(TrackingFix.pilot) \
                .filter(TrackingFix.time >= datetime.utcnow() - max_age) \
                .filter(TrackingFix.time <= datetime.utcnow() - tracking_delay) \
                .filter(TrackingFix.location_wkt != None) \
                .subquery()

        query = DBSession.query(TrackingFix) \
                .options(joinedload(TrackingFix.pilot)) \
                .filter(TrackingFix.id == subq.c.id) \
                .filter(subq.c.row_number == 1) \
                .order_by(desc(TrackingFix.time))

        return query
Example #24
0
    def create_pilot(self, email_address, display_name, **kw):
        if not self.club.is_writable():
            raise HTTPForbidden

        pilot = User(display_name=display_name,
                     email_address=email_address, club=self.club)
        DBSession.add(pilot)

        pilots = DBSession.query(Group).filter(Group.group_name == 'pilots').first()
        if pilots:
            pilots.users.append(pilot)

        redirect('pilots')
Example #25
0
    def select_pilot(self, pilot, co_pilot, **kwargs):
        if not self.flight.is_writable(request.identity):
            raise HTTPForbidden

        if self.flight.pilot_id != pilot:
            self.flight.pilot_id = pilot
            if pilot:
                self.flight.club_id = DBSession.query(User).get(pilot).club_id
        self.flight.co_pilot_id = co_pilot
        self.flight.time_modified = datetime.utcnow()
        DBSession.flush()

        redirect('.')
Example #26
0
    def igc_headers(self):
        """Hidden method that parses all missing IGC headers."""
        igc_files = DBSession.query(IGCFile)
        igc_files = igc_files.filter(or_(IGCFile.logger_manufacturer_id == None,
                                         IGCFile.logger_id == None,
                                         IGCFile.model == None,
                                         IGCFile.registration == None))

        for igc_file in igc_files:
            igc_file.update_igc_headers()

        DBSession.flush()

        return redirect('/flights/')
Example #27
0
    def update(self, **kw):
        flight_id_list = kw.get('flight_id')
        model_list = kw.get('model')
        registration_list = kw.get('registration')

        if not isinstance(flight_id_list, list):
            flight_id_list = [flight_id_list]

        if not isinstance(model_list, list):
            model_list = [model_list]

        if not isinstance(registration_list, list):
            registration_list = [registration_list]

        if flight_id_list is None \
            or len(flight_id_list) != len(model_list) \
            or len(flight_id_list) != len(registration_list):
            flash(_('Sorry, some error happened when updating your flight(s). Please contact a administrator for help.'), 'warning')
            return redirect('/flights/today')

        for index, id in enumerate(flight_id_list):
            try:
                id = int(id)
            except ValueError:
                continue

            try:
                model_id = int(model_list[index])
            except ValueError:
                model_id = None

            registration = registration_list[index]
            if registration is not None:
                registration = registration.strip()
                if not 0 < len(registration) < 32:
                    registration = None

            flight = DBSession.query(Flight).get(id)

            if not flight.is_writable():
                continue

            flight.model_id = model_id
            flight.registration = registration
            flight.time_modified = datetime.utcnow()

        DBSession.flush()

        flash(_('Your flight(s) have been successfully updated.'))
        return redirect('/flights/today')
Example #28
0
def get_requested_record(model, id):
    """Look up a record with the id (string) specified by a remote
    client.  Aborts the current request if the id is malformed or if
    the record does not exist."""

    try:
        id = int(id)
    except ValueError:
        raise HTTPNotFound

    record = DBSession.query(model).get(id)
    if record is None:
        raise HTTPNotFound
    return record
Example #29
0
    def new_post(self, display_name, club, email_address, password, **kw):
        if not club:
            club = None

        user = User(display_name=display_name, club_id=club,
                    email_address=email_address, password=password)
        user.created_ip = request.remote_addr
        user.generate_tracking_key()
        DBSession.add(user)

        pilots = DBSession.query(Group).filter(Group.group_name == 'pilots').first()
        if pilots:
            pilots.users.append(user)

        redirect('/')
Example #30
0
    def igc_headers(self, **kwargs):
        """Hidden method that parses all missing IGC headers."""
        igc_files = DBSession.query(IGCFile)
        igc_files = igc_files.filter(or_(IGCFile.logger_manufacturer_id is None,
                                         IGCFile.logger_id is None,
                                         IGCFile.model is None,
                                         IGCFile.registration is None,
                                         IGCFile.competition_id is None,
                                         IGCFile.date_utc is None))

        for igc_file in igc_files:
            igc_file.update_igc_headers()

        DBSession.flush()

        return redirect('.')